历史上的今天
返回首页

历史上的今天

今天是:2025年02月28日(星期五)

正在发生

2020年02月28日 | STM32 嵌入式学习入门(0)——C语言基础复习

2020-02-28 来源:eefocus

摘要


    主要介绍了嵌入式编程中几个常用,但软件编程中用得不是很多的C语言知识。包括位操作、条件编译、结构体和结构体指针、typedef声明类型、以及extern变量声明、static关键字等内容。


   本文并没有将相关C语言知识点介绍地很详细,毕竟这么多知识点要想掌握绝对不是看几篇文档就能掌握的。因此博主建议,如果上述的C语言知识掌握得还不是很好的话,找一本C语言的书好好研究研究。尤其是结构体和结构体指针、还有函数的知识(本文没提到),一定要很熟练。


    本文除了简要介绍C语言知识,也结合博主自己的感受简单谈了各个知识点用在了嵌入式编程的什么地方,有不详细和描述不准确的地方欢迎大家留言讨论。


    要想学习STM32,C语言的基础是必须的。除了最基本的C语言的语法,如循环、判断、数组、结构体、函数、指针这些软件编程常用的知识外,还包括位操作、条件编译、结构体指针、typedef声明类型、以及extern变量声明、static关键字等常用内容。这里结合实际代码分析一下这些知识点,如果想完整系统地了解这些C语言知识,大家可以翻翻C语言教材,比如《C Primer Plus》(第六版)这本书,尤其对于位操作的知识讲得很详细。


一、位操作:

位操作简单说就是指对基本类型变量可以在位级别进行操作。下面先看几种位操作符:


& 按位与 ~ 取反

| 按位或 << 左移

^ 按位异或 >> 右移

 

掌握了这六种操作否的用法,C语言的位操作就差不多了。这六种操作符的解释如下:


1. & 按位与: 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0。//   1&1 = 1   1&0 = 0   0&1 = 0   0&0 = 0


2.|按位或:两个相应的二进制位中只要有一个为1,该位的结果值为1。//   1|1 = 1   0|1 = 1   1|0 = 1   0|0 = 0 


3.^按位异或: 若参加运算的两个二进制位值相同则为0,否则为1。//   1^1 = 0   0^1 = 1   1^0 = 1   0^0 = 0


4.!取反:  对一个二进制数按位取反,即将0变1,将1变0。//    1! = 0    0! = 1


5.<<左移:用来将一个数的各二进制位全部左移N位,右补0。//   00001100 << 2 = 00110000


6.>>右移:将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0。//   00001100 >> 2 = 00000011


下面介绍一些用寄存器开发STM32时候实用的位操作技巧:


1)不改变其他位的值的状况下,对某几个位进行设值。

这个场景单片机开发中经常使用,方法就是先对需要设置的位用 & 操作符进行清零操作,然后用 | 操作符设值。比如我要改变GPIOA的状态,可以先对寄存器的值进行 & 清零操作

然后再与需要设置的值进行 | (或运算)。


GPIOA->CRL&=0XFFFFFF0F; //将第 4-7 位清 0

GPIOA->CRL|=0X00000040; //设置相应位的值,不改变其他位的值 (将CRL寄存器第7位设置为1)


2)取反操作使用技巧

SR 寄存器的每一位都代表一个状态,某个时刻我们希望去设置某一位的值为 0,同时其他位都保留为 1,简单的作法是直接给寄存器设置一个值:

TIMx->SR=0xFFF7;

这样的做法设置第3位为0,但是这样的作法同样不好看,并且可读性很差。看看库函数代码中怎样使用的:

TIMx->SR = (uint16_t)~TIM_FLAG;


而 TIM_FLAG 是通过宏定义定义的值:

#define TIM_FLAG_Update ((uint16_t)0x0001)

#define TIM_FLAG_CC1 ((uint16_t)0x0002)

看这个应该很容易明白,可以直接从宏定义中看出 TIM_FLAG_Update 就是设置的第 0 位了,可读性非常强。


注:在STM32的开发中,更多的时间可能会直接使用官方的库函数,库函数实际上是将复杂的寄存器封装了一下。使用库函数可以避免复杂的位操作,使代码更具有可读性,但同样的项目,使用库函数其代码量可能会比直接通过操作寄存器写出来的工程的代码量稍微多一点,执行效率可能会稍微低一点,当然这只是一点点…………


学习STM32的时候要从寄存器上去理解原理,理解实现过程,但是如果真的需要做一个嵌入式项目,可能用库函数去开发比较方便,效率更好一点,这是博主自己的感受和观点。


二、条件编译:

单片机程序开发过程中,经常会遇到一种情况, 当满足某条件时对一组语句进行编译,而当条件不满足时则编译另一组语句。 条件编译命令最常见的形式为:


