USART
中英文对照
TX transmit 传送
RX receive接收
串口通讯协议
分层
物理层规定我们用嘴巴还是用肢体来交流(硬件部分)
协议层则规定我们用中文还是英文来交流(软件部分)
物理层标准
RS232&RS485标准
可见RS232和TTL传输速率差别很大
一般直接从单片机中出来的电平都是TTL电平
51单片机中是5V,stm32中是3.3V
RS232标准串口主要用于工业设备直接通信,因为它的电平差值30V,容错能力很强
电平转换芯片一般有MAX3232(这个就是我们电路板上面所使用的),SP3232
USB转串口
USB常用TTL电平,串口常用电平RS232
1、USB转串口主要用于设备跟电脑通信
2、电平转换芯片一般有CH340、PL2303、CP2102、FT232
3、使用的时候电脑端需要安装电平转换芯片的驱动
原生的串口到串口
TTL到TTL
1、原生的串口通信主要是控制器跟串口的设备或者传感器通信,不需要经过电平转换芯片来转换电平,直接就用TTL电平通信
2、GPS模块、GSM模块、串口转WIFI模块、HC04蓝牙模块
协议层标准
协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准
起始位:由1个逻辑 0 的数据位表示
结束位:由 0.5、 1、 1.5 或 2 个逻辑 1 的数据位表示
有效数据:在起始位后紧接着的就是有效数据,有效数据的长度常被约定为 5、 6、 7 或 8 位长
STM32串口功能框图讲解
引脚
均为GPIO引脚
TX:数据发送
RX:是数据接收
SCLK:时钟,仅同步通信时使用(而我们一般都是用的异步,故不用看)
nRTS:请求发送(Request To Send)
nCTS:允许发送(Clear To Send)
注意串口1挂载到APB2,而其他的挂载到APB1,所以对应时钟也不同
对于可复用的引脚,在初始化时可以通过AFIO重映射配置成所需功能引脚
数据寄存器
USART_DR:9位有效,包含一个发送数据寄存器TDR和一个接收数据寄存器RDR。一个地址对应了两个物理内存。
控制器
数据发送&接受状态和控制寄存器
USART_CR1:M,0:8bit,1:9bit
USART_CR2:STOP
USART_CR1:PCE(Parity control enable检验控制使能)、PS(Parity Selection检验选择)、PEIE(PE中断使能)
USART_SR :PE(Parity error校验错误)
USART_CR1:UE(USART enable)、TE(transmitter enable)、RE(receiver enable)
编程时要令UE=1,TE=1
USART_SR:TXE,Transmit data register empty发送数据寄存器空
USART_CR1:TXEIE发送缓冲区空中断使能
USART_SR:TC,Transmission complete发送完成
USART_CR1:TCIE发送完成中断使能
USART_SR:RXNE,Read data register not empty读数据寄存器非空
USART_CR1:RXNEIE接收缓冲区非空中断使能
波特率
USART_BRR:波特率寄存器
USARTDIV:无符号的定点数
FCK:串口的时钟,注意区分APB2和APB1两条总线
常用波特率:115200 9600 4800
写入时4位精度1/16
Eg:USART:USART1,时钟为72M
波特率:115200
串口初始化结构体
DeInit(default init) 默认初始化:将所有寄存器复位成初始时状态
cmd是command的缩写.即命令提示符(CMD)
代码讲解
中断接收和发送
编程要点
1-初始化串口需要用到的GPIO
2-初始化串口,USART_InitTypeDef
3-中断配置(接收中断,中断优先级)
4-使能串口
5-编写发送和接收函数
6-编写中断服务函数
1 #include "bsp_usart.h" 2 3 /** 4 * @brief USART GPIO 配置,工作参数配置 5 * @param 无 6 * @retval 无 7 */ 8 void USART_Config(void) 9 { 10 GPIO_InitTypeDef GPIO_InitStructure; 11 USART_InitTypeDef USART_InitStructure; 12 13 // 打开串口GPIO的时钟 14 DEBUG_USART_GPIO_APBxClkCmd(DEBUG_USART_GPIO_CLK, ENABLE); 15 16 // 打开串口外设的时钟 17 DEBUG_USART_APBxClkCmd(DEBUG_USART_CLK, ENABLE); 18 19 // 将USART Tx的GPIO配置为推挽复用模式 20 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_TX_GPIO_PIN; 21 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 22 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 23 GPIO_Init(DEBUG_USART_TX_GPIO_PORT, &GPIO_InitStructure); 24 25 // 将USART Rx的GPIO配置为浮空输入模式 26 GPIO_InitStructure.GPIO_Pin = DEBUG_USART_RX_GPIO_PIN; 27 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; 28 GPIO_Init(DEBUG_USART_RX_GPIO_PORT, &GPIO_InitStructure); 29 30 // 配置串口的工作参数 31 // 配置波特率 32 USART_InitStructure.USART_BaudRate = DEBUG_USART_BAUDRATE; 33 // 配置 针数据字长 34 USART_InitStructure.USART_WordLength = USART_WordLength_8b; 35 // 配置停止位 36 USART_InitStructure.USART_StopBits = USART_StopBits_1; 37 // 配置校验位 38 USART_InitStructure.USART_Parity = USART_Parity_No ; 39 // 配置硬件流控制 40 USART_InitStructure.USART_HardwareFlowControl = 41 USART_HardwareFlowControl_None; 42 // 配置工作模式,收发一起 43 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; 44 // 完成串口的初始化配置 45 USART_Init(DEBUG_USARTx, &USART_InitStructure); 46 47 // 使能串口 48 USART_Cmd(DEBUG_USARTx, ENABLE); 49 } 50 51 /***************** 发送一个字符 **********************/ 52 void Usart_SendByte( USART_TypeDef * pUSARTx, uint8_t ch) 53 { 54 /* 发送一个字节数据到USART */ 55 USART_SendData(pUSARTx,ch); 56 57 /* 等待发送数据寄存器为空 */ 58 while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); 59 } 60 61 /***************** 发送字符串 **********************/ 62 void Usart_SendString( USART_TypeDef * pUSARTx, char *str) 63 { 64 unsigned int k=0; 65 do 66 { 67 Usart_SendByte( pUSARTx, *(str + k) ); 68 k++; 69 } while(*(str + k)!=‘\0‘); 70 71 /* 等待发送完成 */ 72 while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TC)==RESET) 73 {} 74 } 75 76 /***************** 发送一个16位数 **********************/ 77 void Usart_SendHalfWord( USART_TypeDef * pUSARTx, uint16_t ch) 78 { 79 uint8_t temp_h, temp_l; 80 81 /* 取出高八位 */ 82 temp_h = (ch&0XFF00)>>8; 83 /* 取出低八位 */ 84 temp_l = ch&0XFF; 85 86 /* 发送高八位 */ 87 USART_SendData(pUSARTx,temp_h); 88 while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); 89 90 /* 发送低八位 */ 91 USART_SendData(pUSARTx,temp_l); 92 while (USART_GetFlagStatus(pUSARTx, USART_FLAG_TXE) == RESET); 93 } 94 95 ///重定向c库函数printf到串口,重定向后可使用printf函数 96 int fputc(int ch, FILE *f) 97 { 98 /* 发送一个字节数据到串口 */ 99 USART_SendData(DEBUG_USARTx, (uint8_t) ch); 100 101 /* 等待发送完毕 */ 102 while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_TXE) == RESET); 103 104 return (ch); 105 } 106 107 ///重定向c库函数scanf到串口,重写向后可使用scanf、getchar等函数 108 int fgetc(FILE *f) 109 { 110 /* 等待串口输入数据 */ 111 while (USART_GetFlagStatus(DEBUG_USARTx, USART_FLAG_RXNE) == RESET); 112 113 return (int)USART_ReceiveData(DEBUG_USARTx); 114 }
main函数
1-如何发送16位的数据?
Usart_SendByte(DEBUG_USARTx,‘A‘);
Usart_SendHalfWord(DEBUG_USARTx, 0xff56);
2-如何发送一个数组&字符串?
Usart_SendArray(DEBUG_USARTx, a,10);
Usart_SendStr(DEBUG_USARTx, "欢迎使用秉火STM32F103开发板 \n");
3-如何使用printf()?如何使用scanf()?
4-电脑端发送过来的数据是什么格式的?十进制?十六进制?字符?
对字(Word)、半字(Half-Word)、字节(Byte)的概念说明如下:
1.字(Word):在ARM体系结构(32位机)中,字的长度为32位,而在8位/16位处理器体系结构中,字的长度一般为16位。
2.半字(Half-Word):在ARM体系结构(32位机)中,半字的长度为16位,与8位/16位处理器体系结构中字的长度一致。即65535=0xffff
3.字节(Byte):在ARM体系结构(32位机)和8位/16位处理器体系结构中,字节的长度均为8位。即255=1111 1111=0xff
#include "stm32f10x.h" // 相当于51单片机中的 #include <reg51.h> #include "bsp_led.h" #include "bsp_exit.h" #include "bsp_usart.h" int main(void) { //来到这里的时候,系统的时钟已经被配置成72M。 //USART和上位机交互 uint8_t a[10]={100,2,3,4,5,6,7,8,9,10};//声明必须在前面 USART_Config(); /*初始化USART 配置模式为 115200 8-N-1,中断接收*/ //默认发送的是字符,当不是字符时候,会自动将其转换成相对于的ASCII值 100对应d //当然你也可以这样: ‘A‘ 或者在上位机上选择16进制 //Usart_SendByte(USART1, 100); //Usart_SendByte(USART1,‘A‘); //Usart_SendHalfWord(USART1, 0xff56); //printf( "串口printf函数测试\n" ); //Usart_SendStr(USART1, "欢迎使用秉火STM32F103开发板 \n"); Usart_SendArray(USART1, a,10); while(1){ } }
串口控制RGB灯亮灭
原文:https://www.cnblogs.com/sunny-sky/p/12727208.html