UART通信
0x01 什么是UART?
通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),通常称作UART,是一种异步收发传输器
同步通信:发送方发出数据后,等接收方发回响应以后才发下一个数据包
异步通信:发送方发出数据后,不等接收方发回响应,接着发送下个数据包的通讯方式
总结
- 同步通信是阻塞方式,异步通信是非阻塞方式
- 常见通信总线协议中,I2C、CPI属于同步通信,UART属于异步通信
注意
同步通信的通信双方必须先建立同步,双方的时钟需要调整到同一个频率
异步通信两个通信设备没有时钟信号,因此需要约定好波特率,常见的有4800,9600,115200等,土工室数据起始位和停止位必不可少
一种常用也是最简单的串行数据传输协议。数据线只需要两根就可以实现全双工
Tx:发送数据线
Rx:接收数据线
RS-232标准:上位机和下位机串口通信时的接线方式,主要是接线需要接对
0x02 上位机和下位机
通信,通信,两台设备才能进行通信
- 模块之间的通信,根据其在系统中的功能与作用可分为上位机 与 下位机
- 上位机:处理性能强的计算机,数据的统一处理都在上位机完场
- 下位机:数据采集和发送的终端,处理性能单一的计算机
- 注意:一般一个上位机会对应多个下位机,这种模式可以使数据处理的更加全面,同时也大大降低成本。
0x03 UART数据帧
在协议层(UART protocol 串口协议),规定了数据包的内容,串口发送和接收的数据包都是以帧为单位,Frame
数据包(帧Frame)内容组成:起始位(1bit)+数据位(5~9bit)+校验位(0/1bit)+停止位(0.5,1,1.5bit)
起始位:一个周期的低电平
数据位:5~9bits数据位,具体多少需要双方协商,并优先传送最低位(LSB)
校验位
0校验:校验位总为“0”
1校验:校验位总为“1”
奇校验:有效数据和校验位中“1”的个数为奇数
譬如0101,2个1,为达到奇校验,校验位为“1”
偶校验:有效数据和校验位中“1”的个数为偶数
譬如0100,1个1,为达到偶校验,校验位为“1”
停止位:高电平,1个停止位
波特率(Baudrate):传输速率,即每一秒传输多少个bit为
- 4800
- 9600
- 115200
0x04 串口配置
1.结构体halUARTCfg_t
- halUARTCfg_t结构体是串口初始化的结构体,可以对串口的初始化进行相应设置
1 | typedef struct |
2.串口初始化实例
1 | static void InitUart(void) |
- 最后的HalUARTOpen函数,将串口初始化结构体作为参数对串口0进行初始化
3.串口读操作函数
串口的读操作函数为HalUARTRead(),主要功能是读取上位机通过串口发送至设备节点的数据。
uint16 HalUARTRead(uint8 port, uint8 *buf, uint16 len)
@port:串口端口的设置,可以设置为串口0或串口1;
@buf:数据缓冲区;
@len:数据长度。
返回值:实际成功读取的字节数
4.串口写操作函数
串口的写操作函数为HalUARTWrite(),主要功能是实现向上位机或其他设备通过串口发送数据。
uint16 HalUARTWrite(uint8 port, uint8 *buf, uint16 len)
@port:串口端口的设置,可以设置为串口0或串口1;
@buf:数据缓冲区;
@len:数据长度。
返回值:实际成功发送的字节数
0x05 DHT11温湿度传感器
只简单介绍使用过的部分,因为只是进行了简单的使用,并没有深入了解
1.DHT11数据传输协议
DHT11通过DATA线与MCU实现半双工通讯。每次通讯时间4ms左右(听不懂)
数据:小数部分和整数部分
数据传输:一次完整的数据传输为40bit,高位先出
数据格式
40bits = 8bit湿度整数数据+8bit湿度小数数据
+8bit温度整数数据+8bit温度小数数据 +8bit**校验和**
校验
- 数据传送正确时,校验和数据 = 8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据所得结果的末8位。
- 即校验和数据 =( 8bit湿度整数数据+8bit湿度小数数据+8bi温度整数数据+8bit温度小数数据)% 256(2的8次方)
2.使用DHT11温湿度显示数据
1).P0_4引脚初始化
- DHT11使用的是CC2530的P0_4引脚,初始化引脚的输入和输出模式
- 在dht11.c中进行初始化,具体CPIO初始化可参考Day02记录
1 | void DATA_IO_input_Cfg(void)//设置为上拉输入模式 |
因为数据采集和处理函数已经给我们准备好了,因此我们只要在Z-stack协议栈中创建事件进行调用即可
数据采集和处理函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27int Start_DHT11(void)//开始采集数据
{
unsigned char buf[5];
DATA_IO_output_Cfg();//设置为输出模式
DATA = 0;//发送开始信号
MicroWait(20000);//延时至少18ms
DATA = 1;//拉高20~40us
MicroWait(40);
DATA_IO_input_Cfg();//设置为输入模式
while(!(DATA ==0));//等DHT11回响应信号
while(!(DATA ==1));//等DHT11把总线拉高,准备接收数据
buf[0] = Read_Byte();
buf[1] = Read_Byte();
buf[2] = Read_Byte();
buf[3] = Read_Byte();
buf[4] = Read_Byte();
if((buf[0]+buf[1]+buf[2]+buf[3])%256 == buf[4])
{
humidity = buf[0];
temperature = buf[2];
return 1;
}
return 0;
}
步骤:为事件定义编码-宏–>添加提取事件类处理代码–调用事件设置函数
2).为事件定义编码-宏
在GenericApp.h中添加
1 |
3).添加提取事件类处理代码
GenericApp.c中的GenericApp_ProcessEvent()函数中最后部分添加
1 | if ( events & GENERICAPP_MY_EVT1 ) |
4).添加调用事件设置函数代码
GenericApp.c中的GenericApp_ProcessEvent()函数中switch中添加
1 | if (GenericApp_NwkState == DEV_ZB_COORD) // 网络状态变成协调器 |