一、项目介绍:
本项目是用 MAX78000和 DHT11温湿度传感器实现环境数据监测功能。MAX 78000 和 DHT 11 进行通信,通过处理 DHT 11 发送过来的数据,转换成温湿度数据,将数据显示在 TFT 屏幕上(原计划还有和8266 通信上传到云平台显示遇到问题通信一直没有调通),为用户提供实时的环境温湿度监测功能。
二、项目设计思路:
硬件设计 :
用 MAX 78000 的 GPIO P0_19 引脚和 DHT 11 的 DATA 位连接进行通信 ! 连接 TFT 屏幕与 MAX78000微控制器,用于显示环境温湿度数据。屏幕的具体连线和使用方法参考上一届大佬的文档基于MAX78000的智能语音控制洗衣机(模拟) - 电子森林 (本项目将 RES 口改成了 P 1_6)
软件设计 :
dht 11
通信时序 -单总线协议
DHT11 采用单总线协议与单片机通信,单片机发送一次复位信号后,DHT11 从低功耗模式转换到高速模式,等待主机复位结束后,DHT11 发送响应信号,并拉高总线准备传输数据。一次完整的数据为 40bit,按照高位在前,低位在后的顺序传输。 数据格式为:8bit 湿度整数数据+8bit 湿度小数数据+8bit 温度整数数据+8bit 温度小数数据+8bit 校验和,一共 5 字节(40bit)数据。由于 DHT11 分辨率只能精确到个位,所以小数部分数据全为 0。校验和为前 4 个字节数据相加,校验的目的是为了保证数据传输的准确性。 DHT11 只有在接收到开始信号后才触发一次温湿度采集,如果没有接收到主机发送复位信号,DHT11 不主动进行温湿度采集。当数据采集完毕且无开始信号后,DHT11 自动切换到低速模式。
通信时序分析
- 复位信号
- 开始主机先拉低总线 18ms 以上,然后拉高 20-40 us (一般取中间值 30us)DHT11 收到启动信号
- 响应信号
- DHT 11 先拉低总线80 us 然后拉高总线80 us 响应结束
- 数据信号
- 发送一位数据前从机先拉低 50 us,然后拉高26~28 us表示数据‘0’,拉高70 us表示数据‘1’,一共 40 位数据。
MAX 78000 IO 口
最开始用 P0_19 作为数据总线和 DHT11 进行通信,用到 TFT 屏幕时 RES 引脚也占用了 P 0_19, 于是改到了 P 1_6,但是输出一直有问题,不能输出低电平,不知道是哪里的问题但是 P 0_19 就可以正常运行,于是将两个 IO 口进行调换,就可以正常运行。
三、项目思路:
最开始是想用 DHT 11 采集温湿度数据,然后通过 MAX 78000 处理,和 ESP 8266 通信用 AT 指令将数据发送到 onenet 云平台。(目前和 ESP 8266 通信调试中一直有问题,所以先写目前的成果 )
四、实现过程及关键代码说明:
- MAX78000的引脚定义配置 :
// DHT11 连接引脚定义
#define DHT11_Dout_PORT MXC_GPIO0
#define DHT11_Dout_PIN MXC_GPIO_PIN_19
// DHT11 函数宏定义
#define DHT11_Dout_LOW() MXC_GPIO_OutPut(DHT11_Dout_PORT, DHT11_Dout_PIN,0)
#define DHT11_Dout_HIGH() MXC_GPIO_OutPut(DHT11_Dout_PORT, DHT11_Dout_PIN,1)
#define DHT11_Data_IN() MXC_GPIO_InGet(DHT11_Dout_PORT,DHT11_Dout_PIN)
- 引脚初始化
void DHT11_Init ( void )
{
MXC_GPIO_Init(DHT11_Dout_PORT);
DHT11_Mode_Out_PP();
DHT11_Dout_HIGH(); // 拉高GPIO
}
- IO 口模式设置函数
// 函数功能: 使DHT11-DATA引脚变为上拉输入模式
static void DHT11_Mode_IPU(void)
{
mxc_gpio_cfg_t gpio_data;
gpio_data.port = DHT11_Dout_PORT ;
gpio_data.mask = DHT11_Dout_PIN;
gpio_data.pad = MXC_GPIO_PAD_PULL_UP;
gpio_data.func = MXC_GPIO_FUNC_IN;
MXC_GPIO_Reset(DHT11_Dout_PORT);
MXC_GPIO_Config(&gpio_data);
}
// 函数功能: 使DHT11-DATA引脚变为推挽输出模式
static void DHT11_Mode_Out_PP(void)
{
mxc_gpio_cfg_t gpio_data;
gpio_data.port = DHT11_Dout_PORT;
gpio_data.mask = DHT11_Dout_PIN;
gpio_data.pad = MXC_GPIO_PAD_NONE;
gpio_data.func = MXC_GPIO_FUNC_OUT;
MXC_GPIO_Reset(DHT11_Dout_PORT);
MXC_GPIO_Config(&gpio_data);
}
- 读取一字节函数
// 函数功能: 从DHT11读取一个字节,MSB先行
static uint8_t DHT11_ReadByte ( void )
{
uint8_t i, temp=0;
for(i=0;i<8;i++)
{
/*每bit以50us低电平标置开始,轮询直到从机发出 的50us 低电平 结束*/
while(DHT11_Data_IN()==Bit_RESET);
/*DHT11 以26~28us的高电平表示“0”,以70us高电平表示“1”,
*通过检测 x us后的电平即可区别这两个状 ,x 即下面的延时
*/
MXC_Delay(MXC_DELAY_USEC(40)); //延时x us 这个延时需要大于数据0持续的时间即可
if(DHT11_Data_IN())/* x us后仍为高电平表示数据“1” */
{
/* 等待数据1的高电平结束 */
while(DHT11_Data_IN());
temp|=(uint8_t)(0x01<<(7-i)); //把第7-i位置1,MSB先行
}
else // x us后为低电平表示数据“0”
{
temp&=(uint8_t)~(0x01<<(7-i)); //把第7-i位置0,MSB先行
}
}
return temp;
}
- 完整接收 40 字节数据并做处理
uint8_t DHT11_Read_TempAndHumidity(DHT11_Data_TypeDef *DHT11_Data)
{
uint8_t temp;
uint16_t humi_temp;
/*输出模式*/
DHT11_Mode_Out_PP();
/*主机拉低*/
DHT11_Dout_LOW();
/*延时18ms*/
MXC_Delay(MXC_DELAY_MSEC(20));
/*总线拉高 主机延时30us*/
DHT11_Dout_HIGH();
MXC_GPIO_OutSet(DHT11_Dout_PORT,DHT11_Dout_PIN);
MXC_Delay(30); //延时30us
/*主机设为输入 判断从机响应信号*/
DHT11_Mode_IPU();
MXC_Delay(30); //延时30us
/*判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行*/
if(DHT11_Data_IN()==Bit_RESET)
{
/*轮询直到从机发出 的80us 低电平 响应信号结束*/
while(DHT11_Data_IN()==Bit_RESET);
/*轮询直到从机发出的 80us 高电平 标置信号结束*/
while(DHT11_Data_IN());
/*开始接收数据*/
DHT11_Data->humi_high8bit= DHT11_ReadByte();
DHT11_Data->humi_low8bit = DHT11_ReadByte();
DHT11_Data->temp_high8bit= DHT11_ReadByte();
DHT11_Data->temp_low8bit = DHT11_ReadByte();
DHT11_Data->check_sum = DHT11_ReadByte();
/*读取结束,引脚改为输出模式*/
DHT11_Mode_Out_PP();
/*主机拉高*/
MXC_GPIO_OutSet(DHT11_Dout_PORT, DHT11_Dout_PIN);
/* 对数据进行处理 */
humi_temp=DHT11_Data->humi_high8bit*100+DHT11_Data->humi_low8bit;
DHT11_Data->humidity =(float)humi_temp/100;
humi_temp=DHT11_Data->temp_high8bit*100+DHT11_Data->temp_low8bit;
DHT11_Data->temperature=(float)humi_temp/100;
/*检查读取的数据是否正确*/
temp = DHT11_Data->humi_high8bit + DHT11_Data->humi_low8bit +
DHT11_Data->temp_high8bit+ DHT11_Data->temp_low8bit;
if(DHT11_Data->check_sum==temp)
{
return SUCCESS;
}
else
return ERROR;
}
else
return ERROR;
}
- 40 字节存储的数据结构
typedef struct
{
uint8_t humi_high8bit; //原始数据:湿度高8位
uint8_t humi_low8bit; //原始数据:湿度低8位
uint8_t temp_high8bit; //原始数据:温度高8位
uint8_t temp_low8bit; //原始数据:温度高8位
uint8_t check_sum; //校验和
float humidity; //实际湿度
float temperature; //实际温度
} DHT11_Data_TypeDef;
- 显示在 TFT 屏幕的程序
MXC_TFT_SetBackGroundColor(BLACK);
MXC_TFT_SetForeGroundColor(WHITE); // set chars to white
MXC_TFT_ClearScreen();
snprintf(buff, sizeof(buff), "Tem: %.2f C",(float)DHT11_Data.temperature);
TFT_Print(buff, 0, 100, (int)&SansSerif16x16[0]);
snprintf(buff, sizeof(buff), "humi: %.2f %%", DHT11_Data.humidity);
TFT_Print(buff, 150, 100, (int)&SansSerif16x16[0]);
五、遇到的主要问题:
MAX 78000 IO 口使用中遇到很多问题,比如用 MXC_GPIO_OutSetClr
拉低,会自动复位,不知道是哪里的问题,P 2_3 拉低后会一直维持低电平。 sdk 中的 api 描述不太清楚使用困难,使用 uart 通信有很多问题。
六、未来的计划:
调通 uart 和 esp8266 成功通信,并将数据上传到 onenet 云端做可视化处理。 添加数据存储功能,可以记录历史温湿度数据。可考虑添加其他传感器,实现更全面的环境监测功能,和智能家居结合,对采集的数据分析,让居住环境更加适宜。
七、感悟:
最开始是想做训练识别方面的选题,训练过程中问题频出,本人学识尚浅对于人工智能方面了解不多,再加上这学期课程较多,没有较多时间调试,中间已经放弃。感谢硬禾科技 -Miya 小姐姐的督促与鼓励,善始善终。虽然没有做出多么成功的项目,但这是我第一次成功参加并完成的活动 (T_T),对我来说很有意义。