嵌入式开发从入门到入土

news2024/11/14 20:54:22

写在前面的话

嵌入式开发涉及的层面很广,它既有底层硬件的开发,又涉及上层应用的开发,也就是所谓的系统集成的硬件和软件。而C语言不仅具有汇编语言操作底层的优势,又具有高级开发语言的功能性强的特点,当之无愧地成为了嵌入式开发中的主流语言。

所以,”在STM32开发过程中,不论是基于寄存器开发还是基于库开发,深入理解和掌握嵌入式C语言的函数、指针、结构体,这是学习STM32的关键“

嵌入式为何物?

网上一搜,教材一翻,关于嵌入式的简介满天飞,分析的很专业,解释的很透彻,但是…看不懂

伟大的现代哲学家吕小布说过,所谓教材就是把一堆简单易懂的名词扩写成一堆谁也看不懂的句子。

“沿波讨源,虽幽必显”,嵌入式其实就在我们身边,一些小家电,电饭煲、热水壶、冰箱、空调、洗衣机等,在这些琳琅满目的家电里面有那么一块电路板,上面焊满了各式各样的电子元器件和芯片。如果这些家电需要带上一些**“智能化”**功能如按键、显示屏、定时、感应等功能,则需要加一个可编程芯片,这个芯片就是单片机,也是微控制器,是这个电路板的大脑,单片机编程,从某种意义来说就是嵌入式开发

STM32的数据类型

  • 数据是嵌入式中C语言的基本操作对象,数据类型指的是数据在计算机内的存储方式

一些基本类型如下图:

在这里插入图片描述

  • 由于不同CPU定义的数据类型的长度不同,因此ARM公司联合其他半导体厂商制定了统一的CMSIS 软件标准,这个标准中预先定义了相关的数据类型,ST公司也为开发人员提供了基于C语言的标准外设库 :
1	STM32定义的数据类型
CSTM功能
unsigned charuint8_t0~255
unsigned short intuint16_t0~65535
unsigned intuint32_t0 ~ (2^32) - 1
unsigned long longuint64_t0 ~ (2^64) - 1
signed charint8_t(-128) ~ (+127)
signed short intint16_t(-32768) ~ (+32767)
signed intint32_t(-2^31) ~ (+2^31) - 1
signed long longint64_t(-2^64) ~ (+2^64) - 1
2	STM32的IO类型限定词
IO类型限定词类型说明
_IVolatile const只读
_Ovolatile只写
_IOvolatile读写

C语言中常用的关键字

1. const

  • const关键字用于定义只读的变量,其值在编译时不能被改变,注意,const关键字定义的是变量而不是
  • 使用 const关键字是为了在编译时防止变量的值被误修改,同时提高程序的安全性可靠性,一般放在头文件中或者文件的开始部分
  • const关键字定义的变量是全局变量
  • const 关键字与#definc关键字存在区别,#define关键字只是简单的文本替换,而const关键字定义的变量是存储在静态存储器中的 。
  • 使用**#define**关键字定义常量的形式为
#define PI 3.14159  
/*使用该方式定义后,无论在何处使用PI,都会被预处理器以3.14159替代,
编译器不对PI进行类型检查,若使用不慎,则很可能由预处理引入错误,
且这类错误很难发现。*/

用const声明变量的方式虽然增加了分配空间,但可以很好地消除预处理引入的错误,并提供了良好的类型检查形式,保证安全性。

  • 利用 const关键字进行编程时需要注意以下三点 :

    • 使用const关键字声明的变量,只能读取,不能被赋值。 如:
    const uint8t sum = 3.14;
    uint8_t abs=0;
     
    ...
    sum= abs; //非法,将导致编译错误,因为sum 只能被读取,不能赋值
    abs- sum: //合法
    
    • const关键词修饰的变量在声明时必须初始化,上述语句表示 sum值是3.14,且sum值在编译时不能修改,若在编译过程中直接修改sum值,则编译器会提示出错。
    • 函数的形参声明为const,则意味着所传递的指针指向的内容只能读,不能被修改。如C语言的标准函数库中用于统计字符串长度的函数 int strlen(const char*str)。

2.static关键字

