STM32F103(二十三)通用同步异步收发器(USART)

学习板:STM32F103ZET6

通用同步异步收发器

  • 一、USART简介
  • 二、、USART相关寄存器
    • 1、控制寄存器 1(USART_CR1)
    • 2、控制寄存器 2(USART_CR2)
    • 3、控制寄存器 3(USART_CR3)
    • 4、状态寄存器(USART_SR)
    • 5、数据寄存器(USART_DR)
    • 6、波特比率寄存器(USART_BRR)+波特率计算方法
  • 三、USART相关库函数
    • 1、USART复位函数USART_DeInit()
    • 2、USART初始化函数USART_Init()
    • 3、结构体初始化函数USART_StructInit()
    • 4、同步模式下时钟配置函数USART_ClockInit()
    • 5、同步模式下初始化时钟配置结构体函数USART_ClockStructInit()
    • 6、USART使能函数USART_Cmd()
    • 7、USART中断配置函数USART_ITConfig()
    • 8、DMA使能函数USART_DMACmd()
    • 9、静默模式下设备地址设置函数USART_SetAddress()
    • 10、静默模式下唤醒方式设置函数USART_WakeUpConfig()
    • 11、设置静默模式函数USART_ReceiverWakeUpCmd()
    • 12、LIN模式下断开符长度设置函数USART_LINBreakDetectLengthConfig()
    • 13、使能LIN模式函数USART_LINCmd()
    • 14、发送数据函数USART_SendData()
    • 15、接收数据函数USART_ReceiveData()
    • 16、发送断开符函数USART_SendBreak()
    • 17、状态获取函数USART_GetFlagStatus()与USART_GetITStatus()
    • 18、清除标志位函数USART_ClearFlag()与USART_ClearITPendingBit
  • 四、USART编程顺序
    • 1、串口时钟和GPIO时钟使能
    • 2、串口复位(可不必)
    • 3、GPIO初始化(+一个重点说明
    • 4、串口初始化
    • 5、串口使能
    • 6、中断配置(如果需要)
    • 7、发送和接收数据
    • 8、获取串口状态
    • 9、获取中断状态(如果需要)
  • 五、例1(发送一个字符到串口)
    • 1、题
    • 2、分析
    • 3、代码
      • (1)按键代码
      • (2)串口设置代码
      • (3)主函数代码
    • 4、测试效果:
  • 六、例2(STM32F1、F4之间的串口通信)(+一个注意事项
    • 1、题
    • 2、分析
    • 3、代码
      • (1)F1代码
      • (2)F4的LED代码
      • (3)串口设置代码
      • (4)主函数代码
    • 4、硬件连接
    • 5、效果
  • 七、例3(对例2的修改)

一、USART简介

USART为通用同步异步收发器,支持同步单向通信和半双工单线通信,也支持LIN(局部互连网),智能卡协议和IrDA(红外数据组织)SIR ENDEC规范,以及调制解调器(CTS/RTS)操作。

STM32F103(二十三)通用同步异步收发器(USART)_第1张图片

USART双向通信至少需要两个引脚:收数据输入(RX)和发送数据输出(TX)。此外,CK引脚用于同步通信;CTS、RTS用于调制解调。

USART传输数据时,有一个起始位、数据位可通信双方软件约定8位或9位、停止位可设置为0.5或1位或1.5位或2位。

在传输线空闲状态下,TX线为高电平,起始位时,TX为低电平,故可以通过下降沿检测是否开始数据传输(后边还会详述);停止位时TX处于高电平。

(1)接收数据
外部设备——>串行输入移位寄存器——>输入数据缓冲寄存器——>MCU

(2)发送数据
MCU——>输出数据缓冲器——>串行输出移位寄存器——>外部设备

二、、USART相关寄存器

1、控制寄存器 1(USART_CR1)

STM32F103(二十三)通用同步异步收发器(USART)_第2张图片

位0: 发送断开帧
STM32F103(二十三)通用同步异步收发器(USART)_第3张图片

该位设置为1后,完成当前数据传输,会在TX线上发送一个断开符号,发送断开符号完成后该位被硬件置1 。空闲帧为高电平,断开帧为低电平,而起始位也为低电平。所以插入断开帧后,TX线会传送一个“1”,为了准确检测下一帧的起始位(低电平)。当然如果没有下一帧数据,会处于空闲状态,TX线保持高电平。

位1: 接收唤醒

STM32F103(二十三)通用同步异步收发器(USART)_第4张图片
该位设置USART是否为静默模式,该位不设置时,为默认正常工作状态。设置为唤醒模式时,需要先接收一个数据字节才能设置,否则无法唤醒。唤醒序列到来时,该位硬件清零。

静默模式:
①任何接收状态都不会被设置
②所有接收中断被禁止
③CR1寄存器位11 WAKE设置为0,可以被空闲总线唤醒;WAKE设置为1,可以被地址标记唤醒。

位2: 接收使能
在这里插入图片描述
该位使能接收,置1后开始搜索RX引脚上的起始位。

起始位:1110x0x0x0000(x为0或1,x为1时,认为有噪音)
STM32F103(二十三)通用同步异步收发器(USART)_第5张图片

在搜索起始位时,先检测低电平(因为空闲状态传输线上为高电平),检测到下降沿后,会通过两次采样。上图中的第3、5、7为第一次采样;第8、9、10为第二次采样。

如果俩次采样的每一次都全为0。(即图中红框中“每三位至少有2个0”,为全0),此时确定为起始位。

如果俩次采样中,有一次仅仅有2个0、或者两次采样每次都只有2个0,也会判断为起始位,此时表示有噪音,噪声标志位会被置1.

位3: 发送使能
STM32F103(二十三)通用同步异步收发器(USART)_第6张图片
位4: IDLE中断使能
在这里插入图片描述
该位使能空闲总线中断,该位置1后,使能中断。当检测到总线空闲时,SR寄存器的位4:IDLE硬件置1,发生中断。

位5~位8: :各中断使能

STM32F103(二十三)通用同步异步收发器(USART)_第7张图片

分别为接收缓冲区非空中断、发送完成中断、发送缓冲区空中断、帧错误中断。由SR寄存器可以得到状态。

位9~位10: :校验选择与校验控制

STM32F103(二十三)通用同步异步收发器(USART)_第8张图片
位10使能校验控制,根据帧长度的不同,校验码插入到不同的位置。校验码在数据位后面,停止位之前
STM32F103(二十三)通用同步异步收发器(USART)_第9张图片
位9选择奇偶校验。奇偶校验的目的是判断数据传输是否出错。偶校验通过校验位配置,使数据位与校验位的所有“1”加起来为偶数。奇校验通过校验位配置,使数据位与校验位的所有“1”加起来为奇数。

偶校验:如果数据位中1的个数为奇数,则校验位为1;如果数据位中1的个数为偶数,则校验位为0。

奇校验:如果数据位中1的个数为奇数,则校验位为0;如果数据位中1的个数为偶数,则校验位为1。

位11: :唤醒方法设置
在这里插入图片描述
该位设置唤醒静默状态下的唤醒方式。之前的位1设置什么工作状态,位1置1后进入静默状态。

WAKE=0时:

此时静默状态由空闲总线唤醒,即当检测到空闲帧后被唤醒;此时CR1寄存器位1(RWU)被硬件清零,USART进入正常工作状态。

WAKE=1时:

此时静默状态由地址标记唤醒,当传输的数据高位为1时,认为是地址,否则认为是数据。目标接收器的地址在第四位中存储低四位在CR2寄存器的位0:3设置。

当接收到的字节与接收器编程地址匹配时,被唤醒;否则还会处于静默状态;之前也总结到过,处于静默状态不会产生中断。

当接收到的字节与接收器编程地址匹配时,被唤醒,退出静默状态。CR1寄存器的位1被硬件清零,即USART处于正常工作状态。

位12: :设置字长
STM32F103(二十三)通用同步异步收发器(USART)_第10张图片
该位设置字长,停止位由CR2寄存器设置,之后与字长一起总结。

位13: :使能USART
STM32F103(二十三)通用同步异步收发器(USART)_第11张图片

2、控制寄存器 2(USART_CR2)

STM32F103(二十三)通用同步异步收发器(USART)_第12张图片
位3:0: :设备地址设置
在这里插入图片描述
这4位来设置目标设备的地址,用于静默状态下由地址标记唤醒USART设备。

位5: :断开符长度检测

在这里插入图片描述
该位用来设置断开符的长度。之前CR1寄存器位0置1后发送断开符。本寄存器位5设置断开符长度为10位或11位。

位6: :断开符中断使能

STM32F103(二十三)通用同步异步收发器(USART)_第13张图片

该位使能检测断开符中断。

如果检测到断开符,则状态寄存器SR的位8 LBD被硬件置1 ,当CR2寄存器位6 LBDIE设置为1,则会产生中断。

位8: :最后一位时钟脉冲
STM32F103(二十三)通用同步异步收发器(USART)_第14张图片
位9~10: :时钟与相位设置
STM32F103(二十三)通用同步异步收发器(USART)_第15张图片

注意是在同步模式下设置极性和相位。与SPI时钟的极性和相位一致。
附SPI数据时钟序图:
STM32F103(二十三)通用同步异步收发器(USART)_第16张图片
位11: 时钟使能
STM32F103(二十三)通用同步异步收发器(USART)_第17张图片
位12~13: 设置停止位
STM32F103(二十三)通用同步异步收发器(USART)_第18张图片

①不设置时,默认1位停止位。
②2个停止位:用于常规USART模式、单线模式、调制解调器模式
③0.5个停止位:智能卡模式下接收数据
④1.5个停止位:智能卡模式下发送和接收数据

前面CR1寄存器设置过字长、奇偶校验、起始位,本寄存器位13:12设置停止位。其数据传输如下:

STM32F103(二十三)通用同步异步收发器(USART)_第19张图片
位14: LIN模式使能
STM32F103(二十三)通用同步异步收发器(USART)_第20张图片

之前总结的CR1寄存器位0发送断开符。需要通过CR2寄存器位14使能断开符发送,使能后才能通过CR1寄存器位0发送断开符。

3、控制寄存器 3(USART_CR3)

STM32F103(二十三)通用同步异步收发器(USART)_第21张图片
位0:错误中断使能
STM32F103(二十三)通用同步异步收发器(USART)_第22张图片

该中断用于DMA传送时的错误中断,所以必须先使能DMA,即需将本寄存器的位6置1 。

位1~5:
STM32F103(二十三)通用同步异步收发器(USART)_第23张图片

分别为红外模式使能、红外功耗、半双工选择、智能卡不应答设置、只能卡使能
位6~7:使能DMA发送和接收
STM32F103(二十三)通用同步异步收发器(USART)_第24张图片

位8~10:

STM32F103(二十三)通用同步异步收发器(USART)_第25张图片

分别为RTS硬件流使能、CTS硬件流使能、CTS中断使能。

4、状态寄存器(USART_SR)

STM32F103(二十三)通用同步异步收发器(USART)_第26张图片

位0:校验错误状态

STM32F103(二十三)通用同步异步收发器(USART)_第27张图片

该位在接收模式出现奇偶校验错误时,硬件置1 。注意清除方式:先读SR寄存器、再读DR寄存器。读DR寄存器,要保证DR寄存器非空,所以读之前一定要保证SR寄存器位5 RXNE位为1 。

位1:帧错误状态
STM32F103(二十三)通用同步异步收发器(USART)_第28张图片
当检测到同步错位,过多的噪声或者检测到断开符,该位被硬件置位。注意清除方式:先读SR寄存器、再读DR寄存器。

位2:噪声错误标志

STM32F103(二十三)通用同步异步收发器(USART)_第29张图片
在接收到的帧检测到噪音时,由硬件对该位置位。注意清除方式:先读SR寄存器、再读DR寄存器。

位3:过载错误状态
STM32F103(二十三)通用同步异步收发器(USART)_第30张图片

当DR寄存器非空,但是又有数据传到RDR移位寄存器时,出现过载错误。即当SR寄存器位5 RXNE位为1时,有数据传进RDR移位寄存器,出现过载错误。注意清除方式:先读SR寄存器、再读DR寄存器。

位4:总线空闲状态
STM32F103(二十三)通用同步异步收发器(USART)_第31张图片

当总线处于空闲状态时,该位被硬件置1。注意清除方式:先读SR寄存器、再读DR寄存器。

位5:读数据寄存器非空

STM32F103(二十三)通用同步异步收发器(USART)_第32张图片

当数据从RDR移位寄存器转移到DR数据寄存器是,该位硬件置1 。注意清除方式:读DR寄存器或直接写入0。

位6:发送完成状态
在这里插入图片描述

当发送完一帧的数据,且TD寄存器数据被移入移位寄存器时,该位硬件置1 。注意清除方式:先读SR寄存器、再读DR寄存器。

位7:发送数据寄存器空
STM32F103(二十三)通用同步异步收发器(USART)_第33张图片
注意清除方式:写读DR寄存器。

位8: LIN断开检测标志
STM32F103(二十三)通用同步异步收发器(USART)_第34张图片
位9:CTS标志
STM32F103(二十三)通用同步异步收发器(USART)_第35张图片

5、数据寄存器(USART_DR)

该寄存器只有低9位有效
STM32F103(二十三)通用同步异步收发器(USART)_第36张图片

数据寄存器分为发送数据寄存器TDR和接收数据寄存器RDR。

6、波特比率寄存器(USART_BRR)+波特率计算方法

STM32F103(二十三)通用同步异步收发器(USART)_第37张图片

该寄存器的的位15:4储存分频器除法因子的整数部分,位3:0储存分频除法因子的小数部分。

波特率计算:

STM32F103(二十三)通用同步异步收发器(USART)_第38张图片

STM32F1中USART1搭载在APB2线上,时钟最大为72MHZ;USART2、USART3、USART4、USART5搭载在APB1上,时钟最大为36MHZ。

以USART1、72MHZ时钟、115200波特率为例:

根据上述公式:

USARTDIV=72000000/(16*115200)=39.0625

十进制39=100111B=0x27,故将0x27存入BRR寄存器位15:4

小数部分转二进制:

STM32F103(二十三)通用同步异步收发器(USART)_第39张图片

故十进制0.0625=0.0001B=0x 0.1

故BRR寄存器位3:0存储 1

三、USART相关库函数

1、USART复位函数USART_DeInit()

STM32F103(二十三)通用同步异步收发器(USART)_第40张图片
该函数开启USARTx时钟,再打开,完成复位

2、USART初始化函数USART_Init()

STM32F103(二十三)通用同步异步收发器(USART)_第41张图片
参数1:
USART1~USART5

参数2:
结构体

成员:

  uint32_t USART_BaudRate;       		 //波特率    
  uint16_t USART_WordLength;      		 //字长 
  uint16_t USART_StopBits;        		 //停止位  
  uint16_t USART_Parity;            	 //校验码
  uint16_t USART_Mode;             		 //发送或接收模式
  uint16_t USART_HardwareFlowControl;	 //硬件控制流

3、结构体初始化函数USART_StructInit()

STM32F103(二十三)通用同步异步收发器(USART)_第42张图片

参数:
USART_Init()函数传递的那个结构体

操作:

波特率:9600
字长:8位
停止位:1位
校验位:无
模式:接收或发送
硬件控制流:无

4、同步模式下时钟配置函数USART_ClockInit()

STM32F103(二十三)通用同步异步收发器(USART)_第43张图片

参数1:
USART1~USART5

参数2:
结构体,成员:

typedef struct
{
     
  uint16_t USART_Clock;  //时钟使能
  uint16_t USART_CPOL;   //时钟极性
  uint16_t USART_CPHA;    //时钟相位
  uint16_t USART_LastBit; //时钟最后一个脉冲是否从ck输出
} USART_ClockInitTypeDef;

5、同步模式下初始化时钟配置结构体函数USART_ClockStructInit()

STM32F103(二十三)通用同步异步收发器(USART)_第44张图片

设置为:
①不使能同步时钟
②极性位0
③相位为0
④时钟脉冲最后一个周期不从Ck输出

6、USART使能函数USART_Cmd()

STM32F103(二十三)通用同步异步收发器(USART)_第45张图片
参数1:
USART1~USART5

参数2:
ENABLE 或DISABLE

7、USART中断配置函数USART_ITConfig()

STM32F103(二十三)通用同步异步收发器(USART)_第46张图片
参数1:
USART1~USART5

参数2:

USART_IT_PE          //奇偶校验错误中断               
USART_IT_TXE         //发送数据寄存器空中断              
USART_IT_TC          //发送完成中断       
USART_IT_RXNE        //接收数据就绪中断              
USART_IT_IDLE 	 	 //空闲总线中断
USART_IT_LBD          //断开标志中断              
USART_IT_CTS           //CTS中断      
USART_IT_ERR 		 //传输出错中断

参数3:
EnABLE 或DISABLE

8、DMA使能函数USART_DMACmd()

STM32F103(二十三)通用同步异步收发器(USART)_第47张图片

参数1:
USART1~USART5

参数2:
在这里插入图片描述

参数3:
ENABLE 或DISABLE

9、静默模式下设备地址设置函数USART_SetAddress()

STM32F103(二十三)通用同步异步收发器(USART)_第48张图片
该函数在多处理器通信下的静默模式中使用的,使用地址标记来唤醒某个USART设备。

参数1:
USART1~USART5

参数2:

小于0xf的一个数

10、静默模式下唤醒方式设置函数USART_WakeUpConfig()

STM32F103(二十三)通用同步异步收发器(USART)_第49张图片
参数1:
USART1~USART5

参数2:

在这里插入图片描述
分别为空闲总线唤醒、地址标记唤醒

11、设置静默模式函数USART_ReceiverWakeUpCmd()

STM32F103(二十三)通用同步异步收发器(USART)_第50张图片

参数1:
USART1~USART5

参数2:

ENABLE 或DISABLE

ENABLE 时将USARTx设置为静默模式,否则为正常工作模式。

12、LIN模式下断开符长度设置函数USART_LINBreakDetectLengthConfig()

STM32F103(二十三)通用同步异步收发器(USART)_第51张图片
参数1:
USART1~USART5

参数2:
在这里插入图片描述

13、使能LIN模式函数USART_LINCmd()

STM32F103(二十三)通用同步异步收发器(USART)_第52张图片
参数1:
USART1~USART5

参数2:

ENABLE 或DISABLE

14、发送数据函数USART_SendData()

STM32F103(二十三)通用同步异步收发器(USART)_第53张图片
参数1:
USART1~USART5

参数2:

一个小于等于0x1ff的数,DR寄存器为低9位有效寄存器

15、接收数据函数USART_ReceiveData()

STM32F103(二十三)通用同步异步收发器(USART)_第54张图片
参数1:
USART1~USART5

DR寄存器可读、写

16、发送断开符函数USART_SendBreak()

STM32F103(二十三)通用同步异步收发器(USART)_第55张图片
参数1:
USART1~USART5

17、状态获取函数USART_GetFlagStatus()与USART_GetITStatus()

STM32F103(二十三)通用同步异步收发器(USART)_第56张图片
参数1:
USART1~USART5

参数2:

USART_IT_PE          //奇偶校验错误中断               
USART_IT_TXE         //发送数据寄存器空中断              
USART_IT_TC          //发送完成中断       
USART_IT_RXNE        //接收数据就绪中断              
USART_IT_IDLE 	 	 //空闲总线中断
USART_IT_LBD          //断开标志中断              
USART_IT_CTS           //CTS中断      
USART_FLAG_ORE			//数据溢出中断
USART_FLAG_NE				//噪声标记中断
USART_FLAG_FE				//帧错误中断

返回:

返回SET表示发生中断
返回RESET表示未发生中断

18、清除标志位函数USART_ClearFlag()与USART_ClearITPendingBit

STM32F103(二十三)通用同步异步收发器(USART)_第57张图片
参数1:
USART1~USART5

参数2:

USART_IT_PE          //奇偶校验错误中断               
USART_IT_TXE         //发送数据寄存器空中断              
USART_IT_TC          //发送完成中断       
USART_IT_RXNE        //接收数据就绪中断              
USART_IT_IDLE 	 	 //空闲总线中断
USART_IT_LBD          //断开标志中断              
USART_IT_CTS           //CTS中断      
USART_FLAG_ORE			//数据溢出中断
USART_FLAG_NE				//噪声标记中断
USART_FLAG_FE				//帧错误中断

四、USART编程顺序

1、串口时钟和GPIO时钟使能

其中:
USART1使用RCC_APB2PeriphClockCmd()使能
USART2~5使用RCC_APB1PeriphClockCmd使能

2、串口复位(可不必)

使用USART_DeInit()函数复位串口

3、GPIO初始化(+一个重点说明

使用GPIO_Init()函数初始化GPIO

在《中文参考手册》GPIO章节的“外设的GPIO配置”中得到以下信息:
STM32F103(二十三)通用同步异步收发器(USART)_第58张图片

所以一定要注意在什么模式下,GPIO应该配置为什么模式。

最长用的是TX、RX全双工模式,所以TX引脚配置为推挽复用输出、RX引脚配置为浮空输入或上拉输入(空闲状态下,总线为高电平,所以可以为上拉输入)

4、串口初始化

使用 USART_Init()函数初始化串口

5、串口使能

使用USART_Cmd()函数使能串口

6、中断配置(如果需要)

使用USART_ITConfig()配置中断
如果配置了中断,需要设置NVIC中断分组,使用NVIC_Init()函数

7、发送和接收数据

使用USART_SendData()函数发送数据
使用USART_ReceiveData()函数接收数据

8、获取串口状态

使用USART_GetFlagStatus()函数获取USART状态

9、获取中断状态(如果需要)

使用USART_GetITStatus()函数获取中断状态

五、例1(发送一个字符到串口)

1、题

利用按键,通过串口1发送一个字符:按一下KEY_UP按键发送一个字符a;按一下KEY1发送一个字符b;按一下KEY2,发送一个字符c;按一下KEY3,发送字符d;通过串口监视器察看串口发送情况。

2、分析

按键实验STM32F103五分钟入门系列(五)按键实验(库函数+寄存器)总结过,不再赘述。

在串口设置中,PA9为USART1的TX引脚,设置为复用推挽输出。PA10为USART1的RX引脚,设置为浮空输入(本实验没用到输入,所以可以不设置)。没有接收,所以接收中断、中断优先级分组都不用设置。

需要用到串口监视器,所以需要通过跳线帽,将PA9、PA10与RS232的引脚连接,通过RS232与电脑USB连接在一起

3、代码

(1)按键代码

key.h代码:

#ifndef KEY_H
#define KEY_H
void KEY_Init(void);
#endif

key.c代码:

#include "stm32f10x.h"
#include "sys.h"
#include "key.h"
void KEY_Init(void)
{
     
	GPIO_InitTypeDef GPIO_InitStruct_A;
	GPIO_InitTypeDef GPIO_InitStruct_E;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOE , ENABLE);//使能GPIOA和GPIOE(PA0 PE2、3、4)
	
	GPIO_InitStruct_A.GPIO_Mode=GPIO_Mode_IPD;
	GPIO_InitStruct_A.GPIO_Pin=GPIO_Pin_0;
	GPIO_InitStruct_A.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStruct_A);//PA0 key_up  下拉输入
	
	GPIO_InitStruct_E.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_InitStruct_E.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;
	GPIO_InitStruct_E.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOE, &GPIO_InitStruct_E);//PE2、3、4 key0、key1、key2 上拉输入
}

