历史上的今天
返回首页

历史上的今天

今天是:2025年07月01日(星期二)

正在发生

2020年07月01日 | STM32学习之使用库函数编写串口通信

2020-07-01 来源:eefocus

注:使用的芯片是STM32F103ZET6


一、串口初始化部分的程序

1.初始化时钟

  因为要使用串口1这个外设,因此在使用之前就需要开启串口1的时钟,并且之后还需要设置IO输入输出的模式,在这里我们也需要开启GPIO的时钟。程序如下:


//初始化串口时钟

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);

 //初始化GPIO时钟

 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);


  可是为什么要初始化时钟呢在《STM32中文参考手册_V10》的RCC中有这样一句话“当外设时钟没有启用时,软件不能读出外设寄存器的数值,返回的数值始终是0x0。”,也就是只有开启了对应外设的时钟,才能操作外设。

  该部分解释参考如下文档:

https://blog.csdn.net/dp29sym41zygndvf/article/details/82321133


2. 初始化GPIO

  初始化GPIO就是设置使用端口的引脚、模式以及速度。因为使用的是串口1,所以在STM32F103ZET6芯片上USART_TX、USART_RX分别对应的引脚是PIOA.9和GPIOA.10。引脚复用的功能不同,对应引脚模式设置就不同,详细的可以参考《STM32中文参考手册_V10》的8.1.11,下表就是使用参考手册里的表21 USART。


这里是引用《STM32中文参考手册》里的表21

截取《STM32中文参考手册》里的图

  一般都设置串口的配置为全双工模式,因此设置GPIOA.9的模式为推挽复用输出,设置GPIOA.10的模式为浮空输入。引脚的速度没有太大的限制。该端程序如下:


GPIO_InitTypeDef GPIO_InitStruct;


//初始化GPIO

 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;  //GPIOA.9是USART1的TX

 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; //设置其模式为推挽复用输出

 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz; //速度为10MHz

 GPIO_Init(GPIOA,&GPIO_InitStruct);

 

 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;  //GPIOA.10是USART1的RX

 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置其模式为浮空输入

 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;  //速度为10MHz

 GPIO_Init(GPIOA,&GPIO_InitStruct);


3. 初始化串口

  初始化串口就是设置串口的停止位、奇偶校验位、字长、波特率、串口的模式以及硬件流控制。

   停止位:可以设置停止位为0.5个、1个、1.5个和2个停止位,当通常都设置1个停止位。

  字长:可以设置8个数据位或9个数据位。

  奇偶校验位:当设置有8个数据位时,就没有奇偶校验位;当设置有9个数据位时,第9位为奇偶校验位,以保证传送数据的准确性。如果设置为奇校验,如果前8个数据位中1的个数为奇数,则该位为0,如果为偶数,该位为1。若为偶校验,如果1的个数为偶数该位为0,为奇数该位为1。


  波特率:就是数据传输的速率,接收方的波特率要与发送方的波特率相同。

  串口的模式:设置发送使能和接受使能

  硬件流控制:这个只有在半双工时使用,一般不开启这个功能。

  该段程序如下:


USART_InitTypeDef USART_InitStruct;


//初始化串口

 USART_InitStruct.USART_BaudRate = 115200; //设置波特率 

 USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不使用这个

 USART_InitStruct.USART_Mode = (USART_Mode_Rx | USART_Mode_Tx);  //设置模式为即接受又发送

 USART_InitStruct.USART_Parity = USART_Parity_No;  //无奇偶校验位,也就是无第九位

 USART_InitStruct.USART_StopBits = USART_StopBits_1;  //1位停止位

 USART_InitStruct.USART_WordLength = USART_WordLength_8b; //8位数据位

 USART_Init(USART1,&USART_InitStruct);


4.串口使能

  之前都只是设置串口的一些配置,并没有使串口开始工作,因此我们要使能串口,需要调用USART_Cmd(USART_TypeDef* USARTx, FunctionalState NewState)这个函数,其最终是对控制寄存器1(USART_CR1)的位13的操作,如果该位为1,USART模块使能,若为0,禁止USART分频器和输出。


  该段程序如下:


//使能串口

 USART_Cmd(USART1,ENABLE);


  通常接受数据需要使用串口中断,而串口发送可以不使用串口中断。如果不需要开启串口中断,到这一步已经完成串口的初始化部分。如果需要用到串口中断,则再需要下面两个步骤。


5.初始化NVIC

  首先就是了解一下NVIC是什么,NVIC,就是Nested vectored interrupt controller,即嵌套向量中断控制器。


  在STM32F103ZET6芯片中有16个内核中断,60个可屏蔽中断,16个可编程中断优先级,怎么多中断怎么管理呢,这时候NVIC嵌套向量中断管理器就派上用场了。首先先对中断进行分组,如下表所示:


