串口传输温湿度数据部分代码解析 (基于51单片机)

        不废话,直接上代码,recv_data_fromDHT11函数功能为接收DHT11模块发送的数据,每次接收数据前调用HDT11_start()函数向模块发送信号,请求接收数据。基于模块每次发送的数据量为40bit5个char。

        由于数据是按位传输,我们可以把这40bit分为发送5次8位,即发送5次1个字节。至于这里为何需要延时以及卡高低电平,可以查阅DHT11模块使用手册,根据时序图来分析,这里不过多赘述。随后通过高电平持续时间判断模块传输的数据位flag为0或1,再将每个数据位写入tmp中,这里主要来分析下,数据是如何被写入tmp中的。

char datas[5];

void recv_data_fromDHT11()
{
		int i,j;
		char tmp;
		char flag;
		// 用户MCU发送一次开始信号后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集
		HDT11_start();		
		for(i=0; i<5; i++)		
		{											// 数据是按位传输, 每8位为1字节
			for(j=0; j<8; j++)		
			{
					// 每一位数据都以50us低电平间隙开始传输,当跳至高电平时为有效数据
					while(HDT11==0);
					// 通过高电平时间判断数据位0或1, 0(高电平时间26~28us), 1(高电平时间70us)
					Delay40us();
					if(HDT11){				// 40us后仍为高电平,则数据位为1
						flag = 1;
						while(HDT11);
					}else
						flag=0;
					tmp <<= 1;				// 位移8位,并修改位值为flag
					tmp |= flag;
			}
			datas[i] = tmp;
		}
}

        首先我们在上面定义了一个char tmp; tmp为一个字节,内循环8次传输一个字节。这里使用移位运算来完成1个字节的传输。举例: tmp初始化默认为0000 0000B(1个字节char可转为8位二进制)左移1位后再和数据位flag进行或运算,若flag为1,则运算后tmp值为0000 0001,下一次循环tmp再左移一位,变为0000 0010,然后再和flag或运算,左移可以理解为为下一位数据腾出位置

        flag值只有1和0,转换为二进制也就是只有0000 0001和0000 0000,所以每次或运算都是只改变最右边的那一位,tmp左移可以腾出最右边位来接收flag的值。位移8次后完成一个字节的传输,然后将这个数据赋值给char型数组datas, DHT11一次传输40bit数据,刚好装满数组。

char H_data[9]="H:";
char T_data[9]="T:";

void build_data()		// 例:H:32.00%\0
{		
		// 湿度
		H_data[2] = datas[0]/10+'0';		
		H_data[3] = datas[0]%10+'0';
		H_data[4] = '.';
		H_data[5] = datas[1]/10+'0';
		H_data[6] = datas[1]%10+'0';
		H_data[7] = '%';
	
		// 温度
		T_data[2] = datas[2]/10+'0';		
		T_data[3] = datas[2]%10+'0';
		T_data[4] = '.';
		T_data[5] = datas[3]/10+'0';
		T_data[6] = datas[3]%10+'0';
		T_data[7] = 'C';
}

         接收DHT11的数据后,这里需要通过串口传输到PC机,且我们希望数据是以字符的形式展现出来,便于阅读。上面将tmp存入数组datas中,tmp虽然为字符型,但我们假设tmp左移8位接收flag值以后为 00000000~00011111 转换为ASCII码为0~31,而0~31没有对应的可打印字符,那么如果直接传输到串口,以字符方式显示则会不打印亦或者打印乱码。这里关于ASCII码的知识如果有不懂,大家可以自行百度。或者参考以下博客:

http://t.csdnimg.cn/Mk9XJ

        为了解决这种情况,所以我们在这里可以将tmp对应的ASCII码直接转为对应的字符数字显示,字符0~9可以用ASCII码48~57来表示。这样就可以打印出来正常的字符数据了。

        我们知道单个字符数字转为整形数字的公式为:c - 48,  那么这里我们是将字符的ASCII码转换为数字字符,datas[i]中存储的是一个字符,当datas[i]参与算术运算时,自动转换为ASCII码参与计算,得出的结果为整形值,再加上字符'0'对应的ASCII码0x30,则ASCII码值就转换为了对应的数字字符。

        举例:tmp值为a, 对应ASCII码值97,将97/10==9, 9+48 == 57,ASCII码57对应字符9,再将97%10==7,7+48==55,对应字符7,那么这样就将一个字符a转换为两个数字字符了,  在显示数据时本应该显示a字符,就会显示97,其他任意字符都可以通过其ASCII码转换为此形式。

最终传输结果:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值