|
STM32学习笔记06—USART驱动实验 + |$ z1 C0 B* b) e1 i8 R 6.1 STM32串口简介2 k0 ?: b, ^ ~ 在之前的51单片机开发中已经详细地描述过串行通信协议,但是51中的串口有一个缺点,就是为了使用串口的波特率必须将晶振更换为11.0592MHz,如果采用12MHz晶振就会导致波特率误差太大,以致于串口无法正常收发,但是如果使用11.0592MHz晶振又会存在定时器计数误差(即定时器计数不准确),在STM32中很好地解决了这个问题,并且扩展了串口的应用。" |; g% J1 L6 N$ q STM32F103ZET6最多可提供5路串口,有分数波特率发生器、支持同步单线通信和半双工单线通讯、支持LIN、支持调制解调器操作、智能卡协议和IrDASIRENDEC规范、具有DMA等。STM32的USART模块结构框图如下图所示。
我们可以从框图发现,STM32的波特率是低4位表示小数部分,高12位表示整数部分,这就是为什么STM32可以在不更换晶振的条件下使用串口通信。 6.2 相关寄存器 6.2.1 控制寄存器USART_CR1
Bit 13:USART使能" O1 W) I8 n' T& Z 0:USART分频器和输出被禁止4 @4 w4 l% j* D7 ~' y, n8 l9 n4 z) D 1:USART模块使能 Bit 12:字长* P3 ~+ k3 }% @$ S 0:一个起始位,8个数据位,n个停止位2 g5 Z+ _6 r3 V4 W5 O1 X" ] 1:一个起始位,9个数据位,n个停止位 s6 b6 U1 G4 R0 x, c+ J Bit 11:唤醒的方法" v9 p, U0 Z4 f8 J X 0:被空闲总线唤醒 1:被地址标记唤醒# d4 q- Y% h% U6 w* k1 Y! w Bit 10:检验控制使能+ }" O8 x! M! T9 N, w! D8 ~ 0:禁止校验控制 1:使能校验控制 Bit 9:校验选择 0:偶校验, m% O6 }5 @( _0 O2 B! h. D 1:奇校验 Bit 8:PE中断使能 0:禁止产生中断 1:当USART_SR中的PE为1时,产生USART中断 Bit 7:发送缓冲区空中断使能 0:禁止产生中断; {7 L$ `6 f; \* e2 u0 Y5 F( X 1:当USART_SR中的TXE为1时,产生USART中断* C7 v4 c% n! V Bit 6:发送完成中断使能 0:禁止产生中断- V# X; G% C# f0 j. y1 ]' O3 q 1:当USART_SR中的TC为1时,产生USART中断! n2 W& v5 O: J6 p# q! H$ o1 x Bit 5:接收缓冲区非空中断使能 0:禁止产生中断3 [3 K6 p+ {+ a0 \) v 1:当USART_SR中的ORE或者RXNE为1时,产生USART中断 Bit 4:IDLE中断使能 0:禁止产生中断 1:当USART_SR中的IDLE为1时,产生USART中断 Bit 3:发送使能, p, h5 y4 t% x0 `$ J 0:禁止发送 1:使能发送 Bit 2:接收使能) @; j5 l+ J) i$ F- X: c L+ l 0:禁止接收 1:使能接收,并开始搜寻RX引脚上的起始位 Bit 1:接收唤醒 0:接收器处于正常工作模式;8 o1 g$ W' a( Q$ a 1:接收器处于静默模式9 Y, o! L2 D( F$ g9 G Bit 0:发送断开帧2 ]& r4 F6 {0 w) i# p* P" s6 I! C 0:没有发送断开字符 1:将要发送断开字符 6.2.2 波特率寄存器USART_BRR
Bit 15~Bit 4:波特率整数部分7 a3 o- d2 |& P0 k7 B Bit 3~Bit 0:波特率小数部分 注:波特率的计算公式6 H3 ?: E. {8 M, G% T' `
6.2.3 数据寄存器USART_DR
Bit 8~Bit 0:数据值" q1 E# M7 D9 d2 \: p 包含了发送或接收的数据。由于它是由两个寄存器组成的,一个给发送用TDR,一个给接收用RDR,该寄存器兼具读和写的功能。当USART_CR1中PCE位被置位进行发送时,写到MSB的值(根据数据的长度不同,MSB是第7位或者第8位)会被后来的校验位取代。当使能校验位进行接收时,读到的MSB位是接收到的校验位。( B7 v% w4 a) N5 J5 S 6.2.4 状态寄存器USART_SR( F/ N& Z( q* M6 C; p9 B0 F) O
Bit 9:CTS标志(如果设置了CTSE位,当nCTS输入变化状态时,该位被硬件置高,由软件将其清零)1 |' o) g1 N. G, i: E+ |6 q8 w9 X 0:nCTS状态线上没有变化5 u( a5 D( C0 V 1:nCTS状态线上发生变化2 q G- T3 a6 r& L7 }6 N Bit 8:LIN断开检测标志(当探测到LIN断开时,该位由硬件置1,由软件将其清零). b- U* u r6 u1 P/ ?- D% R 0:没有检测到LIN断开+ A" Y9 D1 n! E; U, @) z 1:检测到LIN断开3 W% y" e& [3 E6 Y7 |3 E Bit 7:发送数据寄存器空 当TDR寄存器中的数据被硬件转移到移位寄存器时,该位被硬件置位,对USART_DR的写操作,将该位清零。; E& U' v/ Y& Q$ R 0:数据还没有被转移到移位寄存器& W9 f# U% Z/ @$ V, b D; q 1:数据已经被转移到移位寄存器 Bit 6:发送完成( G: ?1 x& P: f V% z- Z 当包含有数据的一帧发送完成后,并且TXE=1时,由硬件将该位置’1’。然后写入USART_DR清除该位。 0:发送还未完成$ x6 v0 z! x0 v6 i' ] 1:发送完成 Bit 5:读数据寄存器非空 当数据被转移到USART_DR寄存器中,该位被硬件置位。对USART_DR读操作可以将该位清零。1 [9 t: |; y: Y. F' t+ C9 s 0:数据没有收到; 1:收到数据,可以读出 Bit 4:检测到总线空闲1 \. X) h& o# B* _; z# y 当检测到总线空闲时,该位被硬件置位,则产生中断。先读USART_SR,然后读USART_DR清除该位。 0:没有检测到空闲总线$ f0 ?7 M) k) i0 A5 n P, } 1:检测到空闲总线 Bit 3:过载错误 当RXNE仍然是1的时候,当前被接收在移位寄存器中的数据,需要传送至RDR寄存器时,硬件将该位置位,先读USART_SR,然后读USART_CR清零。2 u! o/ N! U& m7 Y& \ 0:没有过载错误 1:检测到过载错误- K% s, R7 @8 T u& Z Bit 2:噪声错误标志 在接收到的帧检测到噪音时,由硬件对该位置位。先读USART_SR,再读USART_DR清0。 0:没有检测到噪声 1:检测到噪声! F- u6 h0 U! X% {; C# f: p: W Bit 1:帧错误 当检测到同步错位,过多的噪声或者检测到断开符,该位被硬件置位。先读USART_SR,再读USART_DR清零+ B* I. n% o3 N# p! F" @+ P! e 0:没有检测到帧错误 1:检测到帧错误或者break符, ^, s# ]9 g! f' R6 Y. F Bit 0:校验错误 在接收模式下,如果出现奇偶校验错误,硬件对该位置位。依次读USART_SR和USART_DR清零,在清除PE位前,软件必须等待RXNE标志位被置1。5 g4 i5 l- L# w3 t( ` 0:没有奇偶校验错误; 1:奇偶校验错误 6.3 printf函数重映射 学习C语言的时候会经常用到一个函数,就是格式化输出printf,这个函数的源代码如下所示。
从上图可以看出来,printf函数实际上的核心是putchar函数,在KEIL中,由于我们使用了MicroLIB,所以putchar函数改为了fputc函数,此时,我们只需要修改fputc函数就可以完成printf重定向,重定向代码如下图所示。
6.4 串口例程( e* r% u% o$ c+ z- w/ g) ^0 N 使用printf函数将串口接收到的字符串发送出去。0 J" ~/ o. w7 F! Y- [; u3 D3 V, k, W, t (1)底层寄存器文件stm32f10x.h添加串口寄存器地址。
(3)将usart1.c和usart1.h两个文件加入工程。0 o4 X; a- q# c
(5)在1.c文件中添加以下代码。, t' H/ @. o& ]1 q7 {
6.5 实验结果
t3 g- ], K. U3 a : I6 ^. z/ t9 H4 i/ [ 上一篇: STM32学习笔记05—GPIO输入输出实验:$ @ N4 @7 ]) f6 ?; c ) J# J5 A8 w1 p0 ^ $ v! ~3 T7 i" ^9 s5 e% m* T- E1 K |
微信公众号
手机版