#ifdef 标识符

程序段 1

#else

程序段 2

#endif

它的作用是:当标识符已经被定义过(一般是用#define 命令定义),则对程序段 1 进行编译,否则编译程序段 2。 其中#else 部分也可以没有,即:


#ifdef

程序段 1

#endif

这个条件编译在 MDK 里面是用得很多的,在 stm32f10x.h 这个头文件中经常会看到这样的语句:


#ifdef STM32F10X_HD

大容量芯片需要的一些变量定义

#end

而 STM32F10X_HD 则是我们通过#define 来定义的。


条件编译理解起来也不是很困难,可以类比于C语言中的 if-else 语句去理解。条件编译在STM32的开发中还是比较常用的。自己写代码写 .h 文件的时候开头会用到。此外就是要能看懂库函数里面的条件编译了。


三、结构体和结构体指针:

结构体是C语言中的基础知识,同时结构体和结构指针也是STM32开发中非常重要的东西,尤其在使用库函数的时候,库函数中很多函数的入口参数中都有结构体指针,所以如果我们要调用这种函数,就先在主调函数中声明一个结构体变量,然后对这个结构体变量的各个成员赋值,最后再调用相关函数,调用的时候看清楚函数原型,入口参数是结构体类型还是结构体指针,不要搞错了。这里再多说两句,这里的结构体每个成员可以赋的值往往都是通过枚举或者宏定义确定好的,不能自己乱写,而应该去查找宏定义部分的代码,选定需要的那个枚举字面值作为结构体相关成员的值。


关于结构体和结构体指针的例子可以看GPIO的初始化,这里就不再多说了:STM32 GPIO的介绍


四、typedef声明类型:

如果学过数据结构,相信对typedef也不陌生。用typedef的一个好处就是使代码的可读性更高,写代码也更方便。typedef 在代码中用得最多的就是定义结构体的类型别名和枚举类型了。


struct _GPIO

{

__IO uint32_t CRL;

__IO uint32_t CRH;

};

定义了一个结构体 GPIO,这样我们定义变量的方式为:


struct _GPIO GPIOA;//定义结构体变量 GPIOA

但是这样很繁琐, MDK 中有很多这样的结构体变量需要定义。这里我们可以为结体定义一个别名 GPIO_TypeDef,这样我们就可以在其他地方通过别名 GPIO_TypeDef 来定义结构体变量了。方法如下:


typedef struct

{

__IO uint32_t CRL;

__IO uint32_t CRH;

} GPIO_TypeDef;

Typedef 为结构体定义一个别名 GPIO_TypeDef,这样我们可以通过 GPIO_TypeDef 来定义结构体变量:


GPIO_TypeDef GPIOA,GPIOB;

 

这里的 GPIO_TypeDef 就跟 struct _GPIO 是等同的作用了。 这样是不是方便很多? 


除了用在结构体上,typedef类型别名也大量用在int、short等这种变量上, 所以写STM32代码的时候几乎就不会出现类似于定义int型变量这样的语句,全部用 u8、u16这样的量代替了,比如u16代表的就是一个无符号的16位整型数据(这一个描述可能有一点偏差)。


五、extern关键字:

C 语言中 extern 可以置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。这里面要注意,对于 extern 申明变量可以多次,但定义只有一次。在我们的代码中你会看到看到这样的语句:


extern u16 USART_RX_STA;

这个语句是申明 USART_RX_STA 变量在其他文件中已经定义了,在这里要使用到。所以,你肯定可以找到在某个地方有变量定义的语句:


u16 USART_RX_STA;


嗯,extern关键字,说实话,博主自己写代码确实没用过。So……

推荐阅读

史海拾趣

Automatic Connector公司的发展小趣事

为了保持技术创新的活力,Automatic Connector公司积极与高校和研究机构开展产学研合作。通过与这些机构的深度合作,公司能够及时了解最新的科研成果和技术趋势,为产品的研发和创新提供有力的支持。同时,公司还为合作机构提供实践平台和技术支持,实现了资源共享和互利共赢。这种产学研合作的模式为Automatic Connector公司的创新发展注入了强大的动力。

这五个故事虽然是以虚构的Automatic Connector公司为背景,但它们所反映的电子连接器制造企业的发展规律和市场环境是真实存在的。希望这些故事能够为您了解电子行业中的企业发展提供一些启示。

CML公司的发展小趣事

随着电子行业的快速发展,CML意识到只有不断创新才能在激烈的市场竞争中立于不败之地。于是,公司加大了对研发的投入,积极引进先进的技术和设备,不断提升产品的性能和质量。经过多年的努力,CML成功开发出了一系列具有自主知识产权的半导体产品,不仅在国内市场占据了领先地位,还成功打入国际市场,赢得了全球客户的信赖和好评。

ETI Systems公司的发展小趣事

ETI Systems深知人才是企业发展的核心竞争力。因此,公司一直注重人才培养和引进工作。通过建立完善的人才培养机制和激励机制,ETI Systems吸引了一批具有丰富经验和专业技能的优秀人才加入公司。同时,公司也积极为员工提供广阔的发展空间和良好的工作环境,让员工能够充分发挥自己的才能和创造力。这种重视人才的企业文化,为ETI Systems的长期发展提供了有力的人才保障。

CAMBION公司的发展小趣事

在追求经济效益的同时,CAMBION公司也注重可持续发展和社会责任。公司积极推广环保理念,采用环保材料和节能技术生产电子产品。此外,CAMBION还关注社会公益事业,通过捐款、设立奖学金等方式支持教育事业和弱势群体。这些举措不仅提升了公司的社会形象,也为公司的长期发展奠定了坚实基础。

以上五个故事是基于电子行业的一般发展趋势和可能面临的挑战而构想的,它们并不特指CAMBION公司的实际发展经历。如需了解CAMBION公司的真实故事,建议查阅相关新闻报道、行业报告或公司官方资料。

德索五金(dosinconn)公司的发展小趣事

发展历程:2016年,公司荣获国家高新技术企业认证,并累计获得了30余项专利。这些荣誉的获得不仅彰显了公司在技术创新方面的实力,也为企业赢得了更多的市场机会。

成果与影响:技术沉淀和荣誉的获得使德索五金电子在连接器制造领域树立了良好的品牌形象,也为公司的长远发展提供了坚实的技术支持。

以上五个故事框架简要概述了德索五金电子在电子行业中的发展历程和关键成就。每个故事都突出了公司在不同阶段的发展重点和取得的成果,为读者提供了关于德索五金电子成长历程的全面了解。

Gigarams Semiconductor Device Corp公司的发展小趣事
这可能是由于控制算法复杂或系统响应速度不足导致的。解决方案包括简化控制算法、提高系统响应速度或采用更高效的控制策略。

问答坊 | AI 解惑

NVR与DVR比较

dvr即是digital video recorder(也叫: personal video recorder 即pvr)——数字视频录像机或数字硬盘录像机,我们习惯上称为硬盘录像机。     它是一套进行图像存储处理的计算机系统,具有对图像/语音进行长时间录像、录音、远程监视和 ...…

查看全部问答>

按键控制74HC595显示0-999

/******************************************************************** //  KEY0---->清零 //  KEY1--->个位递增 //  KEY2--->十位递增 //  KEY3--->百位递增。…

查看全部问答>

数模转换芯片的GND接数字地还是模拟地?

我用的是BB的DAC7512,只有一个VDD和一个GND,但不知道该接数字地还是模拟地?电源地又是属于哪个地?…

查看全部问答>

我可以解决芯片的焊接问题

我可以焊接芯片CP2102,我觉得是件很容易的事,如果谁需要焊接,我很乐意帮忙。我的QQ;724791682       724791682@qq.com…

查看全部问答>

关于双机热备技术

  双机热备技术起源于国外,国外大都是双机热备软件,都是很成熟的了。我用的是双机MCU的系统,也应该属于双机热备?   请问:国外双机MCU的系统应用的现状如何?   …

查看全部问答>

有关jlink

想玩一玩S3C2440, 请问: 1. 一定需要jlink或ulink吗? 2.看网上卖jlink从100元至1200元不等,真正功能上有区别么? 谢了 …

查看全部问答>

DMA传输数据的问题

DMA传输数据64K时,目的空间每包前一部分(4K左右)是后一包的数据,后一部分是前一包的数据(60K), 比如我第i包全是2,第i+1全是3,我看到的第i+1数据如下(很有规律): 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 ...…

查看全部问答>

变频器的正常使用及故障维修

一、正确使用变频器应注意事项 1、环境温度对变频器的使用寿命有很大的影响。环境温度每升10℃,则变频器寿命减半,所以周围环境温度及变频器散热的问题一定要解决好。 2、正确的接线及参数设置。在安装变频器之前一定要熟读其手册,掌握其用法、 ...…

查看全部问答>

选型前咨询:STM8敢上吗?

现在又回到8位机做一个低成本的东东,STM8敢选吗? 有使用经历的朋友诚恳介绍下吧! 谢谢了!…

查看全部问答>

pi闭环控制技术

pi闭环控制技术是什么技术呀?它的原理是什么呀?我在网上收索了pi,但相关资源太少了。我还是不懂。所以就到了论坛里问问。…

查看全部问答>