static关键字可以用来修饰变量,使用static关键字修饰的变量,称为静态变量。

  • 静态变量的存储方式与全局变量一样,都是静态存储方式

  • 全局变量的作用范围是整个源程序,当一个源程序由多个源文件组成时,全局变量在各个源文件中都是有效的

  • 即一个全局变量定义在某个源文件中,若想在另一个源文件中使用该全局变量,则只需要在该源文件中通过 extern关键字声明该全局变量就可以使用了

  • 若在该全局变量前加上关键字static,则该全局变量被定义成一个静态全局变量,其作用范围只在定义该变量的源文件内有效,其他源文件不能引用该全局变量,这样就避免了在其他源文件中因引用相同名字的变量而引发的错误,有利于模块化程序设计。

    • static关键字不仅可以用来修饰变量,而且可以用来修饰函数。模块化程序设计中,若用static声明一个函数,则该函数只能被该模块内的其他函数调用
      #include "stm32f1xx_hal .h”
      static void DMA_SetConfig (DMA_HandleTypeDef *hdma,uint32_t SrcAddress,uint32_t DstAddress, uint32_t DataLength);
...
      HAL_statusTypeDef HAL_DMA_start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
      HAL_StatusTypeDef status- HAL_OK;.... ...
      if(HAL_DMA_STATE_REA.DY m- hdma->state)
  {
        DMA_Setconfig(hdma, SrcAddress, DstAddress, DataLength);
       ... ...
  }
      ... ...
}

/*上述代码为DMA模块的源文件stm32f1xx_hal_dma.c,
若利用static将DMA_SetConfig()函数声明为一个静态函数,
则 DMA_SetConfig)函数只能被stm32flxx_hal_dma.c中的其他函数调用,
而不能被其他模块的文件使用,即定义了一个本地函数,
有效避免了因其他模块的文件定义了同名函数而引发的错误,
充分体现了程序的模块化设计思想*/
    • static除了用于定义静态全局变量,还用于定义静态局部变量,保证静态局部变量在调用过程中不被重新初始化。典型应用案例有实现计数统计功能。
void fun_count()
{
      static count_num=0;
      //声明一个静态局部变量,count_num用作计数器,初值为0
      count_num++;
      printf("%d\n",count_num) :
}
int main(void)
(
     int i=0;
     for( i=0;i<=5;i++)
  {
     fun_count();
  }
     return 0;
}
    
/*在main函数中每调用一次 fun_count()函数,静态局部变量count_num加1,
而不是每次都被初始化为初值0。*/

3.volatile关键字

volatile关键字,它是一个类型修饰符,含义为“易变的”

volatile char i;
/*使用volatile关键字定义了一个字符型的变量i,指出i是随时可能发生变化的,
每次使用该变量时都必须从i的地址中读取*/
  • 由于内存的读/写速度远不及CPU中寄存器的读/写速度
  • 为了提高数据信息的存取速度
    • 一方面在硬件上引入高速缓存Cache
    • 另一方面在软件上使用编译器对程序进行优化 – 将变量的值提前从内存读取到CPU的寄存器中,以后用到该变量时,直接从速度较快的寄存器中读取
  • 这样有利于提高运算速度,但同时也可能存在风险:
    • 如该变量在内存中的值有可能被程序的其他部分(如其他线程)修改或覆盖
    • 而寄存器中存放的仍是之前的值,这就导致应用程序读取的值和实际变量值不一致
    • 也有可能是寄存器中的值发生了改变,而内存中该变量的值没有被修改,同样也会导致不一致的情况发生
  • 为防止由于编译器对程序进行优化导致读取错误数据,使用 volatile关键词进行定义
  • 使用volatile关键字就是不让编译器进行优化,即每次读取或者修改值时,都必须重新从内存中读取或者修改,而不是使用保存在寄存器的备份。
  • 使用 volatile关键字定义变量后,该变量就不会因外因而发生变化了 :
    • 中断服务程序中修改的、供其他程序检测的变量需要使用volatile关键字
    • 多任务环境下各任务间共享的标志应添加 volatile关键字
    • 外设寄存器地址映射的硬件寄存器通常要用volatile关键字进行声明

4.extern关键字

extern关键字用于指明此函数或变量定义在其他文件中,提示编译器遇到此函数或变量时到其他模块中寻找其定义

extern关键字声明的函数或变量就可以在本模块或其他模块中使用,因此,使用extern关键字是一个声明而不是重新定义