(2)串口设置代码

myusart.h代码:

#ifndef _USART_
#define _USART_
#include "stm32f10x.h"
void Myusart_Init(u32);
#endif

myusart.c代码:

#include "myusart.h"
#include "stm32f10x.h"
void Myusart_Init(u32 baud)
{
     
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef  USART_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure); //TX
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure); //RX
	
	USART_InitStructure.USART_BaudRate=baud;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	USART_InitStructure.USART_Parity=USART_Parity_No;
	USART_InitStructure.USART_StopBits=USART_StopBits_1;
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStructure);
	
	USART_Cmd(USART1, ENABLE);
}

(3)主函数代码

#include "stm32f10x.h"
#include "myusart.h"
#include "delay.h"
#include "key.h"
char temp=0;
 int main(void)
 {
     	
	 Myusart_Init(115200);
	 KEY_Init();
	 delay_init(); 
	 while(1)
	 {
     
	 if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))//检测key_up按下
		{
     
			delay_ms(10);                                 //消抖
			while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0))//检测key_up按下
			{
     
				temp='a';
			}//取消按下key_up
			if(temp=='a')
			{
     
				USART_SendData(USART1,temp);
				temp=0;
			}
					
		}
	if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)//key0按下
		{
     
			delay_ms(10);  
			while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_4)==0)//key0按下
			{
     
				temp='b';
			}//取消按下key0
			if(temp=='b')
			{
     
				USART_SendData(USART1,temp);
				temp=0;
			}
		}
		
		
		else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)//key1按下
		{
     
			delay_ms(10);
			while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_3)==0)//key1按下
			{
     
				temp='c';
			}
			//取消按下key1
			if(temp=='c')
			{
     
				USART_SendData(USART1,temp);
				temp=0;
			}
		}
		else if(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0)//key2按下
		{
     
			delay_ms(10);  
			while(GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_2)==0)//key2按下
			{
     
				temp='d';
			}//取消按下key2
			if(temp=='d')
			{
     
				USART_SendData(USART1,temp);
				temp=0;
			}
		}
		
	 } 
  }