AIRCR[10:8] IP bit[7:4]分配情况 分配结果

0 111 0:4 0位抢占优先级,4位响应优先级

1 110 1:3 1位抢占优先级,3位响应优先级

2 101 2:2 2位抢占优先级,2位响应优先级

3 100 3:1 3位抢占优先级,1位响应优先级

4 011 4:0 4位抢占优先级,0位响应优先级

注:该表是参考正点原子第24讲 NVIC中断优先级管理的PPT


  这里所说的中断分组并不是说把各个中断分到了这几个组,而是说每一个组对应的抢占优先级和响应优先级的位数不同,根据自己需要多少位抢占优先级和几位响应优先级来设置,总共有4个位来控制。


  抢占优先级的讲解:抢占优先级高的中断可以打断抢占优先级低的中断,这就有点像51的中断优先级,0的时候抢占优先级最高。


  响应优先级的讲解:响应优先级高的不能打断响应优先级低的,只有在抢占优先级相同时起作用,当抢占优先级相同时,响应优先级高的,当和响应优先级低的中断相同时发生时,响应优先级高的中断先触发。


  上面说到总共有4个位来设置这两个优先级,因此24就为16,就有16级可编程中断优先级。

  举个例子:

  我要设置串口1的中断,其抢占优先级为2,响应优先级也为2。

  1.先设置中断分组。

  因为抢占优先级为2,则不能用组1,因为组1可设置的抢占优先级为0位,不可以设置,所以应该从组1到4选择,因为响应优先级为2,则不能用组4,组4的响应优先级没有分配位数,因此可以从组2到3选择,我选择组2。


  2.设置优先级。

  因为组2,抢占优先级分配2个位,响应优先级分配2个位,因此抢占优先级可以设置22个也就是4个优先级等级,响应优先级也是4个等级,即0到3。要设置抢占优先级为2,响应优先级也为2,把2写入NVIC_IP寄存器的位6和位7,设置抢占优先级;把2写入NVIC_IP寄存器的位4和位5,设置响应优先级优先级。


  在我们使用库函数编写程序时,void NVIC_PriorityGroupConfig(uint32_t NVIC_PriorityGroup);是进行中断分组,NVIC_Init(&NVIC_InitStruct);是对NVIC初始化,也就是设置抢占优先级,响应优先级,IRQ的串口通道打开和IRQ通道使能这四个参数。

  抢占优先级和响应优先级是几设置即就行。

  为什么要打开IRQ对应的串口1通道,因为IRQ是interrupt

request,即中断请求通道,也就是选择什么来触发中断,因为使用的是串口1,因此需要开启IRQ的串口1通道,选择使用串口1触发。使能串口1的IRQ通道就不用说了。

  该段程序如下:


NVIC_InitTypeDef NVIC_InitStruct;


//初始化NVIC(设置抢占优先级和响应优先级)

 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn;  //选择IRQ为USART1

 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能IRQ通道

 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2; //设置抢占优先级

 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2; //设置响应优先级

 NVIC_Init(&NVIC_InitStruct);  


  中断分组有关的库函数放在了主函数刚开始,没在在这部分程序中。


6.开启串口1中断

  在之前的步骤中把有关于串口的配置都配置好了,而这一步是设置串口1是通过什么触发中断的,比如是发送完成后触发中断还是接受到数据触发中断。在库函数中void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT, FunctionalState NewState);是开启串口1中断的,这个函数第二个形参就是设置串口是通过哪种方式触发中断的,一般情况下我们使用的是USART_IT_RXNE,就是设置当接收到数据触发中断。

  该段程序如下:


USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //设置接受到数据触发中断

  之前设置串口1的IRQ通道,只是设置了是通过串口1来触发中断,也就是中断源,但具体是由串口1的哪种方式来控制触发中断,就需要这一步设置。


  到此,串口初始化已经全部配置完成。


二、中断服务函数部分

  由于这个程序只是编写一个简单的串口收发,所以在中断服务函数部分就编写了收到什么数据就发送什么数据,程序如下:


void USART1_IRQHandler(){  //串口1中断服务函数

 u8 Recv;

 if(USART_GetITStatus(USART1,USART_IT_RXNE) != RESET){

  Recv = USART_ReceiveData(USART1);

  USART_SendData(USART1,Recv);

 }

}


  进入串口1的中断服务函数后,先通过调用USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)这个函数来判断是不是因为接收到数据而触发中断的,或许该奇怪了,之前明明设置的就是接收到数据后触发中断,为什么进中断服务函数还需要再判断,这是因为虽然选择中断的触发方式,但是可能是别的情况触发,下面引用《STM32中文参考手册_V10》25.4中断请求的话来解释一下:


  USART的各种中断事件被连接到同一个中断向量,有以下各种中断事件:

● 发送期间:发送完成、清除发送、发送数据寄存器空。