extern int a;
/*第一条语句仅仅是变量a的声明,而不是定义变量a,并未为a分配内存空间,
变量a作为全局变量只能被定义一次*/
extern int  funA( ):
/*第二条语句声明函数funA(),此函数已在其他文件中定义*/

下期预告

今天简单介绍了嵌入式开发的几个方向和几个常见的关键字介绍,其实很多知识都是我从别的博主中的博客中看到的,然后进行一个搬运总结,下期继续回顾结构体等C语言常用类型

万事开头难,所有的领域在学习的初期都是一个从无到有的过程,独自探索这个过程无疑是非常枯燥且痛苦的,没有结果产出的喜悦,也没有醍醐灌顶的振奋。
慢慢来吧,先搞起来再说,希望在这个领域,能遇到许多不以山海为远的相知者,一起交流
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1244269.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript框架 Angular、React、Vue.js 的全栈解决方案比较

在 Web 开发领域&#xff0c;JavaScript 提供大量技术栈可供选择。其中最典型的三套组合&#xff0c;分别是 MERN、MEAN 和 MEVN。前端框架&#xff08;React、Angular 和 Vue&#xff09;进行简化比较。 MERN 技术栈详解 MERN 技术栈包含四大具体组件&#xff1a; MongoDB&am…

保姆级 Keras 实现 YOLO v3 一

保姆级 Keras 实现 YOLO v3 一 一. YOLO v3 总览二. 特征提取网络特征提取网络代码实现 三. 特征融合特征融合代码实现 四. 网络输出模型输出代码实现 五. 网络模型代码实现六. 代码下载 如果要给 YOLO 目标检测算法一个评价的话, 就是快和准, 现在已经到了 v8, 但是我为什么还…

前端环境变量释义process.env与import.meta.env

视频教程 彻底搞懂前端环境变量使用和原理&#xff0c;超清楚_哔哩哔哩_bilibili 添加命令行参数 --modexxxxx 新建.env.xxxx文件,其中.env文件会在所有环境下生效 以VITE_开头&#xff0c;字符串无需加双引号 使用import.meta.env.VITE_xxxxx进行调用

JavaScript基础—引入方式、注释和结束符、输入和输出、变量、常量、数据类型、检测数据类型、类型转换、综合案例—用户订单信息

版本说明 当前版本号[20231123]。 版本修改说明20231123初版 目录 文章目录 版本说明目录JavaScript 基础 - 第1天介绍引入方式内部方式外部形式 注释和结束符单行注释多行注释 结束符输入和输出输出输入 变量声明赋值变量初始化更新变量 关键字变量名命名规则 常量数据类型…

2023年11个最佳免费WordPress主题

如果您刚刚开始使用 WordPress&#xff0c;您可能会很自然地认为&#xff0c;只要免费的WordPress主题看起来像您想要的网站主题&#xff0c;那么它就很合适。不幸的是&#xff0c;事情并没有那么简单。这就是为什么在今天的文章中&#xff0c;我们概述了一份可靠的标准清单&am…

投资房产的理由与好处,投资买房的方法与技巧

一、教程描述 本套买房教程&#xff0c;大小2.15G&#xff0c;共有23个文件。 二、教程目录 00.她23岁北漂月薪600&#xff0c;7年后50万在京买了第一套房&#xff0c;如今身价上千万.mpg 01.这个游戏&#xff0c;有些人输了所有钱&#xff0c;一辈子也不明白这个道理.mpg …

脉冲幅度调制信号的功率谱计算

本篇文章是博主在通信等领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅解。文章分类在通信领域笔记&#xf…

Hibernate批量处理数据

概念&#xff1a; 批量处理数据是指在一个事务场景中处理大量数据。 在应用程序中难以避免进行批量操作&#xff0c;Hibernate提供了以下方式进行批量处理数据&#xff1a; (1)使用HQL进行批量操作 数据库层面 executeUpdate() (2)使用JDBC API进行批量操作 数据库层面 …

P6 C++控制流语句(continue, break, return)

前言 今天我们讲的是控制流语句&#xff0c;本期内容是上期课程的延续。 控制流语句一般与循环语句一起工作&#xff0c;它们让我们可以更好的控制这些循环的实际运行。 我们有三个主要的控制流语句可以使用&#xff0c;continue 、break 和 return&#xff0c;它们有不同的…

Nginx模块开发之http handler实现流量统计(1)

