stm32串口自定义协议接收一串十六进制数据(将其中两个字节转化为十进制数据)+部分串口基础知识 | 您所在的位置:网站首页 › 将十六进制数6d268转换为二进制数 › stm32串口自定义协议接收一串十六进制数据(将其中两个字节转化为十进制数据)+部分串口基础知识 |
文章目录
一、基本储存单元二、通信协议(一)并行通信和串行通信(二)三种工作方式(三)收发数据同步或异步传输(四)通信速率
三、串口通信协议(一)RS232(二)USB转串口(TTL标准)(三)串口到串口(TTL->TTL)(四)串口数据包的基本组成
四、寄存器(一)状态寄存器:USART_SR(二)数据寄存器USART_DR(三)控制寄存器1(USART_CR1)(四)串口接收和发送数据
五、STM32固件库函数六、USART应用(一)发送数据1、函数1-串口发送一个字节数据2、函数2-发送两个字节数据3、函数3-发送一个数组数据4、函数4-发送字符串函数5、函数5-使用printf函数进行打印数据6、函数6-使用getchar函数
(二)接收数据1、串口助手发送并返回数据中断函数2、串口发送数据控制led亮灭3、STM32自定义协议接收十六进制数据(使用三合一气体传感器求出CO2浓度)
一、基本储存单元
位(bit): 二进制数中的一个数位,可以是0或者1,是计算机中数据的最小单位。 字节(Byte): 计算机中数据的基本单位,每8位组成一个字节。各种信息在计算机中存储、处理至少需要一个字节。 例如,一个ASCII码用一个字节表示,一个汉字用两个字节表示。 字(Word): 两个字节称为一个字。汉字的存储单位都是一个字。 1个字节(byte)=8位(bit)数据 1个汉字是一个字,即两个字节,16位数据 二、通信协议通信方式-框图-参考链接 (一)并行通信和串行通信并行通信 8位数据并列的传输,传一个8位的数据是需要8根线一起传输。 例如:SDIO,FSMC(16位的)–发送数据都是所有数据位同时传输 串行通信 8位数据一位一位的传输,只需要一根线即可进行传输。 例如:USART,IIC,SPI三种都是串行方式-----发送数据时都是一位一位的进行发送数据 串行通信与并行通信特征 全双工 有两根数据线,一个用来接收数据,一个用来发送数据,互不干扰,可以同时发送和接收数据。 例如:usart(可以半双工或全双工通信),SPI(可以半双工或者全双工通信) 半双工 有两根数据线,但是不可以同时发送数据,可以分时收发数据 单工 只有一根数据线,只可以单向通信(只可以往某一个方向进行) 例如:IIC 000-串口通讯的单工、半双工和全双工的定义、区别及应用- (三)收发数据同步或异步传输同步通信 数据同步方式,两个设备的时钟信号是同一个(有时钟信号的是同步)。 在传输数据时为了保证数据传输的准确性: (1)时钟在高电平时,数据有效 (2)时钟信号在低电平时数据时无效的 (3)对时钟的要求很高(如果时钟有尖峰或者杂波,则数据传输就不准确了) 例如:SPI,IIC通信接口。 异步通信 没有时钟信号:为了保证数据传输的准确性是通过加上一些辅助的标识符 例如:UART(通用异步收发器),单总线。 同步通信和异步通信比较 (1)在同步通信中,数据信号所传输的内容绝大部分就是有效数据。 (2)在异步通信中,传输的数据会包含有帧的各种标识符。 (3)所以同步通信的效率更好,但是对于时钟允许误差较小,异步通信对于时钟允许误差较大。 (四)通信速率比特率:每秒钟传输的二进制数单位:bit/s IIC,SPI(同步通信,一个时钟下传输一个数据,通过时钟来控制) 波特率:每秒钟传输的码元个数(串口) 一个二进制位表示一个码元(特殊情况下) 三、串口通信协议物理层规定我们用嘴巴还是肢体进行交流 协议层就是规定我们用汉语还是英文来交流 (一)RS2321、RS232和TTL就是在电平上的区别 TTL电平是直接从单片机(或者芯片)里面出来的:高电平用3.3V或者5v来表示,低电平用0表示 RS232中1用-15V表示,0用+15V表示,逻辑正好时相反的,低电平和高电平的差距非常大 TXE-发送数据寄存器空 当TDR寄存器中的数据被硬件转移到移位寄存器的时候,TXE位被硬件置位。 如果USART_CR1寄存器中的TXEIE为1,则产生中断。对USART_DR的写操作,将该位清零。 0-数据还没有转移到移位寄存器 1-数据已经转移到移位寄存器 TC-发送完成 当包含有数据的一帧发送完成后,并且TXE=1时,由硬件将TC位置’1’。 如果USART_CR1中的TCIE=1,则产生中断。由软件序列清除该位(先读USART_SR,然后写入USART_DR)。 TC位也可以通过写入’0’来清除,只有在多缓存通讯中才推荐这种清除程序。 0-发送还没有完成 1-发送已经完成 RXNE-读数据寄存器非空 当RDR移位寄存器中的数据被转移到USART_DR寄存器中,该位(RXNE)被硬件置位。 如果USART_CR1寄存器中的RXNEIE=1,则产生中断。对USART_DR的读操作可以将该位清零。 RXNE位也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。 0-数据没有收到 1-收到数据可以读出 (二)数据寄存器USART_DR此时UE=1,TE=1 上图对应的顺序依次是1->2->3,数据来源于CPU或者DMA,数据来了之后首先是放到发送寄存器(TDR)中,然后会再放到发送数据移位寄存器中,由于数据是8位的,会将数据一位一位的发送出去(使用TX引脚)。 当数据由发送寄存器到发送数据移位寄存器时,TXE会被置1,即TXE=1,表示发送数据寄存器为空了,但是并不表示数据已经发送出去了。因为还要通过发送移位寄存器进行一位一位的发送数据,如果发送移位寄存器数据全部发送出去了,TC会被置1,即TC=1表示发送数据完毕。** 接收数据流程**
串口初始化函数 void USART_Init(USART_TypeDef* USARTx, USART_InitTypeDef* USART_InitStruct);引脚、波特率、位数,校验、时钟等串口使能 USART_Cmd(USART1, ENABLE); //使能串口—配置的是UE位中断使能 void USART_ITConfig(USART_TypeDef* USARTx, uint16_t USART_IT,FunctionalState NewState)发送数据 STM32 库函数操作 USART_DR 寄存器发送数据的函数是:通过该函数向串口寄存器 USART_DR 写入一个数据。 void USART_SendData(USART_TypeDef* USARTx, uint16_t Data);接收数据 STM32 库函数操作 USART_DR 寄存器读取串口接收到的数据的函数是:通过该函数可以读取串口接收到的数据。 uint16_t USART_ReceiveData(USART_TypeDef* USARTx);获取标志位 该函数只判断标志位。在没有使能相应的中断函数时,通常使用该函数来判断标志位是否置1 Flagstatus USART_GetFlagStatus(USARTx,USART_FLAG)中断状态位获取函数 不仅会判断标志位是否置1,同时还会判断是否使能了相应的中断。所以在串口中断函数中,如果要获取中断标志位,通常使用该函数。 ITStatus USART_GetITStatus(USART_TypeDef* USARTx, uint16_t USART_IT)清楚中断标志位 Void USART_Flag_Clear(USARTx,USART_FLAG)几个标志位函数的区分说明–链接 六、USART应用串口初始化函数 //初始化IO 串口1 //bound:波特率 void uart_init(u32 bound){ //GPIO端口设置 GPIO_InitTypeDef GPIO_InitStructure;//GPIO结构体指针 USART_InitTypeDef USART_InitStructure;//串口结构体指针 NVIC_InitTypeDef NVIC_InitStructure;//中断分组结构体指针 //1、使能串口时钟,串口引脚时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA时钟 //2、复位串口 USART_DeInit(USART1); //复位串口1 //3、发送接收引脚的设置 //USART1_TX PA.9(由图 可知设置为推挽复用输出) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA9 //USART1_RX PA.10(有图可知浮空输入) GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入 GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化PA10 //4、USART 初始化设置 USART_InitStructure.USART_BaudRate = bound;//一般设置为9600; USART_InitStructure.USART_WordLength = 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_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式 USART_Init(USART1, &USART_InitStructure); //初始化串口 #if EN_USART1_RX //如果使能了接收 //5、Usart1 NVIC 配置 NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//抢占优先级3 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能 NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器 //6、开启接收数据中断 USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启中断 #endif //7、使能串口 USART_Cmd(USART1, ENABLE); //使能串口 } (一)发送数据 1、函数1-串口发送一个字节数据 void Usart_SendByte(USART_TypeDef* pUSARTx,uint8_t data) { //调用固件库函数 USART_SendData(pUSARTx,data);//往串口中写入数据 //发送完数据是检测TXE这个位是否置1,发送数据寄存器空了,表明已经把数据传递到数据移位寄存器了 //检测TXE这个位也需要一个固件库函数 while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE)==RESET); //如果这个位一直为0的话就一直等待,只有当被设为SET后才会跳出这个循环(表示一个字节发送出去了) }在main主函数中编写语句: //在主函数里面发送一个数据试试 Usart_SendByte(USART1,100);//往串口1中写入数据100串口调试助手并没有显示100,而是显示的一个字母d 串口调试助手不管接收到的是什么数据,都会转化为字符 只有发送十六进制数据,串口助手使用十六进制形式接收数据时才不是字符 Usart_SendByte(USART1,'A');//往串口1里面写入一个字符A //串口接收到字符A串口助手无论是收发都是以字符的形式进行传输的 假如说串口助手发送一个数字1,stm32串口如果能够接收的话,在进行数据解析过程中需要按照字符 ’1‘ 来进行解析(把1当成是字符,而不是十进制1 ) 2、函数2-发送两个字节数据有时候传感器数据可能是16位的,怎么发送?发送两个字节? 发送两个字节的数据就是十六位的。 //发送两个字节数据函数 void Usart_SendHalfWord(USART_TypeDef* pUSARTx,uint16_t data) { //发送十六位数据要分为两次来发送,先定义两个变量 uint8_t temp_h,temp_l;//定义8位的变量(分别存储高8位和低8位) //首先取出高8位 temp_h=(data&0xff00)>>8;//低八位先与0相&,低8位变为0再右移8位(0xff00共16位二进制) //再取出低8位 temp_l=data&0xff;//取出低8位数据 //16位的数据这样子就放到了两个变量里面(共16位) //调用固件库函数 USART_SendData(pUSARTx,temp_h);//先发送高8位 while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE)==RESET);//等待数据发送完毕 USART_SendData(pUSARTx,temp_l);//再发送低8位 while(USART_GetFlagStatus(pUSARTx,USART_FLAG_TXE)==RESET);//等待数据发送完毕 }在主函数中发送十六进制数据: Usart_SendHalfWord(USART1,0XFF56);//发送16位数据串口助手显示的是字符,要想接收到的数据和发送的一样,需要把串口助手选择为16进制接收 串口助手接收到ff 56。虽然是16位的数据但是显示的时候还是一个字节一个字节的显示,十六进制ff是一个字节 56是一个字节 |
CopyRight 2018-2019 实验室设备网 版权所有 |