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时钟//复位串口1GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,  GPIO_AF_USART1); //PA9 复用为 USART1GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //PA10 复用为 USART1//驱动是哪个引脚  PA9/PA10GPIO_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 emptywhile(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 emptywhile(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)== RESET){} //如果发送完成会结束循环 RESET=0//串口发送低8位数据USART_SendData(USARTx, temp_l);//检测发送完成 检测状态寄存器的TXE位(发送数据寄存器为空)  TXE:Transmit data register emptywhile(USART_GetFlagStatus(USARTx, USART_FLAG_TXE)== RESET){} //如果发送完成会结束循环 RESET=0
}

2.3 编写接收中断函数

 uint8_t rx_buff[50];  //声明一个数组uint8_t rx_cnt = 0;   //数组索引为0uint8_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<2;i++){printf("value = %x\n",rx_buff[i]);}//拼接数据temp = (rx_buff[0]<<8)|(rx_buff[1]); //或者是 (uint16_t)rx_buff[0]<<8 + (uint16_t)rx_buff[1]printf("value = %.2f\n",(float)temp/100);memset(rx_buff,0,sizeof(rx_buff));   //清空数组rx_cnt = 0;                          //索引置0}
}

2.4 main.c函数

int main(void){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<2;i++){printf("value = %x\n",rx_buff[i]);}//---------------------------------------------if(USART_GetITStatus(USART1,USART_IT_IDLE) != RESET){  //当接收到一帧数据,就会产生USART_IT_IDLE中断data = USART1->SR;        // 清空闲中断data = USART1->DR;           usart_idle_flag = 1; //产生空闲中断,没有用到temp = (rx_buff[0]<<8)|(rx_buff[1]); //或者是 (uint16_t)rx_buff[0]<<8 + (uint16_t)rx_buff[1]printf("value = %.2f\n",(float)temp/100);memset(rx_buff,0,sizeof(rx_buff));   //清空数组rx_cnt = 0;                          //索引置0}
}

串口通信——发送和接收数据(8位和16位数据之间的转换)相关推荐

  1. 51单片机串口通信发送以及接收代码详解1

    #include <reg51.h> //实验现象:单片接收电脑发送的字符串,并发回给PC端的代码.//函数声明 void uart_init(void); void uart_seng_ ...

  2. 51单片机串口通信发送以及接收代码详解2

    #include <reg51.h> //实验现象:在电脑端没按下发送的时候,单片一直给电脑发送aaa字符串: //实验现象:在电脑端按下发送的时候,结束字符串aaa的发送代码,执行单片接 ...

  3. java串口发送16进制数据_MFC串口通信发送16进制数据的方法

    本文实例为大家分享了MFC串口通信发送16进制数据的具体代码,供大家参考,具体内容如下 MFC串口通信会使用m_mscomm控件. 发送数据一般是在edit control 里输入自己想发送的内容,然 ...

  4. 串口接收标志位语句_如何获取串口的发送和接收的标志位?

    我用C#写了一个小的串口调试软件,并在51的板子上调试成功了,但是换到STM32F103上不行了,由于刚学STM32,还很不熟悉,所以还请各位能否告诉我如何获取串口的发送和接收的标志位.或是帮我把下面 ...

  5. 【HAL库】STM32F407ZGT6实现串口中断发送和接收

    ** [HAL库]STM32F407ZGT6实现串口中断发送和接收 (保姆级教写代码1) ** 前言 根据近期所做的项目,想给大家分享一些有关STM32的各类通信方式的代码教程,都是基于STM32HA ...

  6. RS232串口通信(UART的接收部分)

    RS232串口通信(UART的接收部分) 置顶 新人博主,创作不易,波形图手绘,请给个点赞关注吧,非常感谢! 串口简介 ​ 串口作为常用的三大低速总线(UART.SPI.IIC)之一,在设计众多通信接 ...

  7. C语⾔:8位、16位、32位数据转换

    C语⾔:8位.16位.32位数据转换 8位转16位 将2个8位数据u8_high.u8_low合成⼀个16位数据u16_data: u16_data=(u8_high<<8)| u8_lo ...

  8. 单片机8位、16位、32位和64位系统在内存上的区别

    总线.内存和变量的相关知识 前言 本篇文章主要介绍单片机内部的总线和内存的一些关系及知识点, 一.32位系统和64位系统的区别 1. 8位.16位.32位和64位CPU的含义 如标题所述,不同位数的单 ...

  9. MD5的应用场景以及MD5 32位和16位的区别

    MD5为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.用于确保信息传输完整一致.是计算机广泛使用的杂凑算法之一(又译摘要算法.哈希算法),主流编程语言普遍已有MD5实现.将数据(如汉 ...

最新文章

  1. jQuery / jQuery mvc plugin
  2. activeMQ使用总结
  3. android 工程中引入第三方JAR包后安装APK时老是提示找不到库文件?
  4. spring 通过EsClientFactory注入elasticsearch
  5. 160 - 1 Acid burn
  6. MySQL中序列的作用_MySql中序列的应用和总结
  7. jquery.autocomplete自动补齐和自定义格式
  8. Python爬虫实践(一) -- 社交网站用户信息爬取
  9. java的datatype_java基本数据类型--Basic Datatypes
  10. 数据库的几种去重方法总结
  11. java强行删除文件(针对进程正在使用的文件的删除)
  12. html和js制作个人所得税表格,【JS】计算个人所得税(新版)
  13. 特别有趣的spyder运行程序
  14. Java制作的类祖码游戏-数字祖码
  15. 2023计算机毕业设计SSM最新选题之java中药城药材销售管理系统eah41
  16. 机器学习测试模型 的混淆矩阵
  17. 乡镇级echarts地图json获取、各省市区地图json文件
  18. vjdesign - vue 界面可视化设计器
  19. 全自动化学加药装置循环水应用介绍
  20. 尚学堂Java学习日记Day3

热门文章

  1. PostgreSQL学习总结(十七)——(客户端命令<一>)
  2. 常见的Linux操作系统有哪些 常见的Linux操作系统介绍
  3. 分段表rowid_Oracle表的Rowid字段
  4. Linux命令(十七) 关机命令,linux定时关机命令是什么
  5. 服务器虚拟化知识点的总结以及了解虚拟化
  6. 伪原创视频怎么做 视频md5修改批量修改器
  7. 单例模式懒汉单例实现
  8. MongoDB复制集搭建
  9. 研磨设计模式 之 生成器模式(Builder)2 ——跟着cc学设计系列
  10. 前端如何提升To B产品用户体验