二进制数中的一个数位,可以是0或者1,是计算机中数据的最小单位。
计算机中数据的基本单位,每8位组成一个字节。各种信息在计算机中存储、处理至少需要一个字节。
例如,一个ASCII码用一个字节表示,一个汉字用两个字节表示。
两个字节称为一个字。汉字的存储单位都是一个字。
1个汉字是一个字,即两个字节,16位数据
8位数据并列的传输,传一个8位的数据是需要8根线一起传输。
例如:SDIO,FSMC(16位的)–发送数据都是所有数据位同时传输
8位数据一位一位的传输,只需要一根线即可进行传输。
例如:USART,IIC,SPI三种都是串行方式-----发送数据时都是一位一位的进行发送数据
串行通信与并行通信特征
有两根数据线,一个用来接收数据,一个用来发送数据,互不干扰,可以同时发送和接收数据。
例如:usart(可以半双工或全双工通信),SPI(可以半双工或者全双工通信)
有两根数据线,但是不可以同时发送数据,可以分时收发数据
只有一根数据线,只可以单向通信(只可以往某一个方向进行)
数据同步方式,两个设备的时钟信号是同一个(有时钟信号的是同步)。
在传输数据时为了保证数据传输的准确性:
(1)时钟在高电平时,数据有效
(2)时钟信号在低电平时数据时无效的
(3)对时钟的要求很高(如果时钟有尖峰或者杂波,则数据传输就不准确了)
例如:SPI,IIC通信接口。
没有时钟信号:为了保证数据传输的准确性是通过加上一些辅助的标识符
例如:UART(通用异步收发器),单总线。
同步通信和异步通信比较
(1)在同步通信中,数据信号所传输的内容绝大部分就是有效数据。
(2)在异步通信中,传输的数据会包含有帧的各种标识符。
(3)所以同步通信的效率更好,但是对于时钟允许误差较小,异步通信对于时钟允许误差较大。
比特率:每秒钟传输的二进制数单位:bit/s
IIC,SPI(同步通信,一个时钟下传输一个数据,通过时钟来控制)
波特率:每秒钟传输的码元个数(串口)
一个二进制位表示一个码元(特殊情况下)
物理层规定我们用嘴巴还是肢体进行交流
协议层就是规定我们用汉语还是英文来交流
1、RS232和TTL就是在电平上的区别
TTL电平是直接从单片机(或者芯片)里面出来的:高电平用3.3V或者5v来表示,低电平用0表示
RS232中1用-15V表示,0用+15V表示,逻辑正好时相反的,低电平和高电平的差距非常大
TXE-发送数据寄存器空
当TDR寄存器中的数据被硬件转移到移位寄存器的时候,TXE位被硬件置位。
如果USART_CR1寄存器中的TXEIE为1,则产生中断。对USART_DR的写操作,将该位清零。
0-数据还没有转移到移位寄存器
1-数据已经转移到移位寄存器
当包含有数据的一帧发送完成后,并且TXE=1时,由硬件将TC位置’1’。
如果USART_CR1中的TCIE=1,则产生中断。由软件序列清除该位(先读USART_SR,然后写入USART_DR)。 TC位也可以通过写入’0’来清除,只有在多缓存通讯中才推荐这种清除程序。
RXNE-读数据寄存器非空
当RDR移位寄存器中的数据被转移到USART_DR寄存器中,该位(RXNE)被硬件置位。
如果USART_CR1寄存器中的RXNEIE=1,则产生中断。对USART_DR的读操作可以将该位清零。 RXNE位也可以通过写入0来清除,只有在多缓存通讯中才推荐这种清除程序。
上图对应的顺序依次是1->2->3,数据来源于CPU或者DMA,数据来了之后首先是放到发送寄存器(TDR)中,然后会再放到发送数据移位寄存器中,由于数据是8位的,会将数据一位一位的发送出去(使用TX引脚)。
数据从RX引脚进来来,数据是一位一位进行接收的。
STM32 库函数操作 USART_DR 寄存器发送数据的函数是:通过该函数向串口寄存器 USART_DR 写入一个数据。
STM32 库函数操作 USART_DR 寄存器读取串口接收到的数据的函数是:通过该函数可以读取串口接收到的数据。
该函数只判断标志位。在没有使能相应的中断函数时,通常使用该函数来判断标志位是否置1
不仅会判断标志位是否置1,同时还会判断是否使能了相应的中断。所以在串口中断函数中,如果要获取中断标志位,通常使用该函数。
在main主函数中编写语句:
//在主函数里面发送一个数据试试
串口调试助手并没有显示100,而是显示的一个字母d
串口调试助手不管接收到的是什么数据,都会转化为字符
只有发送十六进制数据,串口助手使用十六进制形式接收数据时才不是字符
串口助手无论是收发都是以字符的形式进行传输的
假如说串口助手发送一个数字1,stm32串口如果能够接收的话,在进行数据解析过程中需要按照字符 ’1‘ 来进行解析(把1当成是字符,而不是十进制1 )
有时候传感器数据可能是16位的,怎么发送?发送两个字节?
发送两个字节的数据就是十六位的。
//发送两个字节数据函数
//发送十六位数据要分为两次来发送,先定义两个变量
//16位的数据这样子就放到了两个变量里面(共16位)
在主函数中发送十六进制数据:
串口助手显示的是字符,要想接收到的数据和发送的一样,需要把串口助手选择为16进制接收
串口助手接收到ff 56。虽然是16位的数据但是显示的时候还是一个字节一个字节的显示,十六进制ff是一个字节 56是一个字节
判断发送一个字节的数据标志位:USART_FLAG_TXE
判断发送一连串字节的数据标志位:USART_FLAG_TC
在主函数中定义一个数组
串口助手:十六进制形式接收数据
串口助手:非十六进制数据形式接收数据:1-10的ASCII是无法显示的
在主函数中调用函数发送一个字符串
有时候想直接用printf函数直接发送,肯定是不可以的
printf函数底层会有一个fputc,如果想要使用,需要重新定义
重定向c库函数scanf到串口,重写后可以使用scanf和getchar函数
/* 有了这个等待就不需要在中断中进行了 */
如果在主函数中使用getchar()需要把下面的中断设置代码注释掉(下图),否则会冲突
因为不需要在中断中进行
在主函数的while(1)循环中加入接收数据和发送数据的代码
用串口助手发送什么字符,串口助手就会接收到单片机返回什么字符
当接收到数据时产生中断
有中断就要设置中断优先级
串口助手发送什么数据给单片机,单片机自动将接收到的数据返回给串口助手
当外部设备或者串口调试助手给单片机发送数据时,单片机检测到数据接收寄存器非空,表示数据来了此时产生中断,进去中断服务函数调用固件库函数这个标志位是否真正置1,以免产生误中断,如果真的产生1时,调用USART_ReceiveData(USART1)函数接收数据,把数据放ucTemp变量中
通过串口接收到的数据进行控制led灯,这样子就不需要中断来接收了,通过查询方法即可,这时候要把中断部分给注释了,中断服务函数注释掉就可以了
在主函数中加入以下代码:
u8 ch;//存放电脑接收到的数据
如果出现错误:参考此链接
使用串口助手分别发送1和2就可以控制led灯的亮灭了
前面已经说到,如果不勾选十六进制数据接收和发送的话,其他情况都是以字符的形式发送和接收的,所以此处在发送和接收数据时都要将hex选项进行勾选
三合一气体传感器串口数据流格式如下:
由于前两个字节数据是固定的模块地址,因为可以用来当做判断标准,定义一个接收数据的协议:只有第一个字节和第二个字节都符合条件时,才将数据存储到数组中
数据流共9个字节,所以先定义一个存储9个字节的八位数组
u8 table_cp[9];//这是额外定义一个数组,将接收到的数据复制到这里面//使用自定义协议接收十六进制数据
else if(count==1)//第一个数据接收正确的情况下,判断第二个数据
else//如果第二个字符不是0XE4则计数清零,重新接收
上面实现的是通过自定义协议接收并存储数据
在接收到十六进制数据之后,想要提取其中的两个字节并将其转化为十进制数据,首先需要编写一个十六进制转换函数:(输入十六进制数据返回十进制数据)
主函数的while内容如下:
//用十进制数据打印一下接收到的数据 //前两位是固定的,第7个和第8个十六进制数据分别是CO2的高八位和低八位 //把对应的十六进制数据转化为十进制数据
如下图所示:使用串口助手发送十六进制数据:
其中第7个字节是CO2的高8位,第8个字节是CO2浓度的低8位,然后再按照计算公式进行计算即可求出二氧化碳浓度
阶码(指数)就是指数位存储的值,而偏阶(移码)则不同精度的浮点数的偏阶也各不相同,具体可以查看。
半精度浮点数 是一种被计算机使用的二进制浮点数据类型。半精度浮点数使用2个字节(16位)来存储。
在IEEE 754-2008中,它被称作binary16。这种数据类型只适合存储对精度要求不高的数字,不适合用来计算。