继DHT11,将冗长的代码分为移植性和可读性高的代码模块
1.添加新的文件
2. 选择C语言,并命名为uart.c
3. 重复1,2步,分别创建uart.c, LCD1602.c, dht11.c, delay.c(文件名不区分大小写,不能有同名文件)
4. 将原来冗长的代码,通过这四个分类分别把对应的代码移动到相应的C文件下
uart.c
#include "reg52.h" sfr AUXR = 0x8E; void UartInit() //9600bps@11.0592MHz { AUXR = 0x01; SCON = 0x40; //配置串口工作方式1,REN不使能接收 //配置定时器1,工作方式为8位自动重载 TMOD &= 0x0f;// TMOD |= 0x20; TH1 = 0xFD; TL1 = 0xFD; //9600波特率的初值 TR1 = 1;//启动定时器 } void Send_byte(char data_msg) { SBUF = data_msg; while(!TI);//在请求中断时,TI= 1,既!TI=0,等待数据的发送完成;响应中断结束后TI = 0,既!TI = 1,将TI清零 TI = 0; } void Send_string(char* str) { while(*str != '\0') { Send_byte(*str); str++; } }
LCD1602.c
#include "reg52.h" #include <intrins.h> #include "delay.h" #define databuffer P0 //定义8位数据线,Po端口组 sbit RS = P1^0; sbit RW = P1^1; sbit EN = P1^4; void Check_Busy()//(4)以后每次写指令,读/写数据操作均需要检测忙信号 { char temp = 0x80; databuffer = 0x80;//先将databuffer置为忙 while(temp &= 0x80 ){//1000 0000//BF(D7)位为高电平,代表忙 //然后如果temp不变化的话,就一直检查是否busy RS = 0; RW = 1; EN = 0; _nop_(); EN = 1; temp = databuffer;//根据时序图,E为1时开始读 _nop_(); _nop_(); EN = 0; _nop_(); } } void Write_cmd_Func(char cmd)//写入指令的函数 { Check_Busy();//(4)以后每次写指令,读/写数据操作均需要检测忙信号 RS = 0;//写指令 RW = 0; EN = 0; _nop_(); databuffer = cmd; EN = 1; _nop_(); _nop_(); EN = 0; } void Write_data_Func(char dataShow)//写入数据的函数 { Check_Busy();//(4)以后每次写指令,读/写数据操作均需要检测忙信号 RS = 1;//写内容 RW = 0; EN = 0; _nop_(); databuffer = dataShow; _nop_(); EN = 1; _nop_(); _nop_(); EN = 0; } void LCD1602_Init() { //(1)延时 15ms Delay15ms(); //(2)写指令 38H(不检测忙信号) Write_cmd_Func(0x38); //(3)延时 5ms Delay5ms(); //(4)以后每次写指令,读/写数据操作均需要检测忙信号 //(5)写指令 38H:显示模式设置 Write_cmd_Func(0x38); //(6)写指令 08H:显示关闭 Write_cmd_Func(0x08); //(7)写指令 01H:显示清屏 Write_cmd_Func(0x01); //(8)写指令 06H:显示光标移动设置 Write_cmd_Func(0x06); //(9)写指令 0CH:显示开及光标设置 Write_cmd_Func(0x0C); } void LCD1602_ShowLine(char row,char col,char *string) { switch(row){ case 1: Write_cmd_Func(0x80+col);//只要定下开始的位置,之后光标会自行移动 while(*string){ Write_data_Func(*string); string++; } break; case 2: Write_cmd_Func(0x80+0x40+col);//只要定下开始的位置,之后光标会自行移动 while(*string){ Write_data_Func(*string); string++; } break; } /* char pos; if(hang == 0){//如果第一行 pos = 0x80 + 0x00 + lie; }else if(hang == 1){//如果第二行 pos = 0x80 + 0x40 + lie; } Check_Busy(); Write_data_Func(*string); while(*string != '\0'){ Check_Busy(); Write_data_Func(*string); string++; } */ }
dht11.c
#include "reg52.h" #include "delay.h" sbit dht = P3^3; char datas[5]; char temperature[8]; char humidity[8]; void Build_datas() { humidity[0] = 'H'; humidity[1] = datas[0]/10 + 0x30; humidity[2] = datas[0]%10 + 0x30; humidity[3] = '.'; humidity[4] = datas[1]/10 + 0x30; humidity[5] = datas[1]%10 + 0x30; humidity[6] = '%'; humidity[7] = '\0'; temperature[0] = 'T'; temperature[1] = datas[2]/10 + 0x30; temperature[2] = datas[2]%10 + 0x30; temperature[3] = '.'; temperature[4] = datas[3]/10 + 0x30; temperature[5] = datas[3]%10 + 0x30; temperature[6] = 'C'; temperature[7] = '\0'; } void Start_DHT() { dht = 1; dht = 0; Delay30ms(); dht = 1; while(dht == 1);//不断读取直到DHT再次变低,跳出循环,说明模块响应 while(dht == 0);//不断读取直到DHT再次拉高,80us之后,再经过50us后DHT变成低电平,就代表要开始变高并开始传输数据了 while(dht == 1);//等待数据传输,不断读取直到DHT再次变低,如退出循环说明数据传输前的50us低电平开始了 } void Read_data_From_DHT() { int i;//轮 int j;//每一轮读多少次 char temp; char flag; Start_DHT(); for(i = 0;i < 5; i++) {//5组数据 for(j =0;j<8;j++) {//每组数据8位 while(!dht);//等待上拉 dht = 1 退出循环 Delay40us();//高电平持续26-28us是‘0’,高电平持续70us是'1',所以delay40us之后观察还是否是高电平 if(dht == 1) { flag = 1; while(dht);//不断读取下拉的一瞬间,因为在开始传输数据之前要延迟80us,如果提前结束,下一次开始传输数据就会出错,因为“开始传输数据”是从判断上拉开始的 } else { flag = 0; } temp = temp << 1;//temp左移一位,例如temp= 10101011 左移之后变成-》01010110(第一个数移出去,最后一位补零) temp |= flag;//假如flag=1,temp=01010111 } datas[i] = temp; } }
delay.c
#include <intrins.h> void Delay15ms() //@11.0592MHz { unsigned char i, j; i = 27; j = 226; do { while (--j); } while (--i); } void Delay5ms() //@11.0592MHz { unsigned char i, j; i = 9; j = 244; do { while (--j); } while (--i); } void Delay1000ms() //@11.0592MHz { unsigned char i, j, k; _nop_(); i = 8; j = 1; k = 243; do { do { while (--k); } while (--j); } while (--i); } void Delay30ms() //@11.0592MHz { unsigned char i, j; i = 54; j = 199; do { while (--j); } while (--i); } void Delay40us() //@11.0592MHz { unsigned char i; _nop_(); i = 15; while (--i); }
5. 光是分文件不行,其他文件要调用文件,例如main.c文件要调用delay.c文件, 因此需要创建delay.h的头文件: (头文件也不分大小写)
6. 在h文件中,删除函数的实现体,只保留需要在其他C文件调用的函数的声明(在文件内调用的函数可以不声明)
delay.h
void Delay15ms(); //@11.0592MHz void Delay5ms(); //@11.0592MHz void Delay1000ms(); //@11.0592MHz void Delay30ms(); //@11.0592MHz void Delay40us(); //@11.0592MHz
7.同理
dht11.h
void Build_datas(); void Read_data_From_DHT();
lcd1602.h
void LCD1602_Init(); void LCD1602_ShowLine(char row,char col,char *string);
uart.h
void UartInit(); //9600bps@11.0592MHz void Send_byte(char data_msg); void Send_string(char* str);
8. 由于“humidity”和“temperature”变量是在dht11中被定义,但是在main函数中被使用,但现在dht11变成了单独的C文件,所以为了让main的C文件也认识这两个变量,需要将他们在main的C文件中也定义一下,并加上“extern”前缀!
具体的extern解释可查看一文彻底搞懂extern用法
main.c
#include "reg52.h"
#include <intrins.h>
#include <string.h>
#include "delay.h"
#include "uart.h"
#include "lcd1602.h"
#include "dht11.h"
sbit led1 = P3^7;//根据原理图(电路图),设备变量led1指向P3组IO口的第7口
extern char temperature[8];
extern char humidity[8];
void main()
{
Delay1000ms();//传感器上电后,要等待 1s 以越过不稳定状态在此期间无需发送任何指令
UartInit();
LCD1602_Init();
Delay1000ms();
Delay1000ms();
led1 = 0;
while(1)
{
Delay1000ms();
Read_data_From_DHT();
Build_datas();
Send_string(humidity);
Send_string("\r\n");
Send_string(temperature);
Send_string("\r\n");
LCD1602_ShowLine(1,2,humidity);
LCD1602_ShowLine(2,2,temperature);
}
}
结果一样