文章目录 一、handler简介二、Nginx handler模块开发2.1、示例代码2.2、编写config文件2.3、编译模块到Nginx源码中2.4、修改conf文件2.5、执行效果 三、Nginx的热更新总结 一、handler简介 Handler模块就是接受来自客户端的请求并产生输出的模块。 配置文件中使用location指令…

UML建模图文详解教程06——顺序图

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl本文参考资料&#xff1a;《UML面向对象分析、建模与设计&#xff08;第2版&#xff09;》吕云翔&#xff0c;赵天宇 著 顺序图概述 顺序图(sequence diagram&#xff0c;也…

docker安装以及idea访问docker

其他目录&#xff1a; docker 安装环境&#xff08;有空更新&#xff09; url “” docker 打包java包&#xff0c;并运行&#xff08;有空更新&#xff09; url “” docker 打包vue &#xff08;有空更新&#xff09; url “” docker 多服务 &#xff08;有空更新&#xff…

扩展外部eMMC存储

By Toradex胡珊逢 简介 存储器的嵌入式设备中扮演着重要角色&#xff0c;上面不仅安装有操作系统&#xff0c;同时也保存着应用程序和运行日志等。对于存储器如 eMMC&#xff0c;写入的数据量决定其使用寿命&#xff0c;对于有大量日志记录的应用&#xff0c;通常可以选用一个…

【Unity】接入MAX聚合广告SDK Applovin + GoogleAdmob

版本&#xff1a; Unity&#xff1a;2019.4.35f1gradle plugin: 4.2.0 &#xff08;实际要7.0 对应build_tools:34.0.0) gradle: 6.7.1 &#xff08;实际要7.0 对应build_tools:34.0.0) jdk: 1.8.0_241build_tools: 34.0.0 ndk: android-ndk-r19 文档&#xff1a; 6.0.1(Andro…

windows根据已有的安卓签名文件获取MD5签名

windows根据已有的安卓签名文件获取MD5签名 0 现状 uniapp 本机号码一键登录需要MD5的&#xff0c;现有的签名文件但是只有SHA1和SHA256 查看SHA1和SHA256 keytool -list -v -keystore [你的.keystore文件]1 前提 已有生成签名文件的环境 搭建Openssl环境&#xff0c;设置…

基于Springboot+Vue选课系统

选课系统要求 (1)数据库表&#xff1a;教师信息表、学生信息表、课程表、选课表 其中&#xff0c;教师信息表、学生信息表和选课表的数据需要提前设置&#xff0c;本题主要操作课程表 (2) 技术架构&#xff1a; 后台使用springboot 前端使用vue-admin-template (3) 考试时间&…

西米支付:如何设计和构建游戏支付系统?

如何设计和构建游戏支付系统&#xff1f; 目前&#xff0c;游戏开发中最常见的支付方式包括微信支付、支付宝支付和苹果支付等。今天&#xff0c;我将与大家分享游戏支付系统的架构和设计。 游戏支付的主要业务流程是指游戏玩家在游戏中购买虚拟物品或服务所进行的支付过程。一…

鸿蒙 ark ui 轮播图实现教程

前言&#xff1a; 各位同学有段时间没有见面 因为一直很忙所以就没有去更新博客。最近有在学习这个鸿蒙的ark ui开发 因为鸿蒙不是发布了一个鸿蒙next的测试版本 明年会启动纯血鸿蒙应用 所以我就想提前给大家写一些博客文章 效果图 具体实现 我们在鸿蒙的ark ui 里面列表使…

【jvm】虚拟机之堆

目录 一、堆的核心概述二、堆的内存细分&#xff08;按分代收集理论设计&#xff09;2.1 java7及以前2.2 java8及以后 三、堆内存大小3.1 说明3.2 参数设置3.3 默认大小3.4 手动设置3.5 jps3.6 jstat3.7 OutOfMemory举例 四、年轻代与老年代4.1 说明 五、对象分配过程5.1 说明5…

开源Flutter on Desktop项目-极扩安卓开发者工具

极扩-安卓开发者工具 他能干嘛 这个Flutter on Desktop桌面项目可以辅助你开发APP&#xff0c;支持分析一些运行数据以及操作APK安装等功能&#xff0c;甚至我还加入了Window安卓子系统的功能。 在它的帮助下&#xff0c;你可以快速查看当前正在运行的Activity&#xff0c;给你…