




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
实验5——串口通信卓越工程师培养系列本书获深圳大学教材出版资助STM32F1开发标准教程01实验内容实验内容每秒通过printf向计算机发送一句话(ASCII格式),如ThisisthefirstSTM32F103Project,byZhangsan,在计算机上通过串口助手显示。另外,计算机上的串口助手向STM32核心板发送1字节数据(hex格式)STM32核心板收到之后,进行加1处理再回发到计算机,通过串口助手显示出来。比如,计算机通过串口助手向STM32核心板发送0x13,STM32核心板收到之后,进行加1处理,向计算机发送0x14。基于STM32核心板设计一个串口通信实验02实验原理1.UART电路原理图串口通信实验涉及的硬件包括一个XH-6P底座(编号为J4)两个100Ω限流电阻及一个10kΩ上拉电阻,STM32核心板上的USART1TX通过一个100Ω电阻连接到STM32F103RCT6芯片的PA9,USART1RX通过一个100Ω电阻连接到芯片的PA10。STM32核心板通过XH-6P底座与通信-下模块相连接,STM32核心板的数据发送线USART1_TX与通信-下载模块的数据接收线相连,STM32核心板的数据接收线USART1_RX与通信-下载模块的数据发送线相连。STM32核心板的GND必须和通信-下载模块的GND相连接。通信-下载模块通过XH-6P底座向STM32提供5V电源,因此,只需要将J4的5V、USART1_RX、USART1_TX、GND与通信-下载模块相连就可以实现两者之间的通信,NRST和BOOTO主要是配合USARTI_RX和USART1_TX,在不手动重启STM32核心板的前提下,将程序下载到STM32F103RCT6芯片。串口硬件电路如图6-1所示。2.UART通信协议UART是异步串行全双工通信,因此UART通信没有时钟线,而有两根数据线可以实现双向同时传输。收发数据只能一位一位地在各自的数据线上传输,所以UART最多只有两根数据线,一根发送数据线,一根接收数据线。数据线是高低逻辑电平传输,因此还必须有参照的地线,最简单的UART接口由发送数据线TXD、接收数据线RXD和GND共3根线组成。UART一般采用TTL/CMOS的逻辑电平标准表示数据,逻辑1用高电平表示,逻辑0用低电平表示。比如,在TTL电平标准中,逻辑1用5V表示,逻辑0用0V表示;在CMOS电平标准中,逻辑1的电平接近于电源电平,逻辑0的电平接近于OV。1.UART物理层2.UART通信协议两个UART设备的连接非常简单,比如UART设备A和UART设备B只需要将UART设备A的发送数据线TXD与UART设备B的接收数据线RXD相连接将UART设备A的接收数据线RXD与UART设备B的发送数据线TXD相连接,当然,两个UART设备必须共地,因此,还需要将两个设备的GND相连接,如图6-2所示。1.UART物理层2.UART通信协议UART数据按照一定的格式打包成帧,微控制器或计算机在物理层上以帧为单位进行传输。UART的一数据由起始位、数据位、校验位、停止位和空闲位组成,如图6-3所示。需要说明的是,一个完整的UART数据必须有起始位数据位和停止位,但是不一定有校验位和空闲位。2.UART数据格式2.UART通信协议(1)起始位长度为1位,起始位的逻辑电平为低电平。由于UART空闲状态时的电平为高电平,因此,UART在每一个数据帧的开始,需要先发出一个逻辑0,表示传输开始。(2)数据位长度通常为8位,也可以为9位,每个数据位的值可以为逻辑0也可以为逻辑1,而且传输采用的是小端方式,即最低位(D0)在前,最高位(D7)在后。2.UART数据格式2.UART通信协议(3)校验位不是必需项,因此可以将UART配置为没有校验位,即不对数据位进行校验,也可以将UART配置为带奇偶校验位。如果配置为带奇偶校验位,则校验位的长度为1位校验位的值可以为逻辑0也可以为逻辑1。在奇校验模式下,如果数据位中的逻辑1是奇数个,则校验位为0;如果数据位中的逻辑1是偶数个,则校验位为1。在偶校验模式下,如果数据位中的逻辑1是奇数个,则校验位为1;如果数据位中的逻辑1是偶数个则校验位为0。(4)停止位长度可以是1位、1.5位或2位,但是,通常情况下停止位都是1位。停止位是一帧数据的结束标志,起始位是低电平,因此,停止位为高电平。(5)空闲位是数据传输完毕后,线路上保持的逻辑1电平,也就是线路上当前没有数据传输。2.UART数据格式2.UART通信协议UART传输速率用比特率来表示。比特率是每秒传输的二进制位数,单位为bps(bitpeisecond)。波特率,即每秒传送码元的个数,单位为baud。由于UART使用NRZ(Non-ReturrtoZero,不归零)编码因此UART的波特率和比特率是相同的。在实际应用中常用的UART传输速率有1200、2400、4800、9600、19200、38400、57600和115200。如果数据位为8位,校验为奇校验,停止位为1位,波特率为115200,计算每2ms最多可以发送多少字节数据。首先,通过计算可知一数据有11位(1位起始位+8位数据位+1位校验位+1位停止位),其次,波特率为115200即每秒传输115200bit,那ms可以传输115.2bit,由于每数据有11位,因此每ms就可以传输10字节数据2ms就可以传输20字节数据。3.UART传输速率2.UART通信协议综上所述,UART是以为单位进行数据传输的。一个UART数据由1位起始位、5~9位数据位、0位/1位校验位、1位/15位/2位停止位组成。除了起始位外,其他三部分必须在通信前由通信双方设定好,即通信前必须确定数据位和停止位的位数,以及校验方式。当然,波特率也必须在通信前设定好。这就相当于两个人通过电话交谈之前,要先设定好交谈使用的语言,否则,一方使用英语、另外一方使用中文,就无法进行有效交流。3.UART传输速率2.UART通信协议由于UART是异步串行通信,没有时钟线只有数据线。那么拿到一个UART原始波形如何确定一帧数据?如何计算传输的是什么数据呢?下面以一个UART形为例进行讲解假设UART波特率为115200,数据位为8位,无奇偶校验位,停止位为1位。如图6-4所示,第1步获取UART原始波形数据;第2步按照波特率进行中值采样,每一bit的时间宽度为1/115200(s),大约868μs,将电平第一次由高到低的转换点作为基准点,即0us时刻,4.34μs时刻采样第1个点,再过8.68μs,即13.02μs时刻采样第2个点,依次类推,采样第3、4、5、6、7、8、9个点,然后判断第10个采样点是否为高电平,如果为高电平,表示完成一帧数据的采样;4.UART通信实例3.UART功能框图图6-5所示是UART的功能框图,下面依次介绍UART的功能引脚、数据寄存器、控制器和波特率发生器。3.UART功能框图STM32的UART功能引脚包括TX、RX、SWRX、RTS、nCTS和SCLK。本书中涉及串口的实验仅用到了TX和RX,TX是发送数据输出引脚,RX是接收数据输入引脚。表6-1取自《STM32芯片手册(英文版)-STM32F103C-STM32F103xD-STM32F103xE》,包含所有UART的TX和RX引脚信息。1.功能引脚3.UART功能框图STM32核心板上的芯片型号是STM32F103RCT6,该芯片包含5个UART,分别是USART1、USART2、USART3、UART4和UART5,其中,USART1的时钟来源于APB2总线时钟,APB2总线时钟最大频率为72MHzUSART2、USART3UART4和UART5的时钟来源于APB1总线时钟,APB1总线时钟最大频率为36MHz。USART1、USART2、USART3相比UART4和UART5增加了同步传输功能。1.功能引脚3.UART功能框图UART的数据寄存器(USARTDR)只有低9位有效,该寄存器在物理上由两个寄存器组成,分别是发送数据寄存器(TDR)和接收数据寄存器(RDR)。UART执行发送操作(号操作)即向USARTDR写数据实际上是将数据写入TDR;UART执行接收操作(读操作),即读取USARTDR中的数据,实际上是读取RDR中的数据。写数据到TDR之后,UART控制器会将数据转移到发送移位寄存器,然后由发送移位寄存器一位一位地通过TX引脚发送出去。通过RX引脚接收到的数据,按照顺序保存在接收移位寄存器,然后UART控制器会将接收移位寄存器中的数据转移到RDR。2.数据寄存器3.UART功能框图UART的控制器包括发送器控制、接收器控制、唤醒单元、校验控制和中断控制等,这里重点介绍发送器控制和接收器控制。使用UART之前需要向USARTCR1的UE写入1使能UART,通过向USARTCR1的M写入0或1可以将UART传输数据的长度设置为8位或9位,通过USARTCR2的STOPT1:0],可以将UART的停止位配置为0.5个1个15个或2个。3.控制器3.UART功能框图1)发送器控制向USARTCR1的TE写入1,即可启动数据发送,发送移位寄存器的数据会按照一帧数据格式(起始位+数据+可选的奇偶校验位+停止位)通过TX引脚一位一位输出,一数据的最后一位发送完成且TXE为1时,USARTSR的TC将由硬件置为1表示数据传输完成,此时如果USARTCR1的TCIE为1,则产生中断。在发送过程中,除了发送完成(TC=1)可以产生中断,发送寄存器为空(TXE=1)也可以产生中断,即TDR中的数据被硬件转移到发送移位寄存器时,TXE将被硬件置位,此时,如果USARTCR1的TXEIE为1,则产生中断。3.控制器3.UART功能框图2)接收器控制向USARTCR1的RE写入1,即可启动数据接收,当UART控制器在RX引脚侦测到起始位时,就会按照配置的波特率,将RX引脚上读取到的高低电平(对应逻辑1或0)依次存放在接收移位寄存器。当接收到一顿数据的最后一位,即停止位时,接收移位寄存器中的数据将会被转移到USARTDR,USARTSR的RXNE将由硬件置为1表示数据接收完成。此时,如果USARTCR1的RXNEIE为1,则产生中断。3.控制器3.UART功能框图接收器和发送器的波特率由波特率发生器控制,用户只需要向波特率寄存器(USARTBRR)写入不同的值,就可以控制波特率发生器输出不同的波特率。USARTBRR由整数部分DIVMantissa[11:0]和小数部分DIVFraction[3:0]组成,如图6-6所示。4.波特率发生器3.UART功能框图DIVMantissa[11:0]是UART分频器除法因子(USARTDIV)的整数部分,DIVFraction[3:0]是USARTDIV的小数部分,接收器和发送器的波特率计算公式如下所示:公式中的ƒck是外设的时钟(PCLK1用于USART2、USART3UART4UART5,PCLK2用于USART1),USARTDIV是一个无符号定点数,这16位的值设置在USARTBRR。4.波特率发生器3.UART功能框图写USARTBRR之后,波特率计数器会被波特率寄存器中的新值替换。因此,不能在通信进行中改变波特率寄存器的数值。由于USARTBRR取值范围的限制,一些常用的波特率与将USARTBRR的值代入公式得到的实际波特率并不都是严格相等的,差计算如表6-2所示。4.波特率发生器4.UART部分寄存器USARTSR的结构、偏移地址和复位值如图6-7所示,对部位的解释说明如表6-3所示。1.状态寄存器(USARTSR)4.UART部分寄存器1.状态寄存器(USARTSR)4.UART部分寄存器USARTDR的结构、偏移地址和复位值如图6-8所示,对部分位的解释说明如表6-4所示。2.数据寄存器(USARTDR)4.UART部分寄存器2.数据寄存器(USARTDR)4.UART部分寄存器USARTBRR的结构、偏移地址和复位值如图6-9所示,对部分位的解释说明如表6-5所示。3.波特率寄存器(USARTBRR)4.UART部分寄存器3.波特率寄存器(USARTBRR)4.UART部分寄存器USARTCR1的结构、偏移地址和复位值如图6-10所示,对部分位的解释说明如表6-6所示。4控制寄存器1(USART_CR1)4.UART部分寄存器4控制寄存器1(USART_CR1)4.UART部分寄存器USARTCR2的结构偏移地址和复位值如图6-11所示对部分位的解释说明如表6-7所示。5.控制寄存器2(USART_CR2)4.UART部分寄存器5.控制寄存器2(USART_CR2)4.UART部分寄存器USARTCR3的结构偏移地址和复位值如图6-12所示,对部分位的解释说明如表6-8所示。6.控制寄存器3(USART_CR3)5.UART部分固件库函数USARTImit函数的功能是初始化UART,包括选定指定的串口,设定串口的数据传输速率、数据位数、校验方式、停止位、流量控制方式等,通过向USARTX-BRR、USARTx一CR1、USARTx一CR2和USARTx-CR3写入参数实现。具体描述如表6-9所示。1.USART_Init5.UART部分固件库函数USARTInitTypeDef结构体定义在stm32f10xusart.h文件中,内容如下:1.USART_Init5.UART部分固件库函数(1)参数USARTBaudRate用于设置USART传输的波特率波特率计算公式如下所示:(2)参数USARTWordLength用于定义一顿数据中的数据位数可取值如表6-10所示。1.USART_Init5.UART部分固件库函数(3)参数USART_StopBits用于定义发送的停止位位数,可取值如表6-11所示。(4)参数USART_Parity用于定义奇检验模式,可取值如表6-12所。1.USART_Init5.UART部分固件库函数(5)参数USART_HardwareFlowControl用于使能或除能指定硬件流控制模式,可取值如表6-13所示。(6)参数USART_Mode用于指定使能或除能发送和接收模式,可取值如表6-14所示。1.USART_Init5.UART部分固件库函数USART_Cmd函数的功能是使能/除能UART,通过向USARTx→CR1写入参数来实现具体描述如表6-15所示。2.USART_Cmd5.UART部分固件库函数USART_ITConfig函数的功能是使能/除能UART中断,通过向USARTx→CR3写入参数来实现。具体描述如表6-16所示。3.USART_ITConfig5.UART部分固件库函数参数USART_IT是待使能或除能的USART中断源,可取值如表6-17所示。3.USART_ITConfig5.UART部分固件库函数USART_SendData函数的功能是发送数据通过向USARTX→DR写入参数来实现。具体描述如表6-18所示。4.USART_SendData5.UART部分固件库函数USART_ReceiveData函数的功能是读取接收到的数据通过读取USARTX→DR来实现具体描述如表6-19所示。5.USART_ReceiveData5.UART部分固件库函数USART_GetFlagStatus函数的功能是检查UART标志位设置与否,通过读取USARTx→SR来实现。具体描述如表6-20所示。6.USART_GetFlagStatus5.UART部分固件库函数参数USART_FLAG为待检查的USART标志位,可取值如表6-21所示。6.USART_GetFlagStatus5.UART部分固件库函数USART_ClearFlag函数的功能是清除UART的待处理标志位通过向USARTx→SR写入参数来实现。具体描述如表6-22所示。7.USART_ClearFlag5.UART部分固件库函数USARTGetITStatus函数的功能是检查指定的USART中断发生与否,通过读取并判断USARTx→CR1和USARTx→SR来实现。具体描述如表6-23所示。8.USART_GetITStatus6.STM32异常和中断中断是主机与外设进行数据通信的重要机制,它负责处理处理器外部的异常事件;异常实质上也是一种中断,只不过它主要负责处理处理器内部事件。处理器复位或异常退出时为线程模式(ThreadMode),出现中断或异常时会进入处理模式(HandlerMode),处理模式下所有代码为特权访问。1.中断和异常2.线程模式和处理模式6.STM32异常和中断Cortex-M3在内核水平上搭载了一个异常响应系统支持为数众多的系统异常和外部中断。其中,编号为1~15的对应系统异常,如表6-24所示,编号>16的对应外部中断,如表6-25所示。除了个别异常的优先级不能被修改,其他异常优先级都可以通过编程进行修改。3.Cortex-M3的异常和中断6.STM32异常和中断由于芯片设计厂商(如ST公司可以修改Cortex-M3的硬件描述源代码,因此不同的芯片设计厂商可以根据产品定位对表6-24和表6-25进行调整。比如,STM32大容量产品将编号从-15~-1的向量定义为系统异常,将编号从0~59的向量定义为外部中断,如表6-26所示。其中,优先级为-15、-14和-13的系统异常,如复位(Reset)不可屏中断(NMI)、硬件失效(HardFault),优先级是固定的,其他异常和中断的优先级可以通过编程修改。表6-26所示的STM32大容量产品向量表中的中断号在stm32f10x.h文件中定义,各中断号对应的中断服务函数名定义可以在启动文件startupstm32f10xhds中查找到。4.STM32的异常和中断6.STM32异常和中断4.STM32的异常和中断7.NVIC中断控制器通过表6-26可以看到,STM32的系统异常多达10个,而外部中断多达60个,那如何管理这么多的异常和中断呢?ARM公司专门设计了一个功能强大的中断控制器NVIC(NestedVectoredInterruptController)。NVIC与CPU紧密合,它还包含了若干系统控制寄存器。NVIC采用向量中断的机制,在中断发生时,会自动取出对应的服务例程入口地址,并且直接调用,无须软件判定中断源,这样就可以大大缩短中断延时。8.NVIC部分寄存器中断的使能与除能分别使用各自的寄存器来控制,这与传统的、使用单一位的两个状态来表达使能与除能截然不同。Cortex-M3中有240对使能位/除能位,每个中断拥有一对,这240个对子分布在8对32位寄存器中(最后一对只用了一半)。STM32虽然没有240个中断但是在固件库设计时,依然预留了8对32位寄存器(最后一对同样只用了一半),分别是8个32位中断使能寄存器(NVIC-ISER[O]NVIC-ISERI7)和8个32位中断除能寄存器(NVICICER0~NVIC-ICER71),如表6-27所示。1.中断的使能与除能寄存器(NVIC→ISER/NVIC→ICER)8.NVIC部分寄存器如果便能一个中断,需要与1到NVIC→ISER的对应位:如果除能一个中断,需要写1到NVIC→ICER的对应位如果向NVIC→ISER或NVIC→ICER中写则不会有任何效果,写0无效是个非常关键的设计理念,通过这种方式,使能/除能中断时只需要把当事位写成1,其他的位可以全部为0。再也不用像以前那样,害怕有些位被写入0而破坏其对应的中断设置(现在写0没有效果),从而实现每个中断都可以自顾自地设置而互不影响,用户只需单一地写指令,不再需要“读-改-写”三部曲。基于Cortex-M3内核的微控制器并不是都有240个中断,因此,只有该微控制器实现的中断,其对应的寄存器相应位才有意义。STM32的异常和中断向量表如表6-26所示。1.中断的使能与除能寄存器(NVIC→ISER/NVIC→ICER)8.NVIC部分寄存器如果中断发生时,正在处理同级或高优先级异常,或被掩蔽,则中断不能立即得到响应,此时中断被挂起。中断的挂起状态可以通过中断的挂起寄存器(ISPR)和清除寄存器(ICPR)来读取还可以通过写ISPR来手工挂起中断STM32的固件库同样预留了8对32位寄存器分别是8个32位中断的挂起寄存器(NVIC→ISPRTO~NVIC→ISPRI7)和8个32位中断的清除寄存器(NVIC→ICPR[O]~NVIC→ICPR[7]),如表6-28所示。2中断的挂起与清除寄存器(NVIC→ISPR/NVIC→ICPR)8.NVIC部分寄存器每个外部中断都有一个对应的优先级寄存器,每个优先级寄存器占用8位,但是Cortex-M3在最粗线条的情况下,只使用最高4位4个相的优先级寄存器拼成一个32位寄存器。如前所述,根据优先级组的设置,优先级可以被分为高、低两个位段,分别是抢占优先级和子优先级。优先级寄存器都可以按字节访问,当然也可以按半字/字来访问。STM32的固件库预留了240个8位中断优先级寄存器(NVIC→IP[O]~NVIC→IP[239]),如表6-29所示。3中断优先级寄存器(NVIC→IP)8.NVIC部分寄存器STM32固件库中的中断优先级寄存器NVIC→IPTO]~NVIC→IPT2391与240个中断一一对应,每个中断的中断优先级寄存器NVIC→IP[x]都由高4位和低4位组成,高4位用于设置优先级,低4位未使用,如表6-30所示。3中断优先级寄存器(NVIC→IP)8.NVIC部分寄存器每个外部中断都有一个活动状态位。在处理器执行了其中断服务函数的第1条指令后,它的活动位就被置为1,并且直到中断服务函数返回时才由硬件清零。由于支持嵌套,允许高优先级异常抢占某个中断。然而,哪怕中断被抢占,其活动状态也依然为1。活动状态寄存器的定义,与前面讲的使能/除能和挂起/清除寄存器相同,只是不再成对出现。它们也能按字/半字/字节访问,但它们是只读的。STM32的固件库预留了8个32位中断活动状态寄存器(NVIC→IABR[O]~NVIC→IABR[71),如表6-32所示。4.活动状态寄存器(NVIC→IABR)9.NVIC部分固件库函数NVIC_Init函数的功能是初始化NVIC,包括使能或除能指定的IRQ通道,设置成员NVIC_IRQChannel中的抢占优先级和子优先级,通过向NVIC→IP、NVIC→ISER和NVIC→ICER写入参数来实现。具体描述如表6-33所示。1.NVIC_Init9.NVIC部分固件库函数NVIC_ImitTypeDef结构体定义在misch文件中,内容如下:1.NVIC_Init9.NVIC部分固件库函数(1)参数NVICIRQChannel用于使能或除能指定的IRQ通道,可取值如表6-34所示。1.NVIC_Init9.NVIC部分固件库函数(2)参数NVIC_IROChannelPreemptionPriority用于设置成员NVIC_IROChanmel的抢占优先级,可取值如表6-35所示。(3)参数NVIC_IROChannelSubPriority用于设置成员NVIC_IRQChannel的子优先级可取值如表6-35所示。1.NVIC_Init9.NVIC部分固件库函数如果优先级分组是NVIC_PriorityGroup_0,则参数NVC_IROChannelPreemptionPriority对中新通道的设置不产生影响:如果优先级分组是NVIC_PriorityGroup_4,则参数NVIC_IRQChannelSubPriority对中断通道的设置不产生影响。(4)参数NVIC_IROChannelCmd用于使能或除能指定成员NVIC_IROChannel中定义的IRQ通道,可取值为ENABLE或DISABLE。1.NVIC_Init9.NVIC部分固件库函数NVIC_PriorityGroupConfig函数的功能是设置优先级分组位长度,通过SCB→AIRCR写入参数来实现。具体描述如表6-36所示。2.NVIC_PriorityGroupConfig9.NVIC部分固件库函数参数NVIC_PriorityGroup用于设置优先级分组位长度,可取值如表6-37所示。2.NVIC_PriorityGroupConfig9.NVIC部分固件库函数NVIC_ClearPendingIRQ函数的功能是清除中断的挂起通过向NVIC→ICPR写入参数来实现。具体描述如表6-38所示。3.NVIC_ClearPendinglRQ10.UART1模块驱动设计队列是一种先入先出(FirstInFirstOutFIFO)的线性表,它只允许在表的一端插入元素,在另一端取出元素。这和我们日常生活中的排队是一致的,最早进入队列的元素最早离开。在队列中,允许插入的一端叫作队尾(rear),允许取出的一端叫作队头(front)。有时为了方便,将顺序队列臆造为一个环状的空间,称为循环队列。1.队列与循环队列10.UART1模块驱动设计串口通信实验会使用到Queue模块,该模块有6个API函数,分别是InitQueueClearQueue.QueueEmpty、QueueLength、EnQueue和DeQueue,下面对这6个API函数进行讲解。1)InitQueueInitQueue函数的功能是初始化Queue模块,具体描述如表6-39所示。2.循环队列Queue模块函数10.UART1模块驱动设计2)ClearOueueClearQueue函数的功能是清除队列,具体描述如表6-40所示。该函数将pQue→front、pQue→rear、pQue→elemNum赋值为0。2.循环队列Queue模块函数10.UART1模块驱动设计3)QueueEmptyQueueEmpty函数的功能是判断队列是否为空,具体描述如表6-41所示。如果pQue→elemNum为0,表示队列为空,pQue→elemNum不为0,表示队列不为空。2.循环队列Queue模块函数10.UART1模块驱动设计4)QueueLengthQueueLength函数的功能是判断队列是否为空,具体描述如表6-42所示。该函数的返回值为pQue→elemNum,即队列中元素的个数。2.循环队列Queue模块函数10.UART1模块驱动设计5)EnOueueEnQueue函数的功能是插入len个元素(存放在起始地址为pImput的存储区中到队列具体描述如表6-43所示。每次插入一个元素,pQue→rear自增,当pQue→rear的值大于或等于数据缓冲区的长度pQue→bufLen时,pQue→rear赋值为0。需要注意的是,当数据缓冲区中的元素数量加上新写入的元素数量超过缓冲区的长度时,缓冲区只能接收缓冲区中已有的元素数量加上新写入的元素数量,再减去缓冲区的容量,即EnQueue函数对于超出的元素采取不理睬的态度。2.循环队列Queue模块函数10.UART1模块驱动设计6)DeOueueDeQueue函数的功能是从队列中取出len个元素,放入起始地址为pOutput的存储区,具体描述如表6-44所示。每次取出一个元素,pQue→front自增,当pQue→font的值大于或等于数据缓冲区的长度pQue→bufLen时,pQue→front赋值为0。需要注意的是,从队列中提取元素的前提是队列中需要至少有一个元素,当期望取出的元素数量le小于或等于队列中元素的数量时,可以按期望取出len个元素,否则,只能取出队列中已有的所有元素。2.循环队列Queue模块函数10.UART1模块驱动设计本实验中的UART1模块包含串口发送缓冲区和串口接收缓冲区,这两个缓冲区均为结构体,UART1的数据接收和发送过程如图6-15所示。3.UART1数据接收和数据发送路径10.UART1模块驱动设计数据发送过程(写串口)分为三步:①调用WriteUART1函数将待发送的数据通过EnQueue函数写入发送缓冲区,同时开启中断使能;②当发送数据寄存器为空时,会产生中断,在UART模块的USART1_IROHandler中断服务函数中,通过UART的ReadSendBuf函数调用DeOueue函数取出发送缓冲区中的数据再通过USART_SendData函数将待发送的数据写入发送数据寄存器(TDR);③STM32的硬件会将TDR中的数据写入发送移位寄存器,然后按位将发送移位寄存器中的数据通过TX端口发送出去。3.UART1数据接收和数据发送路径10.UART1模块驱动设计数据接收过程(读串口)正好与写串口过程相反,但也分为三步:①DSTM32的接收移位寄存器在接收到一帧数据时,会由硬件将接收移位寄存器的数据发送到接收数据寄存器(RDR),同时产生中断;②在UART模块的USART1_IRQHandler中断服务函数中,通过USART_ReceiveData函数读取RDR,并通过UART的WriteReceiveBuf函数调用EnQueue函数将接收到的数据写入接收缓冲区;③调用UART的ReadUART1函数读取接收到的数据。3.UART1数据接收和数据发送路径10.UART1模块驱动设计UART在微控制器领域,除了用于数据传输,还可以作为调试工具,对微控制器系统进行调试。读者在学习C语言的时候都使用过标准库函数printf,在控制台输出各种调试信息。STM32微控制器的集成开发环境,如KeilIAR等也同样支持标准库函数,本书基于Kei集成开发环境“实验1-F103基准工程”中已经涉及printf并且printf输出的内容通过UART1发送到计算机上的串口助手显示。那printf如何通过UART1输出信息呢?原来fputc是printf的底层函数,因此我们只需要对fputc进行改写即可。在UART1.c文件中,fputc调用SendCharUsedByFputc函数,如程序清单6-1所示。4.printf实现过程10.UART1模块驱动设计而SendCharUsedByFputc又进一步调用USART_SendData函数,该函数通过向USART1_DR写数据,实现基于UART1的信息输出,如程序清单6-2所示。4.printf实现过程03实验步骤步骤1:首先,将“D:STM32KeilTestMaterial05串口通信实验”文件夹复制到“D:STM32KeilTest\Product”文件夹中。然后,双击运行“D:STM32KeilTestProduct05串口通信实验Project'文件夹中的STM32KeilPrjuvprojx,单击工具栏中的酒图标。当BuildOutput栏出现FromELF:creatinghexfle...时表示已经成功生成hex文件出现0Error(s)0Warning()表示编译成功。最后,将axf文件下载到STM32的内部Flash,观察STM32核心板上的两个LED是否交替闪烁。由于本实验实现的是串口通信功能,因此,Material提供的“05.串口通信实验”工程中UART1模块中的UART1文件对是空白的读者也就无法通过计算机上的串口助手软件查看串口输出的信息,不过,UART1模块中的Queue文件对是完整的。如果两个LED交替闪烁,表示原始工程是正确的,接着就可以进入下一步操作。复制并编译原始工程步骤2:首先,将“D:STM32KeilTest\Productl05串口通信实验HWUART1”文件夹中的UART1c和Oueue.c添加到HW分组,具体操作可参见2.3节步骤8。然后,将“D:STM32KeilTestProduct05串口通信实验HWUART1”路径添加到IncludePaths栏,具体操作可参见23节步骤11。添加UART1和Queue文件对步骤3:单击
按钮进行编译,编译结束后,在Project面板中,双击UART1c下的UART1.h。在UART1h文件的“包含头文件”区,添加代码#includestdioh>和#include"DataTypeh"然后,在UART1.h文件的“宏定义”区添加缓冲区大小宏定义代码,如程序清单6-3所示。完善UART1.h文件步骤3:在UART1.h文件的“API函数声明”区添加如程序清单6-4所示的API函数声明代码InitUART1函数用于初始化UART1模块,WriteART1函数的功能是写串口,可以写若干字节,ReadUART1函数的功能是读串口,可以读若干字节。完善UART1.h文件步骤4:在UART1c文件的“包含头文件”区的最后,添加代码#include"stm32f10xconfh"和#include"Oueue.h"。在UART1c文件的“举结构体定义”区,添加如程序清单6-5所示的举定义代码枚举EnumUARTState中的UARTSTATEOFF表示串口关闭,对应的值为0UARTSTATEON表示串口打开,对应的值为1。完善UART1.c文件步骤4:在UART1.c文件的“内部变量”区,添加内部变量的定义代码,如程序清单6-6所示。s_structUARTSendCirQue是口发送缓冲区,s_structUARTRecCirOue是串口接收缓冲区,s_arrSendBuf是发送缓冲区的数组,s_arRecBuf是接收缓冲区的数组,s_iUARTTxSt是串口发送状态位,s_iUARTTxSts为1表示口正在发送数据,为0表示口发送数据完成。完善UART1.c文件步骤4:在UART1.c文件的“内部函数声明”区,添加内部函数的声明代码,如程序清单6-7所示。ImitUARTBuf函数用于初始化串口缓冲区,WriteReceiveBuf函数用于将接收到的数据写入接收缓冲区,ReadSendBuf函数用于读取发送缓冲区中的数据ConfigUART函数用于配置UART,EnableUARTTx函数用于使能串口发送,SendCharUsedByFputc函数用于发送字符该函数专门由fputc函数调用。完善UART1.c文件步骤4:在UART1.c文件的“内部函数实现”区,添加ItUARTBuf函数的实现代码,如程序清单6-8所示。在InitUARTBuf函数中,主要是对发送缓冲区s_structUARTSendCirQue和接收缓冲区s_structUARTRecCirQue进行初始化,将发送缓冲区中的s_arSendBuf数组和接收缓冲区中的s_arrRecBuf数组全部清零,同时,将两个缓冲区的容量均配置为宏定义UART1_BUF_SIZE。完善UART1.c文件步骤4:在UART1.c文件的“内部函数实现”区,在InitUARTBuf函数实现区的后面添加WriteReceiveBuf和ReadSendBuf函数的实现代码,如程序清单6-9所示。WriteReceiveBuf函数调用EnOueue函数,将数据写入接收缓冲区s_structUARTRecCirQue,ReadSendBuf函数调用DeQueue函数,读取发送缓冲区s_structUARTSendCirQue中的数据。完善UART1.c文件步骤4:完善UART1.c文件在ReadSendBuf函数实现区的后面添加ConfgUART函数的实现代码,如程序清单6-10所示。下面按照顺序对ConfgUART函数中的语句进行解释说明。(1)UART1通过PA9引脚发送数据,通过PA10引脚接收数据,因此,需要通过RCC_APB2PeriphClockCmd函数使能USART和GPIOA的时钟。(2)PA9引脚是UART1的发送端,PA10引脚是UART1的接收端,因此,需要通过GPIO_Imit函数将PA9配置为复用推挽输出模式将PA10配置为浮空输入模式然后,将I/0的最大输出速度配置为50MHz。(3)通过USART_StructInit函数USART_IitStruct的成员变量赋初值,将USART_BaudRate赋值为9600,USART_WordLength赋值为USART_WordLength8b,USART_StopBits赋值为USART_StopBits1USART_Parity赋值为USART_Parity_NoUSARTMode赋值为USART_Mode_Rx|USART_Mode_Tx,USART_HardwareFlowControl赋值为USART_HardwareFlowControl_None.在UART1.c文件的“内部函数实现”区步骤4:完善UART1.c文件(4)通过USARTInit函数配置USART1,该函数不涉及USARTCR1的M、PCEPS、TE和RE,以及USARTCR2的STOPT1:0和USARTCR3的CTSERTSE,还涉及USARTBRR。M用于设置UART传输数据的长度,PCE用于使能或除能校验控制,PS用于选择采用偶校验还是奇校验,TE是发送使能,RE是接收使能,可参见图6-10和表6-6。本实验中,UART传输数据的长度为8,除能校验控制,同时使能发送和接收。STOPT1:01用于设置停止位,可参见图6-11和表6-7,本实验的停止位为1位。CTSE用于除能或使能CTS引脚流控制,RTSE用于除能或使能RTS数据流控制,可参见图6-12和表6-8,本实验同时除能了CTS和RTS数据流控制。USARTBRR用于设置UART的波特率,可参见图6-9和表6-5,本实验的波特率为115200。在UART1.c文件的“内部函数实现”区步骤4:完善UART1.c文件(5)通过NVIC_Imit函数使能USART1的中断同时设置抢占优先级为1优先级为1。该函数涉及中断使能寄存器(NVIC→ISER[x])和中断优先级寄存器(NVIC→IP[x]),由于STM32大容量产品的USART1_IROn中断号是37(该中断号可以在文件stm32f10xh中查找到,也可参见表6-26)。因此,NVIC_Init函数实际上是通过向NVIC→ISERT11的bit5写入1使能USART1中断,并将抢占优先级和子优先级写入NVIC→IP37],可参见表6-27和表6-29。在本实验的NVIC模块中,ConfigNVIC函数调用NVICPriorityGroupConfig函数,由于NVIC_PriorityGroupConfig函数的参数是NVIC_PriorityGroup_2,选择第2组即最高2位(NVIC→IP37]的bit7~bit6)用于存放抢占优先级,最低2位(NVIC-IPT37]的bit5~bit4)用于存放子优先级,因此,执行完NVIC_Init函数之后,NVIC→IP[37]为0x50。在UART1.c文件的“内部函数实现”区步骤4:完善UART1.c文件(6)通过USARTITConig函数使能接收缓冲区非空中断,实际上是USARTCR1的RXNEIE写入1;此外USARTITCong函数还使能了发送缓冲区空中断即向USARTCR1的TXEIE写入1,可参见图6-10和表6-6。(7)通过USARTCmd函数使能USART1该函数涉及USARTCR1的UE可参见图6-10和表6-6。在UART1.c文件的“内部函数实现”区步骤4:完善UART1.c文件在UART1.c文件的“内部函数实现”区,在ConfigUART函数实现区的后面添加EnableUARTTx函数的实现代码,如程序清单6-11所示。EnableUARTTx函数实际上是将siUARTTxSts变量赋值为UARTSTATE_ON,并调用USART_ITConfig函数使能发送缓区空中断,该函数在WriteUART1中调用,即每次发送数据之后,调用该函数使能发送缓冲区空中断。步骤4:在UART1c文件的“内部函数实现”区,在EnableUARTTx函数实现区的后面添加SendCharUsedByFputc函数的实现代码,如程序清单6-12所示。putc是printf的底层函数fputc调用SendCharUsedByFputc函数,而SendCharUsedByFputc又调用USART_SendData函数,因此,printf实际上是通过向USART_DR(物理上是TDR)写入数据实现基于串口的信息输出,while语句是为了等待发送完毕再退出SendCharUsedByFputc函数。由于printf会占用主线程,因此,只建议通过printf输出调试信息。完善UART1.c文件步骤4:完善UART1.c文件在SendCharUsedByFputc函数实现区的后面添加USART1IROHandler中断服务函数的实现代码,如程序清单6-13所示。下面按照顺序对USART1IQHandler函数中的语进行解释说明。(1)在UART1c的ConfgUART函数中使能了发送缓冲区空中断和接收缓冲区非空中断,因此,当USART1的接收缓冲区非空,或发送缓冲区空时,硬件会执行USART1_IROHandler函数。(2)无论是通过USART_GetITStatus函数获取USART1接收缓冲区非空中断标志(USART_IT_RXNE),还是通过USART_GetITStatus函数获取USART1发送数据寄存器空中断标志(USARTIT_TXE),都建议通过NVICCIarPendingIRO函数中断起清除寄存器NVIC→ICPRx]对应位写入1清除中断挂起。由于STM32大容量产品的USART1IROn中断号是37(该中断号可以在文件stm32f10x.h中查找到,也可参见表6-26),该中断对应NVIC→ICPRI11的bit5,因此向该位写入1即可实现USART1中断挂起清除,NVIC→ICPR可参见表6-28。在UART1.c文件的“内部函数实现”区步骤4:完善UART1.c文件(3)通过USART_GetITStatus函数获取USART1接收缓冲区非空中断标志,该函数涉及USARTCR1的RXNEIE和USARTSR的RXNE当USART1的接收移位寄存器中的数据被转移到USART_DR(物理上是RDR)时,RXNE被硬件置位,读取USARTDR可以将该位清零,也可以通过向RXNE写入0来清除,可参见图6-7和表6-3。本实验是通过USART_ReceiveData函数读取USART1的USARTDR,再通过WriteReceiveBuf函数将读取到的数写入接收缓冲区。(4)当USART_SR的RXNE仍然是1时,在接收移位寄存器中的数据需要传送至RDR时,硬件会将USART_SR的ORE置为1当ORE为1时,RDR中的数据不会丢失,但是按收移位寄存器中的数据会被覆盖。为了避免数据被覆盖,还需要通过USART_GetFlagStatus函数获取溢出错误标志(USAR_FLAG_ORE),然后,再通过USART_CarFlag函数清除ORE,最后,通过USARTReceiveData函数读取RDR。在UART1.c文件的“内部函数实现”区步骤4:完善UART1.c文件(5)通过USART_GetITStatus函数获取USART1发送数据寄
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025绿化苗木采购合同样本
- 股票出货协议书范本
- 2025年03月浙江台州市玉环市事业单位公开招聘工作人员74人笔试历年典型考题(历年真题考点)解题思路附带答案详解
- 2025年03月广东深圳市光明区统计局公开招聘(选聘)专干4人笔试历年典型考题(历年真题考点)解题思路附带答案详解
- 2025年03月国家卫生健康委统计信息中心应届毕业生公开招聘1人笔试历年典型考题(历年真题考点)解题思路附带答案详解
- 物理试题2025年东北三省四城市联考暨沈阳市高三质量监测(二)及答案
- 重庆五一职业技术学院《俄汉互译口译》2023-2024学年第二学期期末试卷
- 户用和村用风光互补发电系统控制器及逆变器项目安全风险评价报告
- 湖南幼儿师范高等专科学校《BIM协同设计》2023-2024学年第一学期期末试卷
- 成都工贸职业技术学院《基础化学实验二》2023-2024学年第二学期期末试卷
- 六年级下册数学教案-比例 西师大版
- 抗日英雄人物杨靖宇介绍
- AI驱动的可持续能源发展
- 整本书阅读《林海雪原》【知识精研】六年级语文下册 (统编版五四制2024)
- 健康日用品设计与研发趋势
- 【化学】常见的盐(第1课时)-2024-2025学年九年级化学下册(人教版2024)
- 新人教版初中英语七至九年级全部课本单词
- 宜宾市新能源产业有限公司招聘笔试冲刺题2025
- 数字化背景下国有企业财会监督体系的构建与实践创新
- 龙游经济开发区下属国资公司招聘笔试冲刺题2025
- 《海上风电设备运输规范》
评论
0/150
提交评论