4、测试效果:

分别摁一下KEY_UP、KEY0~3:
STM32F103(二十三)通用同步异步收发器(USART)_第59张图片

六、例2(STM32F1、F4之间的串口通信)(+一个注意事项

注意:两块板子必须共地!虽然不同的板子布线不一样,但是如果是四层以上板子,只需要将两块板子的任意GND引脚连起来就行,这样的话两片板子的负片GND就连在一起了。

1、题

F1板子发送字符给F4板子,F4板子做以下操作:

①如果F4接收到字符a,LED0亮、LED1灭;延迟200ms,LED0灭、LED1亮,延迟200ms。两个灯只呼吸一次。
②如果F4接收到字符b,LED0、LED1同时亮、延时200ms后,同时灭。两个灯只呼吸一次。
③如果F4接收到字符c,LED0亮一次,延迟200ms后灭,LED1保持熄灭。LED0呼吸一次。
④如果F4接收到字符d,LED1亮一次,延迟200ms后灭,LED0保持熄灭。LED1呼吸一次。
如果没有接收到字符或接收到其它字符,则LED0、LED1保持熄灭状态。

2、分析

F4板子中,需要接收数据,所以需要配置接收完成中断,告诉单片机什么时候去读数。此外。由于呼吸灯只呼吸一次,所以每次执行完LED闪烁代码后,数据需要清零。

另外F1与F4的波特率要保持相同!

3、代码

(1)F1代码

F1代码与例1代码完全相同。

(2)F4的LED代码

led.h代码

#ifndef LED_H
#define LED_H
void LED_Init(void);

#endif

led.c代码

#include "sys.h"
#include "stm32f4xx.h"
#include "led.h"
void LED_Init(void)
{
     
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_OUT;
	GPIO_InitStructure.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9|GPIO_Pin_10;
	GPIO_InitStructure.GPIO_PuPd=GPIO_PuPd_NOPULL;
	GPIO_InitStructure.GPIO_Speed=GPIO_High_Speed;
	GPIO_Init(GPIOF,&GPIO_InitStructure);
	
	GPIO_SetBits(GPIOF, GPIO_Pin_9|GPIO_Pin_10);//PB5置高电平
}

(3)串口设置代码

myusart.h代码

 #ifndef _USART_
#define _USART_
#include "stm32f4xx.h"
void Myusart_Init(u32);
#endif

myusart.c代码

#include "myusart.h"
#include "stm32f4xx.h"
#include "sys.h"
void Myusart_Init(u32 baud)
{
     
	 GPIO_InitTypeDef  GPIO_InitStructure;
	 USART_InitTypeDef  USART_InitStructure;
	 NVIC_InitTypeDef  NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); 
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); 
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;	//速度100MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
	
	USART_InitStructure.USART_BaudRate=baud;
	USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;
	USART_InitStructure.USART_Parity=USART_Parity_No;
	USART_InitStructure.USART_StopBits=USART_StopBits_1;
	USART_InitStructure.USART_WordLength=USART_WordLength_8b;
	USART_Init(USART1,&USART_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ; //抢占优先级 3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级 3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure); 

	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	USART_Cmd(USART1, ENABLE);
}

