串口通信

您所在的位置:网站首页 问题:一字节是多少位 串口通信

串口通信

#串口通信| 来源: 网络整理| 查看: 265

1. 实验目的

1.发送两个字节数据,就是16位的数据,每一次发送8位,发送两次,这里要进行数据的拆分,如发送一个0XFF56,接收得到的也是FF56(16进制显示); 2.接收两个字节的数据(这里通过串口助手以16进制发送一个数据),将拼接的数据(只能一个字节一个字节接收)除以100展示出来,如通过串口助手发送一个DEEE(16进制发送),其10进制就是57070,最终要展示为570.70。 其中串口是USART1,其端口是GPIOA,引脚是PIN9、PIN10,一个用来收数据,一个用来发收据。

2. 实验流程

初始化串口; 编写发送数据函数; 编写接收中断函数; main函数调用发送函数。

2.1 初始化串口 //配置中断函数,这个函数下面有调用 void EXTI_NVIC_Config(void){ //NVIC初始化结构体 NVIC_InitTypeDef NVIC_InitStruct; //设置中断优先级的分组 //就是设置主抢占优先级和子抢占优先级各是几,这里是分组为1,代表主优先级可以是0和1(就是1个位来设置主优先级),子优先级是0-7,是2的3次方 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //配置USART为中断源 NVIC_InitStruct.NVIC_IRQChannel = USART1_IRQn; //配置抢占优先级 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; //配置子优先级 NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; //使能中断 NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); } //串口初始化函数 void USART_Config(void){ //1.初始化GPIO(PA9(接串口1的TX引脚),这里是PA10(接串口1的RX引脚)) //初始化结构体 GPIO_InitStruct //里面是GPIO的速度,上下拉,输出类型等 GPIO_InitTypeDef GPIO_InitStruct; //USART结构体 USART_InitTypeDef USART_InitStruct; //打开GPIOA时钟(一般开时钟要放到前面的位置,然后再是设置上拉,输出这些) RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能时钟必须放到前面,不然后面的操作不会使灯点亮 //打开USART1时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟 //复位串口1 GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); //PA9 复用为 USART1 GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //PA10 复用为 USART1 //驱动是哪个引脚 PA9/PA10 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9|GPIO_Pin_10; //模式是复用功能 GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF; //输出的速度 GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; //推挽复用输出 GPIO_InitStruct.GPIO_OType = GPIO_OType_PP; //上拉 GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_UP; //变量获取它的指针,取地址就行(&) GPIO_Init(GPIOA,&GPIO_InitStruct); //2.初始化串口 //使能串口时钟 (放在最上面了) //配置波特率 USART_InitStruct.USART_BaudRate = 115200; //设置波特率115200 //配置针数据字长 USART_InitStruct.USART_WordLength = USART_WordLength_8b; //字长为8位数据格式 //配置停止位 USART_InitStruct.USART_StopBits = USART_StopBits_1; //设置为一个停止位 //配置校验位 USART_InitStruct.USART_Parity = USART_Parity_No; //无奇偶校验位 //配置硬件流控制 USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //不使用硬件流控制 //配置工作模式 USART_InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx; //收发模式 //完成串口的初始化配置 USART_Init(USART1,&USART_InitStruct); //串口中断优先级配置(初始化) EXTI_NVIC_Config(); //使能串口接收中断(中断配置函数) 这是使能哪种中断,比如在接收到数据的时候(RXNE 读数据寄存器非空),我们要产生中断 USART_ITConfig(USART1,USART_IT_RXNE,ENABLE); //生成串口中断 接收到数据就产生了中断 USART_ITConfig(USART1, USART_IT_IDLE, ENABLE); // 开启空闲中断 //使能串口(串口使能函数) USART_Cmd(USART1,ENABLE); } 2.2 编写发送数据函数

一个16位的数据,先发送的是高8位,再发送第八位。 uint8_t temp_h,temp_l; 取高8位:temp_h = (data&0xFF00) >>8,先把数据按位与上0xFF00,这样低八位全取了0,再右移8位就得到了高8位。 取低8位:temp_l = (data&0x00FF); 把数据按位与上0x00FF就是高八位清零了,只剩下八位了。

//发送一个字节数据,进行了简单封装,判断了发送结束 void Usart_SendByte(USART_TypeDef* USARTx, uint8_t data){ //串口发送数据 USART_SendData(USARTx, data); //什么时候结束 检测状态寄存器的TXE位(发送数据寄存器为空) TXE:Transmit data register empty while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)== RESET){} //如果发送完成会结束循环 RESET=0 //while(!(USART_GetFlagStatus(USARTx, USART_FLAG_TXE))){} //这个应该也是可以的 } //发送两个字节数据 void Usart_SendHalfWord(USART_TypeDef* USARTx, uint16_t data){ //定义高八位和低八位 uint8_t temp_h,temp_l; //高8位的值是 temp_h = (data&0xff00) >>8; temp_l = data&0x00ff; //高8位清0 //串口发送高8位数据 USART_SendData(USARTx,temp_h); //这里的USART_SendData是可以发送16位数据的 //检测发送完成 检测状态寄存器的TXE位(发送数据寄存器为空) TXE:Transmit data register empty while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)== RESET){} //如果发送完成会结束循环 RESET=0 //串口发送低8位数据 USART_SendData(USARTx, temp_l); //检测发送完成 检测状态寄存器的TXE位(发送数据寄存器为空) TXE:Transmit data register empty while(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)== RESET){} //如果发送完成会结束循环 RESET=0 } 2.3 编写接收中断函数 uint8_t rx_buff[50]; //声明一个数组 uint8_t rx_cnt = 0; //数组索引为0 uint8_t usart_idle_flag = 0; uint16_t temp; //接收数据中断函数 void USART1_IRQHandler(void){ uint8_t i; unsigned int data; if(USART_GetITStatus(USART1,USART_IT_RXNE)){ //每当接收到1个字节,会产生USART_IT_RXNE中断 rx_buff[rx_cnt] = USART_ReceiveData(USART1); //把这个数据放到数组中去 rx_cnt++; } if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET){ //当接收到一帧数据,就会产生USART_IT_IDLE中断 data = USART1->SR; // 清空闲中断 data = USART1->DR; usart_idle_flag = 1; //产生空闲中断,没有用到 //展示接收到的数据 for(i=0;i USART_Config(); //初始化串口 Usart_SendHalfWord(USART1,0XFF56); //调用发送两个字节函数 while(1){} } 3. 实验结果

发送两个字节展示如下图所示: 在这里插入图片描述 接收两个字节如下图所示: 在这里插入图片描述

4. 总结发现

在编写接收数据中断函数时,如果使用printf进行接收数据的打印时候,只会打印接收到的第一个字节,这里是把printf放到接收和空闲中断之间,会产生问题。

//接收数据中断函数 void USART1_IRQHandler(void){ uint8_t i; unsigned int data; if(USART_GetITStatus(USART1,USART_IT_RXNE)){ //每当接收到1个字节,会产生USART_IT_RXNE中断 rx_buff[rx_cnt] = USART_ReceiveData(USART1); //把这个数据放到数组中去 rx_cnt++; } //--------------------------------------------- //放到两者之间的时候 for(i=0;i //当接收到一帧数据,就会产生USART_IT_IDLE中断 data = USART1->SR; // 清空闲中断 data = USART1->DR; usart_idle_flag = 1; //产生空闲中断,没有用到 temp = (rx_buff[0]


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3