● 接收期间:空闲总线检测、溢出错误、接收数据寄存器非空、校验错误、 LIN断开符号检测、噪音标志(仅在多缓冲器通信)和帧错误(仅在多缓冲器通信)。

  如果设置了对应的使能控制位,这些事件就可以产生各自的中断 。通用同步异步收发器(USART)


  因此需要先判断是否为是对应的标志位置一而触发的中断,之后就是调用库函数中串口接收数据的函数,读出接受的数据,为了能看到现象,所以又调用库函数中串口发数据函数,将数据发出去,在电脑的串口小助手中就可以看到接收串口中的数据和发送框中数据一致。


三、主函数部分

  因为实现的功能比较简单,所以在主函数中主要调用初始化函数。主函数部分如下:


int main(){

   NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//中断分组

   Uart_Init(); //初始化串口


   while(1);


  刚开始是调用中断分组的函数,这部分讲解在初始化NVIC部分中解释了,之后就是调用初始化串口函数,这个函数是自己编写的不是库函数里的,这个函数就是包含上面第一部分串口初始化部分的程序中所有列出来的语句。然后就是使用while死循环,使程序一直跑下去。


  该篇文章是我学习正点原子STM32视频讲解之后的总结和自我理解,如果有什么不对的,还请各位指教。


参考资料

《STM32中文参考手册_V10》

《STM32F10xxx Cortex-M3编程手册》

《STM32F1开发指南(精英版)-库函数版本_V1.0》(正点原子)

STM32官方数据手册

推荐阅读

史海拾趣

Free2Move公司的发展小趣事

在电子行业中,Free2Move公司的发展故事虽不直接聚焦于传统电子制造或硬件设计,但其作为出行科技领域的创新者,与电子行业有着紧密的联系,尤其是在汽车电子、物联网(IoT)以及数据服务等方面。以下是五个与Free2Move公司发展相关的事实性故事:

1. 电动汽车生态系统的构建

Free2Move eSolutions,作为Stellantis和Engie EPS的合资企业,致力于电动汽车(EV)产品设计、开发、制造和分销的领先地位。它通过与全球科技企业的合作,如埃森哲,推动电动汽车接入电网,加速出行领域的全面电气化。这一举措不仅促进了电动汽车市场的增长,还带动了电动汽车充电基础设施、电池管理系统等电子相关产业的发展。(参考来源:埃森哲公司官网)

2. 远程信息处理与数据分析的集成

Free2Move与Guidepoint Systems合作,利用远程信息处理技术提升车队管理效率。Guidepoint Air数据监控服务能够接收来自符合条件的Stellantis车辆的数据,包括速度、位置、发动机状态等,为经销商、商业和政府车队提供库存管理和车队管理服务。这种数据驱动的解决方案依赖于先进的电子设备和物联网技术,实现了对车辆运营状态的实时监控和数据分析。(参考来源:百家号)

3. 商业车队解决方案的开发

Free2Move与Samsara的合作是另一个值得注意的案例。两家公司共同开发了一个集成解决方案,使Stellantis原厂远程信息处理设备的数据能够导入Samsara的互联运营云。这一合作让车队客户能够通过一个控制面板访问车辆的GPS定位、发动机工作小时数、燃料使用量和胎压等关键信息,从而提高了车队的运营效率和驾驶员的安全性。这一解决方案的成功实施,依赖于电子传感器、云计算和数据分析技术的深度融合。(参考来源:搜狐网)

4. 共享出行服务的全球扩展

Free2Move在全球范围内提供共享出行服务,包括共享汽车、停车位和充电站等。这一业务模式的成功,离不开电子支付系统、移动应用技术和物联网平台的支持。例如,在中国市场,Free2Move通过与当地合作伙伴的合作,推出了易微享共享汽车服务,为用户提供便捷的出行体验。这一过程中,电子支付、移动应用开发和物联网技术的运用,都是不可或缺的关键因素。(参考来源:雪球)

5. 医疗保健领域的跨界合作

虽然Free2Move的核心业务并非直接面向电子医疗行业,但其品牌名称“Free2Move”被另一家公司在医疗保健领域采用,推出了用于患者运动评估的技术系统。这一跨界合作展示了Free2Move品牌在不同领域的广泛影响力和创新能力。尽管这一故事并不直接涉及Free2Move公司的传统业务,但它反映了电子技术在不同行业间的渗透和融合趋势,以及品牌价值的多元化应用。(参考来源:爱迪斯通(北京)科技有限公司官网)

以上五个故事,从不同角度展示了Free2Move公司在电子行业中的发展和影响,体现了其在技术创新、数据服务、市场拓展等方面的综合实力。

安森德(Ascend)公司的发展小趣事

随着产品技术的成熟,安森德公司开始积极拓展市场。公司凭借优质的产品和服务,成功进入工业电源、电机驱动、消费电子等多个领域。同时,安森德积极寻求与全球顶尖企业的战略合作,通过与这些企业的技术交流和业务合作,不断提升自身的技术水平和市场竞争力。这些合作不仅为安森德带来了更多的商业机会,也进一步提升了公司在行业内的知名度和影响力。

CONTTEK Group GmbH公司的发展小趣事

CONTTEK Group GmbH公司注重企业文化的建设和团队精神的培养。公司倡导“以人为本、创新驱动”的企业文化,鼓励员工积极参与创新活动,发挥个人潜能。同时,公司还注重团队建设,通过定期的培训和团建活动活动,增强员工的凝聚力和向心力。这种积极向上的企业文化和团结协作的团队精神,为公司的持续发展提供了强大的动力。

这五个故事展示了CONTTEK Group GmbH公司在电子行业中的发展历程和取得的成就。从创立初期的艰难起步到技术创新、市场拓展、品质管理和企业文化建设的不断推进,CONTTEK Group GmbH公司始终保持着积极进取的精神和不断创新的态度,在电子连接器领域取得了显著的成绩。

Abbotec Incorporated公司的发展小趣事

Abbotec深知人才是企业发展的核心。因此,公司一直注重人才培养和团队建设。公司定期举办各种培训活动,提升员工的专业技能和管理能力。同时,Abbotec还积极引进外部优秀人才,为公司的发展注入新的活力。

Hind Rectifiers Ltd公司的发展小趣事

Abbotec深知人才是企业发展的核心。因此,公司一直注重人才培养和团队建设。公司定期举办各种培训活动,提升员工的专业技能和管理能力。同时,Abbotec还积极引进外部优秀人才,为公司的发展注入新的活力。

Cogent_Computer_Systems公司的发展小趣事

在电子行业中,技术创新是企业发展的核心驱动力。Cogent_Computer_Systems公司深知这一点,因此始终坚持将大量资金投入研发领域。公司建立了一支高素质的研发团队,并配备了先进的研发设备。通过持续不断的研发投入,公司成功推出了一系列具有创新性的产品,满足了市场不断变化的需求。这种以研发驱动的发展模式使得公司在激烈的市场竞争中始终保持领先地位。

问答坊 | AI 解惑

如何消除启动中这个错误!

s3c6410平台。 [OAL] --OEMInit() [FMD] FMD_OEMIoControl() : IOCTL_FMD_GET_INTERFACE: [FMD] ++FMD_Init() **** [FMD:INF] FMD_Init() : Read ID = 0x0000ecda [FMD] FMD_Init() : NUM_OF_BLOCKS = 2048 [FMD] FMD_Init() : PAGES_PER_BLO ...…

查看全部问答>

求助,并口驱动,协商模式!

我参照PARPROT.SYS开发了一个PCI转并口的驱动,但是我不知道该怎么样通过协商改变并口的模式 我想从默认模式(SPP)协商成EPP/ECP模式,该怎么来操作? 最好能详细一点,谢谢!!!…

查看全部问答>

有一项目,想干私活的进来

本公司有一个涉及到485通讯和蓝牙模拟串口通讯的项目,想找一位能独立画板,独立开发的人来完成。 居住地要求在南京。 电话:1 3 9 5 1 0 3 8 6 8 3…

查看全部问答>

从U盘启动vxworks和从硬盘启动差不多吗?

U盘可以看作硬盘么?在修改config.h文件时,是不是将fd改成ata就行了,其他步骤和硬盘启动一样?? 生成bootrom时是压缩形式还是不压缩形式呢? 如果不一样,还要怎么修改呢…

查看全部问答>

LM324 与单片机的接法

做了个驱动小车.需直流电机带动轮子转动.想请问下.LM324与直流电机的接法!…

查看全部问答>

【求助】430与pc机通信的问题

能否用5V的MAX232作为430的电平转换电路,430 与 MAX232 引脚之间 直接相连可以吗?…

查看全部问答>

IAR MCS-51 8.10过期无法使用了!买得多少钱啊?

IAR MCS-51 8.10申请的30天试用版,还没有到30天就不能用了。用重新申请的key,重新安装也不能用,好吧,我ghost一下系统,不插网线,再次安装,用新申请的key还是不能用。好郁闷啊!…

查看全部问答>

请问谁有在uIP中使用TFTP的相关程序?

请问谁有在uIP中使用TFTP的相关程序?小弟不胜感激!…

查看全部问答>

求指导如何选择单片机和步进电机

我们在做一个本科生创新基金项目,项目中要用到单片机控制步进电机转动 刚刚开始做,我们也在网上查了很多资料,但是还是不是特别了解各器件的性能和要求,具体的价位只能在淘宝上看到 我们的项目要求:单片机我们准备选择52S系列的单片机(待定 ...…

查看全部问答>