extern u16 temp;
void USART1_IRQHandler()
{
     
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{
     
		temp=USART_ReceiveData(USART1);
	}	
}

(4)主函数代码

#include "stm32f4xx.h"
#include "myusart.h"
#include "delay.h"
#include "led.h"
u16 temp=0;
int main(void)
{
     
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	Myusart_Init(115200);
	LED_Init();
	delay_init(168);
	while(1)
	{
     
		if(temp=='a')
		{
     
			PFout(9)=0;//点亮LED0
			PFout(10)=1;//熄灭LED1
			delay_ms(200);
			PFout(9)=1; //熄灭LED0
			PFout(10)=0;//点亮LED1
			delay_ms(200);
			temp=0;
		}
		
		else if(temp=='b')
		{
     
			PFout(9)=0;
			PFout(10)=0;
			delay_ms(200);
			PFout(9)=1;
			PFout(10)=1;
			delay_ms(200);
			temp=0;
		}
		
		else if(temp=='c')
		{
     
			PFout(9)=0;
			PFout(10)=1;
			delay_ms(200);
			PFout(9)=1;
			delay_ms(200);
			temp=0;			
		}
		
		else if(temp=='d')
		{
     
			PFout(9)=1;
			PFout(10)=0;
			delay_ms(200);
			PFout(10)=1;
			delay_ms(200);
			temp=0;
		}
		else 
		{
     
			PFout(9)=1;
			PFout(10)=1;
		}
	}	
}

4、硬件连接

1、F1的TX(PA9)连接F4的RX(PA10)

2、F1与F4的任意GND引脚连接

5、效果

按下KEY_UP键后:

按下KEY0后:

按下KEY1后:

按下KEY2键后:

七、例3(对例2的修改)

如果想让LED一直闪烁,可以将主函数中对temp的清零注释掉。
STM32F103(二十三)通用同步异步收发器(USART)_第60张图片

你可能感兴趣的:(STM32F107,stm32,单片机,arm)