1、通用同步异步通信USART微信公众号:讲编程的高老师8本章目标 了解串行通信的概念 掌握STM32F103xx中USART的结构和功能 掌握串口的配置方法 掌握使用库函数控制STM32F103xx的串口来发送和接收数据的方法目录/Contents8.18.1串行通信原理概述8.28.2STM32F103xx的串口工作原理8.38.3应用案例1:串口查询方式接收8.48.4应用案例2:串口中断方式接收8.58.5小结目录/Contents8.18.1串行通信原理概述一、串行通信的硬件连接二、异步串行通信的数据帧串行通信的硬件连接两台工作电平标准相同的单片机之间只需将发送端(TXD)和接收端(RX
2、D)交叉连接,再将参考零电位引脚相连接串行通信的硬件连接单片机实现两个RS-232通信接口的电路通信标准通信标准电平标准电平标准5V TTL逻辑1:2.45V逻辑0:00.5VRS-232逻辑1:-15-3V逻辑0:+3+15V串行通信的硬件连接USB转串口后与单片机通信电路原理图异步串行通信的数据帧异步串行通信示意图字符帧的结构目录/Contents8.18.1串行通信原理概述8.28.2STM32F103xx的串口工作原理8.38.3应用案例1:串口查询方式接收8.48.4应用案例2:串口中断方式接收8.58.5小结目录/Contents8.28.2STM32F103xx的串口工作原理一、
3、USART的结构框图二、利用库函数设置和使用串口三、数据发送与接收USART的结构框图波特率控制中断控制收发控制数据存储与转移利用库函数设置和使用串口函数名函数名 描述描述RCC_APB2PeriphClockCmd串口时钟使能及GPIO时钟使能USART_DeInit串口复位GPIO_Init串口参数初始化USART_ITConfig开启中断并且初始化NVICUSART_Cmd使能串口数据发送与接收函数名函数名 描述描述USART_SendData向串口寄存器USART_DR写入一个数据(发送数据)USART_ReceiveData读取串口接收到的数据USART_GetFlagStatus读
4、取串口状态目录/Contents8.18.1串行通信原理概述8.28.2STM32F103xx的串口工作原理8.38.3应用案例1:串口查询方式接收8.48.4应用案例2:串口中断方式接收8.58.5小结目录/Contents8.38.3应用案例1:串口查询方式接收一、目标二、仿真电路设计三、运行结果案例1目标 能通过查询方式接收数据,每接收到一个字节,立即向对方发送一个相同内容的字节,并把该字节的十六进制码显示在两位数码管上。使用STM32F103R6串口1,实现:仿真电路1a1b1c1d1e1f1g1dp2a2b2c2d2e2f2g2dp2c1g1a1b2dp1c2g1d2f1e2e1f2
5、d1dp2b2aBOOT060NRST7PA0-WKUP14OSCIN_PD05OSCOUT_PD16PB861PA216PA115PA317PA420PB962PA521PA622PA723PA841PA942PB1029PA1043PB026PB127PB228PB355PB1130PB456PB557PB658PB759PC19PC210PC08PC424PC525PC311PC738PC839PC637PC1051PC1152PC940PB1233PB1334PB1435PB1536PA1144PA1245PA1346PA1449PA1550PC1253PD254PC13_RTC2PC
6、14-OSC32_IN3PC15-OSC32_OUT4VBAT1U1STM32F103R6ERRORTXD3RXD2CTS8RTS7DSR6DTR4DCD1RI9P1COMPIMSEG2SEG1R2R1R3R4R5R6R7R8R10R9R11R12R13R14R15R16510R虚拟串口软件Virtual Serial Port Driver创建COM1、COM2虚拟串口软件占用COM2,向COM1(单片机端)发送数据代码实现usart.h1.#include vartypes.h2.#include stdio.h /为重定向为重定向printf函数作准备函数作准备3.4.#ifndef _
7、USART_H5.#define _USART_H6.7.void usart_init(Int32U baud);8.extern Int08U Receive_byte;9.#endif10.usart.c/Filename:usart.c#include includes.hInt08U Receive_byte;void usart_init(Int32U baud)GPIO_InitTypeDef GPIO_InitStructure;/GPIO初始化结构体初始化结构体 USART_InitTypeDef USART_InitStructure;/串口初始化结构串口初始化结构 RCC
8、_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);/使能使能USART1,GPIOA时钟时钟 USART_DeInit(USART1);/复位串口复位串口1 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;/USART1_TX GPIOA.9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;/复用推挽输出复用推挽输出 GPIO_Init(G
9、PIOA,&GPIO_InitStructure);/初始化初始化GPIOA.9 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;/USART1_RX GPIOA.10初始化初始化 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;/浮空输入浮空输入 GPIO_Init(GPIOA,&GPIO_InitStructure);/初始化初始化GPIOA.10 USART_InitStructure.USART_BaudRate=baud;/串口波特率串口波特率 USART_InitStructure.USART_W
10、ordLength=USART_WordLength_8b;/字长为字长为8位数据格式位数据格式 USART_InitStructure.USART_StopBits=USART_StopBits_1;/一个停止位一个停止位 USART_InitStructure.USART_Parity=USART_Parity_No;/无奇偶校验位无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;/无硬件数据流控制无硬件数据流控制 USART_InitStructure.USART_Mod
11、e=USART_Mode_Rx|USART_Mode_Tx;/收发模式收发模式 USART_Init(USART1,&USART_InitStructure);/初始化串口初始化串口1 USART_Cmd(USART1,ENABLE);/使能串口使能串口1/加入以下代码加入以下代码,支持支持printf函数函数/fputc函数重定向函数重定向 需要包含头文件需要包含头文件stdio.h,并且勾选,并且勾选Options Target对话框对话框Target选项卡中的选项卡中的use MicroLIBint fputc(int ch,FILE*f)USART_SendData(USART1,(u
12、int8_t)ch);/USART1发送一个字符数据发送一个字符数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)=RESET);/等待发送完毕等待发送完毕 return ch;usart_Init()初始化串口Led.h/Filename:led.h#include vartypes.h#ifndef _LED_H#define _LED_H void LED_Init(void);#endif usart.c/Filename:led.c#include includes.h void LED_Init(void)GPIO_InitType
13、Def GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);/使能使能PB端口时钟端口时钟 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_All;/配置配置PB全部端口全部端口 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;/推挽输出推挽输出 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;/IO口速度为口速度为10MHz GPIO_Init(GPIOB,&GPIO_InitStruct
14、ure);/根据设定参数初始化根据设定参数初始化GPIOB LED_Init()初始化数码管相关的IO端口对system_stm32f10 x.c进行修改/void SystemInit(void)RCC_DeInit();/将外设将外设 RCC寄存器重设为缺省值寄存器重设为缺省值 RCC_HSICmd(ENABLE);/使能使能HSI while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY)=RESET);/等待等待HSI使能成使能成功功 RCC_HCLKConfig(RCC_SYSCLK_Div1);/设置设置AHB时钟时钟 HCLK=SYSCLK/1 RCC_PC
15、LK1Config(RCC_HCLK_Div4);/设置低速速设置低速速AHB时钟时钟 RCC_PCLK2Config(RCC_HCLK_Div1);/设置高速设置高速AHB时钟时钟 /设置设置 PLL 时钟源及倍频系数时钟源及倍频系数 RCC_PLLConfig(RCC_PLLSource_HSI_Div2,RCC_PLLMul_12);/8M/2=4M,4M*12=48M,在在Proteus中要设置中要设置CPU工作频率为工作频率为48M,否则串行通信会出错,否则串行通信会出错 RCC_PLLCmd(ENABLE);/使能使能PLL /等待指定的等待指定的 RCC 标志位设置成功标志位设置
16、成功 等待等待PLL初始化成功初始化成功 while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY)=RESET);/设置系统时钟(设置系统时钟(SYSCLK)设置设置PLL为系统时钟源为系统时钟源 RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);/选择想要的系统时钟选择想要的系统时钟 /等待等待PLL成功用作于系统时钟的时钟源成功用作于系统时钟的时钟源 while(RCC_GetSYSCLKSource()!=0 x08);/0 x08:PLL作为系统时钟作为系统时钟SystemInit()初始化配置系统时钟源经过测试,在Proteu
17、s仿真平台中,当STM32F103xx使用外部晶振(HSE)作为系统时钟源时,会导致波特率不准确,从而导致通信失败。为此,要在system_stm32f10 x.c文件中修改SystemInit函数。system_stm32f10 x.c文件是非常重要的系统文件,修改时必须谨慎!建议将原来的SystemInit函数名称修改为SystemInit0,再增加新的SystemInit函数。在实际硬件平台运行程序时,无需对system_stm32f10 x.c文件作这样的修改。main.c/filename:main.c#include includes.hint main(void)Int08U l
18、ed_table16=0 xc0,0 xf9,0 xa4,0 xb0,0 x99,0 x92,0 x82,0 xf8,0 x80,0 x90,0 x88,0 x83,0 xc6,0 xa1,0 x86,0 x8e;/共阳字型编码共阳字型编码 Int16U desplay_word;/两位数码管显示字(两字节)两位数码管显示字(两字节)Receive_byte=0 x00;/数码管显示初值数码管显示初值“00”usart_init(9600);/串口初始化波特率为串口初始化波特率为9600 LED_Init();/LED端口初始化端口初始化 printf(Hello USART!);/测试测试p
19、rintf是否可用是否可用 while(1)if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)!=RESET)/接收数据位非空标志位不为零,即接收到了数据接收数据位非空标志位不为零,即接收到了数据 Receive_byte=USART_ReceiveData(USART1);/把接收到的数据传送到变量把接收到的数据传送到变量 USART_ClearFlag(USART1,USART_FLAG_RXNE);/读数据寄存器非空标志清除读数据寄存器非空标志清除 USART_SendData(USART1,Receive_byte);/向串口向串口1发送相同的
20、数据发送相同的数据 while(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);/等待发送结束等待发送结束 desplay_word=(led_tableReceive_byte4 8)|led_tableReceive_byte&0 x0f;/把刚接收到的字符转换为显示码把刚接收到的字符转换为显示码 GPIO_Write(GPIOB,desplay_word);/PB口输出显示口输出显示 在main函数中调用usart初始化函数,配置波特率为9600bps。在while循环中,用USART_GetFlagStatus函数查询USART1是否接收
21、到数据,如果接收到数据,调用USART_ReceiveData 数据把数据传到Receive_byte 变量。接收到的数据传送完成之后,把读数据寄存器非空标志清除。调用了USART_SendData函数向外发送一个字符(Receive_byte 变量中的内容),把接收到的数据重新发送出去。执行发送后,等待发送完成标志。最后把刚接收到的数据转换为显示码,从PB端口输出。仿真运行效果目录/Contents8.18.1串行通信原理概述8.28.2STM32F103xx的串口工作原理8.38.3应用案例1:串口查询方式接收8.48.4应用案例2:串口中断方式接收8.58.5小结目录/Contents8
22、.48.4应用案例2:串口中断方式接收一、安例2目标二、仿真电路设计三、运行效果案例2目标 通过中断方式接收数据,每接收到一个字节,立即向对方发送一个相同内容的字节,并把该字节的十六进制码显示在两位数码管上使用STM32F103R6串口1,实现:电路和调试方法与案例1相同,只有程序代码有点差异!程序代码的不同之处 串口初始化配置(使能接收中断)增加串口中断服务函数 main函数中的while循环内删除串口查询接收代码。在案例1代码的基础上进行修改usart.c/void usart_init(Int32U bound)GPIO_InitTypeDef GPIO_InitStructure;/G
23、PIO初始化结构体初始化结构体 USART_InitTypeDef USART_InitStructure;/串口初始化结构体串口初始化结构体 NVIC_InitTypeDef NVIC_InitStructure;/中断初始化结构体中断初始化结构体 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA,ENABLE);/使能使能USART1,GPIOA时钟时钟 USART_DeInit(USART1);/复位串口复位串口1 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;/USART1
24、_TX GPIOA.9 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;/复用推挽输出复用推挽输出 GPIO_Init(GPIOA,&GPIO_InitStructure);/初始化初始化GPIOA.9 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_10;/USART1_RX GPIOA.10初始化初始化 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IN_FLOATING;/浮空输入浮空输入 GPI
25、O_Init(GPIOA,&GPIO_InitStructure);/初始化初始化GPIOA.10 /Usart1 中断中断 配置配置 NVIC_InitStructure.NVIC_IRQChannel=USART1_IRQn;/设置串口设置串口1中断中断 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;/抢占优先级抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;/子优先级子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd=ENABL
26、E;/IRQ通道使能通道使能 NVIC_Init(&NVIC_InitStructure);/根据指定的参数初始化根据指定的参数初始化VIC寄存器寄存器 USART_InitStructure.USART_BaudRate=bound;/串口波特率串口波特率 USART_InitStructure.USART_WordLength=USART_WordLength_8b;/字长为字长为8位数据格式位数据格式 USART_InitStructure.USART_StopBits=USART_StopBits_1;/一个停止位一个停止位 USART_InitStructure.USART_Pari
27、ty=USART_Parity_No;/无奇偶校验位无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl=USART_HardwareFlowControl_None;/无硬无硬件数据流控制件数据流控制 USART_InitStructure.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;/收发模收发模式式 USART_Init(USART1,&USART_InitStructure);/初始化串口初始化串口1 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);/开启串口接
28、收中断开启串口接收中断 USART_Cmd(USART1,ENABLE);/使能串口使能串口1 usart_Init()初始化串口串口1中断使能usart.cvoid USART1_IRQHandler(void)/串口串口1中断服务函数中断服务函数 if(USART_GetITStatus(USART1,USART_IT_RXNE)!=RESET)/接收到接收到数据数据 Receive_byte=USART_ReceiveData(USART1);/读取接收到的数据读取接收到的数据 USART_SendData(USART1,Receive_byte);/向串口向串口1发送数据发送数据 wh
29、ile(USART_GetFlagStatus(USART1,USART_FLAG_TC)!=SET);/等等待发送结束待发送结束 USART1_IRQHandler()串口1中断服务函数目录/Contents8.18.1串行通信原理概述8.28.2STM32F103xx的串口工作原理8.38.3应用案例1:串口查询方式接收8.48.4应用案例2:串口中断方式接收8.58.5小结本章小结 介绍了串口配置、查询方式接收数据和中断方式接收数据的方法。给出了两个项目实例,串口查询方式接收、串口中断方式接收。与实际硬件平台相比较,仿真平台的STM32F103xx串行通信功能目前还存在一定的局限性。本章主要内容谢谢观赏微信公众号:讲编程的高老师