一、uart是什么
uart是通用异步收发传输器(universal asynchronous receiver/transmitter),通常称作uart,是一种异步收发传输器,是设备间进行异步通信的关键模块。uart负责处理数据总线和串行口之间的串/并、并/串转换,并规定了帧格式;通信双方只要采用相同的帧格式和波特率,就能在未共享时钟信号的情况下,仅用两根信号线(rx 和tx)就可以完成通信过程,因此也称为异步串行通信。
若加入一个合适的电平转换器,如sp3232e、sp3485,uart 还能用于rs-232、rs-485 通信,或与计算机的端口连接。uart 应用非常广泛,手机、工业控制、pc 等应用中都要用到uart。
uart使用的是 异步,串行通信。 串行通信是指利用一条传输线将资料一位位地顺序传送。特点是通信线路简单,利用简单的线缆就可实现通信,降低成本,适用于远距离通信,但传输速度慢的应用场合。 异步通信以一个字符为传输单位,通信中两个字符间的时间间隔多少是不固定的,然而在同一个字符中的两个相邻位间的时间间隔是固定的。 数据传送速率用波特率来表示,即每秒钟传送的二进制位数。例如数据传送速率为120字符/秒,而每一个字符为10位(1个起始位,7个数据位,1个校验位,1个结束位),则其传送的波特率为10×120=1200字符/秒=1200波特。 数据通信格式如下图:
其中各位的意义如下:起始位:先发出一个逻辑”0”信号,表示传输字符的开始。数据位:可以是5~8位逻辑”0”或”1”。如ascii码(7位),扩展bcd码(8位)。小端传输校验位:数据位加上这一位后,使得“1”的位数应为偶数(偶校验)或奇数(奇校验)停止位:它是一个字符数据的结束标志。可以是1位、1.5位、2位的高电平。空闲位:处于逻辑“1”状态,表示当前线路上没有资料传送。 注:异步通信是按字符传输的,接收设备在收到起始信号之后只要在一个字符的传输时间内能和发送设备保持同步就能正确接收。下一个字符起始位的到来又使同步重新校准(依靠检测起始位来实现发送与接收方的时钟自同步的)
总结起来,如果我们要配置串口通信,至少要设置一下几个参数:字长(即一次传输数据的长度)、波特率(即每秒传输的数据位数)、奇偶校验位及停止位。
二、串口工作过程分析
usart是通用同步/异步收发器
uart是通用异步收发器
由于常用的是异步模式,所以在此我们都是只需要使用uart。
我们先介绍串口发送的过程,我们先来看一下串口架构图:
可以看出,串口外设的架构图乍一看略微复杂,这里我们分开进行分析:
我们直接从发送(tx)和接收(rx)开始讲起。
rx和tx此处不做过多介绍。
根据下图红色箭头标记可以看出:对于接收来说,它经过编解码模块,然后直接进入到了接收移位寄存器,接收移位寄存器一位一位的接收数据,然后再将接收到的数据一次性写到接收数据寄存器(rdr)中,这样,cpu就可以通过读取接收数据寄存器(rdr)来读到接收的数据。
同样,对于发送来说,cpu将数据写入到发送数据寄存器(tdr),发送数据寄存器(tdr)将数据一次性的发送给发送移位寄存器,然后再根据波特率将数据一位一位的移出。如下图:
我们知道,发送和接收事先要确定好波特率,那么波特率是怎么配置的呢?我们顺着箭头继续往下找:
根据上图所示,我们不难看出:波特率是通过发送控制器和接收控制器分别控制发送器时钟和接收器时钟,然后传输到发送移位寄存器和接收移位寄存器中的。
通过上图我们还可以看出:发送器时钟和接收器时钟来自同一单元。我们现在就来分析一下这两个时钟是怎么产生的。
上文中已经介绍过,波特率实际上就是每秒传输的二进制位数,通过对时钟的控制可以改变波特率。我们向波特比率寄存器(即上图中的usart_brr)写入参数,修改了串口时钟的分频值usartdiv。
usart_brr寄存器包括两个部分:div_mantissa(即usartdiv的整数部分)和div_fraction(即usartdiv的小数部分)。计算公式为:usartdiv=div_mantissa+(div_fraction/16)。
波特率计算公式如下:
我们只要知道了usartdiv的值,就可以知道串口波特率寄存器的值。
举一个简单的例子:假设我们串口1要设置的波特率为115200,plck2的时钟频率为72mhz,根据上面的公式,我们可以得出:
usartdiv=72000000/(16*115200)=39.0625
由此 我们就可以得到div_fraction=16*0.0625=1=0x01;
div_mantissa=39=0x27。由于usartdiv是对串口外设的时钟源进行分频,不同的usart挂载的总线并不相同,所以它们的时钟源fpclk也不相同。usart1挂载在apb2总线上,其时钟源为fpclk2;usart2、3、4、5挂载在apb1上,其时钟源为fpclk1。串口的时钟源经过usartdiv分频后,分别输出作为发送器时钟及接收器时钟,来控制发送和接收的时序。
三、程序分析
首先,我们打开ibox开发板的例程usart_demo,在左侧的工程目录中找到user工程文件夹点击前方的“+”,找到main.c文件并打开。
我们可以看到,在主函数上面有一个fputc(intch, file *f)函数。
这个函数的功能是将一个字符写入到文件中。其参数包括:ch要写入的字符; *f指向file结构的指针。
接下来我们来看一下主函数:
上图中的两行代码分别为定义gpio结构体和定义usart结构体。
上面的函数是使能apb2总线上的串口时钟,同时启动gpioa端口。
上图中的代码是对gpio端口的配置。其配置方法在第三讲中有提及到,我们可以看出其配置的是pa9端口。因为pa9端口同时也是usart1_tx,即串口的发送数据端口。
上图中的代码是对pa10端口的配置。因为pa10端口同时也是usart1_rx,即串口的接收数据端口。
我们看一下gpio的工作模式:gpio_pin_9的工作模式为复用推挽输出;gpio_pin_10的工作模式为浮空输入。我们可以在stm32参考手册中找到gpio配置中关于usart的配置,如下表:
我们工作模式为全双工,所以根据表格,配置好相应的gpio端口工作模式,分别为复用推挽输出和浮空输入。
接下来就是对串口的初始化和配置。如上图所示。我们逐行分析。
在此之前,我们可以在工程目录种先找到stm32f10x_usart.h(可以在main.c下面找到,因为我们的main函数包含了此库函数),即usart库函数。
我们可以在最下面找到许多函数声明。我们可以在用户手册种找到这些函数的描述,大家可以简单了解一下。
我们继续浏览stm32f10x_usart.h库函数,可以找到typedef struct,如下图(为方便截图,在此已将注释隐藏):
我们可以发现 我们程序种需要配置的usart相关参数都在这里有所声明。不仅如此,继续向下翻阅还可以找到所需配置的相关参数(由于代码略多,在此不做截图,读者可自己查阅)。
uint32_t usart_baudrate:该成员设置了usart传输的波特率。
uint16_t usart_wordlength:提示了在一个帧中传输或者接收到的数据位数。可取值为:usart_woedlength_8b(8位数据)和usart_woedlength_9b(9位数据)。
uint16_t usart_stopbits:在帧尾传输的停止位。其定义为usart_stopbits_0.5(0.5个停止位)、usart_stopbits_1(1个停止位)、usart_stopbits_1.5(1.5个停止位)、usart_stopbits_2(2个停止位)。
uint16_t usart_parity:奇偶校验位。其定义为usart_parity_no(不使用)、usart_parity_even(偶模式)、usart_parity_odd(奇模式)。
uint16_t usart_mode:指定了使能或者失能发送和接收模式。其定义为:usart_mode_rx(接收使能)、usart_mode_tx(发送使能)。uint16_t usart_hardwareflowcontrol:制定了硬件流控制模式是使能还是失能。其定义为:usart_hardwareflowcontrol_rts(发送请求rts使能)、usart_hardwareflowcontrol_cts(清除发送cts使能)、usart_hardwareflowcontrol_rts_cts(rts和cts使能)。
usart_clock、usart_cpol、usart_cpha和usart_lastbit在同步模式下才需要配置,在此暂时不做解释。
了解了这些,对串口的初始化和配置分析就非常容易了。我们回到主函数,观察串口初始化和配置的几行代码:
上图代码是将波特率设置为115200。
上图代码定义了数据位数为8位数据。
上图代码设定了在帧尾传输一个停止位。
上图代码设定了不使用奇偶校验。
上图代码设定了不使用硬件流控制模式。
上图代码定义了发送和接收模式:使能发送和使能接收。
上图种两行代码第一行为串口初始化,第二行为使能串口。
最后,我们循环打印“usart printf example: retarget the c library printf function to the usart”。
接下来,我们观察实验现象:首先将程序烧录到ibox中,然后我们使用usb转ttl串口工具将ibox与电脑连接,如下图所示:
ibox的j12接口从左到右依次为:tx、rx和gnd(注意:我们没有为ibox接电源,ibox需要单独供电)。
接下来,我们打开串口助手。
如上图:首先我们需要根据我们的程序配置串口(不同助手界面可能有所不同)。
设置好参数后,我们将程序烧录到ibox中,观察串口助手。
“矿机”ASIC供应完全被中国垄断?
戴尔燃7000系列现售6099元!外观精致配置性价比高
PCB封装库汇总分享 | 收集整理百度网盘链接
带32位MCU和高精度ADC的SoC产品-SD93F系列开发指南(十)
从“芯”出发,重振无锡“国家南方微电子工业基地”的雄风
UART是什么?串口工作过程分析
ZedBoard移植嵌入式Linux教程(1,2)
GaN打破壁垒—RF功率放大器的带宽越来越宽、 功率越来越高
厦门警务机器人开始运行 为新时代智慧警务插上5G的翅膀
创维发布首款鸣丽屏 MiniLED 电视 Q70 系列:MiniLED 背光技术、色域达到100%
德索告诉您高压插座使用的注意事项
智能家居的性能要求及系统功能分析
ROHM | R60xxRNx系列概述
ReDB:通过可靠、多样和类平衡的伪标签重新审视跨域3D目标检测
贸泽与Western Automation Research and Development 签订全球代理协议 供应其接地故障保护产品
为了心爱的本本,请不要吸烟
为什么越来越多的游戏玩家转向AMD中央处理器?
红芯浏览器名不副实!简直就是侮辱大家的智商!
绿驰汽车广阔前景引5G、车联网研发专家助阵
固态继电器电路图分享