零死角玩转stm32-中级篇1、调试必备-串口(UART)资料下载.pdf
《零死角玩转stm32-中级篇1、调试必备-串口(UART)资料下载.pdf》由会员分享,可在线阅读,更多相关《零死角玩转stm32-中级篇1、调试必备-串口(UART)资料下载.pdf(21页珍藏版)》请在冰豆网上搜索。
有些朋友会说用到什么就学什么,听起来这也不无道理呀。
但对于野火来说会把学习串口的操作放在第二位。
在程序运行的时候我们可以通过点亮一个LED来显示代码的执行的状态,但有时候我们还想把某些中间量或者其他程序状态信息打印出来显示在电脑上,那么这时串口的作用就可想而知了。
1.1异步串口通讯协议异步串口通讯协议阅读过STM32中文参考手册的读者会发现,STM32的串口非常强大,它不仅支持最基本的通用串口同步、异步通讯,还具有LIN总线功能(局域互联网)、IRDA功能(红外通讯)、SmartCard功能。
为实现最迫切的需求,利用串口来帮助我们调试程序,本章介绍的为串口最基本、最常用的方法,全双工、异步通讯方式。
图1-1为串口异步通讯协议。
图1-1异步串口通讯协议重温串口的通讯协议,我们知道要配置串口通讯,至少要设置以下几个参数:
字长(一次传送的数据长度)、波特率(每秒传输的数据位数)、奇偶校验位、还有停止位。
对ST库函数的使用已经上手的读者应该能猜到,在初始化串口的时候,必然有一个串口初始化结构体,这个结构体的几个成员肯定就是有来存储这些控制参数的。
-第4页-1.2直通线和交叉线直通线和交叉线野火野火STM32开发板开发板串口硬件原理图串口硬件原理图图1-2野火开发板串口硬件图见图1-2,这是野火STM32开发板的接线图,使用的为MAX3232芯片,把STM32的PA10引脚(复用功能为USART1的Rx)接到了DB9接口的第2针脚,把PA9引脚(复用功能为USART的Tx)连接到了DB9接口的第3针脚。
Tx(发送端)接第3针脚,Rx(接收端)接第2针脚。
这种接法是跟PC的串口接法一样的,如果要实现PC跟野火板子通讯,就要使用两头都是母的交叉线。
串口线主要分两种,直通线(平行线)和交叉线。
它们的区别见图1-3。
假如PC与板子之间要实现全双工串口通讯,必然是PC的Tx针脚要连接到板子的Rx针脚,而PC的Rx针脚则要连接至板子的Tx针脚了。
由于板子和pc的串口接法是相同的,就要使用交叉线来连接了。
如果有的开发板是Tx连接至DB9的第2针脚,而Rx连接至第3针脚,这与PC接法是相反的,这样的板子与PC通讯就需要使用直通线了。
为什么野火板子要使用PC的接法?
假如使用非PC接法,由于板子与PC的接法相反,通讯就要使用直通线;
但两个板子之间想要进行串口通讯时,由于接法相同,就要使用交叉线。
如果使用PC接法,板子与PC之间接法相同,通讯使用交叉线;
两个相同板子之间接法也相同,通讯也是使用交叉线。
-第5页-所以野火建议大家设计板子时,尽量采用与PC相同的标准串口接法。
图1-3交叉线与直通线的区别介绍直通线与交叉线的区别,一来是野火发现某些读者因为线的问题而花费了大量宝贵的时间。
二来是介绍串口线的DIY方法。
要实现基本的全双工异步通讯,只要3条线,分别为Rx、Tx、和GND。
如果读者正在为直通线、交叉线、公头、母头不匹配而烦恼,可以根据自己的需要,参照图1-3,用三根杜邦线连接即可。
-第6页-1.3串口工作过程分析串口工作过程分析图1-4串口架构图串口外设的架构图看起来十分复杂,实际上对于软件开发人员来说,我们只需要大概了解串口发送的过程即可。
从下至上,我们看到串口外设主要由三个部分组成,分别是波特率的控制部分、收发控制部分及数据存储转移部分。
-第7页-1.3.1波特率控制波特率控制波特率,即每秒传输的二进制位数,用b/s(bps)表示,通过对时钟的控制可以改变波特率。
在配置波特率时,我们向波特比率寄存器USART_BRR写入参数,修改了串口时钟的分频值USARTDIV。
USART_BRR寄存器包括两部分,分别是DIV_Mantissa(USARTDIV的整数部分)和DIVFraction(USARTDIV的小数)部分,最终,计算公式为USARTDIV=DIV_Mantissa+(DIVFraction/16)。
USARTDIV是对串口外设的时钟源进行分频的,对于USART1,由于它是挂载在APB2总线上的,所以它的时钟源为fPCLK2;
而USART2、3挂载在APB1上,时钟源则为fPCLK1,串口的时钟源经过USARTDIV分频后分别输出作为发送器时钟及接收器时钟,控制发送和接收的时序。
1.3.2收发控制收发控制围绕着发送器和接收器控制部分,有好多个寄存器:
CR1、CR2、CR3、SR,即USART的三个控制寄存器(ControlRegister)及一个状态寄存器(StatusRegister)。
通过向寄存器写入各种控制参数,来控制发送和接收,如奇偶校验位,停止位等,还包括对USART中断的控制;
串口的状态在任何时候都可以从状态寄存器中查询得到。
具体的控制和状态检查,我们都是使用库函数来实现的,在此就不具体分析这些寄存器位了。
1.3.3数据存储转移部分数据存储转移部分收发控制器根据我们的寄存器配置,对数据存储转移部分的移位寄存器进行控制。
当我们需要发送数据时,内核或DMA外设(一种数据传输方式,在下一章介绍)把数据从内存(变量)写入到发送数据寄存器TDR后,发送控制器将适时地自动把数据从TDR加载到发送移位寄存器,然后通过串口线Tx,把数据一位一位地发送出去,在数据从TDR转移到移位寄存器时,会产生发送寄存器-第8页-TDR已空事件TXE,当数据从移位寄存器全部发送出去时,会产生数据发送完成事件TC,这些事件可以在状态寄存器中查询到。
而接收数据则是一个逆过程,数据从串口线Rx一位一位地输入到接收移位寄存器,然后自动地转移到接收数据寄存器RDR,最后用内核指令或DMA读取到内存(变量)中。
1.4串口通讯实验分析串口通讯实验分析1.4.1实验描述及工程文件清单实验描述及工程文件清单实验描述实验描述重新实现C库中的printf()函数到串口1,这样我们就可以像用C库中的printf()函数一样将信息通过串口打印到电脑,非常方便我们程序的调试。
硬件连接硬件连接PA9-USART1(Tx)PA10-USART1(Rx)用到的库文件用到的库文件startup/start_stm32f10x_hd.cCMSIS/core_cm3.cCMSIS/system_stm32f10x.cFWlib/stm32f10x_gpio.cFWlib/stm32f10x_rcc.cFWlib/stm32f10x_usart.c用户编写的文件用户编写的文件USER/main.cUSER/stm32f10x_it.cUSER/usart1.c1.4.2配置工程环境配置工程环境串口实验中我们用到了GPIO、RCC、USART这三个外设的库文件stm32f10x_gpio.c、stm32f10x_rcc.c、stm32f10x_usart.c,所以我们先要把这-第9页-个库文件添加进工程,新建用户文件usart1.c。
并在stm32f10x_conf.h中把相应的头文件的注释去掉。
1./*2.*3.*fileProject/STM32F10x_StdPeriph_Template/stm32f10x_conf.h4.*authorMCDApplicationTeam5.*versionV3.5.06.*date08-April-20117.*briefLibraryconfigurationfile.8.*/9.10.#includestm32f10x_gpio.h11.#includestm32f10x_rcc.h12.#includestm32f10x_usart.h1.4.3main文件文件配置好要用的库的环境之后,我们就从main函数看起,层层剥离源代码。
1./*2.*函数名:
main3.*描述:
主函数4.*输入:
无5.*输出:
无6.*/7.intmain(void)8.9./*USART1config1152008-N-1*/10.USART1_Config();
11.12.printf(rnthisisaprintfdemorn);
13.14.printf(rn欢迎使用野火M3实验板:
)rn);
15.16.USART1_printf(USART1,rnThisisaUSART1_printfdemorn);
17.18.USART1_printf(USART1,rn(_DATE_-_TIME_)rn);
19.20.for(;
)21.22.23.24.首先调用函数USART1_Config(),函数USART1_Config()主要做了如下工作:
1.使能了串口1的时钟2.配置好了usart1的I/O-第10页-3.配置好了usart1的工作模式,具体为波特率为115200、8个数据位、1个停止位、无硬件流控制。
即1152008-N-1。
1.4.4USART初始化配置初始化配置具体的USART1_Config()在usart1.c这个用户文件中实现:
USART1_Config3.*描述:
USART1GPIO配置,工作模式配置。
1152008-N-14.*输入:
无5.*输出:
无6.*调用:
外部调用7.*/8.voidUSART1_Config(void)9.10.GPIO_InitTypeDefGPIO_InitStructure;
11.USART_InitTypeDefUSART_InitStructure;
12.13./*configUSART1clock*/14.RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);
15.16./*USART1GPIOconfig*/17./*ConfigureUSART1Tx(PA.09)asalternatefunctionpush-pull*/18.GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
19.GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
20.GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
21.GPIO_Init(GPIOA,&
GPIO_InitStructure);
22./*ConfigureUSART1Rx(PA.10)asinputfloatin