|
说明:
实际硬件参数如下
晶振:11.0592
IC:STC89C52RC
LCD1602部分:
移植了之前写的LCD1602驱动,因为该驱动显示方式丰富,有整数,小数,字符串三种方式显示内容,移植性很高
DHT11部分:
DHT11部分,将上电延时等待改为2秒,根据温度要求每次采集的时间应该间隔2秒,这样更符合文档要求
其他说明:
整体采用了分文件的方式进行编写,有利于下次更加方便移植.
main.c
- #include "DHT11.h" // 包含头文件
- #include "LCD1602.h" // 包含头文件
- void main()
- {
- uchar rec_dat[4]; // 定义一个温湿度存储数组01 存储温度高低位23存储湿度高低位
- float temp_float; // 温度值
- float HU_float; // 湿度值
- uchar *dis_str;
- int count;
- DU = 0; // 关闭开发板上的数码管段显示
- WE = 0; // 关闭开发板上的数码管位显示
- lcd_init();
- while (1) { // 循环显示温湿度
- count++; // 统计采集次数
- DHT11_delay_ms(2000); // dht11上电后等待1秒,为了确保数据精确性,与采集间隔2秒限制,直接延迟2秒
- // 数据采集部分-----------------------------------------
- dis_str = DHT11_receive(&rec_dat);
- // 数据计算部分-----------------------------------------
- temp_float = rec_dat[0] + (float)((float)rec_dat[1] / 100);
- HU_float = rec_dat[2] + (float)((float)rec_dat[3] / 100);
- // 数据显示部分----------------------------------------
- lcd_show_str(0, 0, "TEMP:"); // 显示温度前缀修饰
- lcd_show_float(6, 0, HU_float); // 显示湿度在第0行
- lcd_show_str(12, 0, "C"); // 显示温度单位
- lcd_show_str(0, 1, "HU:"); // 显示湿前缀修饰
- lcd_show_float(4, 1, temp_float); // 显示温度在第1行
- lcd_show_str(9, 1, "%"); // 显示湿度百分百符号
- lcd_show_int(11, 1, count); // 采集次数显示
- }
- }
复制代码
DHT11.C
- #include "DHT11.h"
- // DHT11延时函数
- void DHT11_delay_us(uchar n)
- {
- while (--n)
- ;
- }
- void DHT11_delay_ms(uint z)
- {
- uint i, j;
- for (i = z; i > 0; i--)
- for (j = 110; j > 0; j--)
- ;
- }
- // DHT11驱动
- void DHT11_start()
- {
- Data = 1;
- DHT11_delay_us(2);
- Data = 0;
- DHT11_delay_ms(25); // 延时18ms以上
- Data = 1;
- DHT11_delay_us(30);
- }
- // DHT11接收8位二进制数
- uchar DHT11_rec_byte()
- {
- uchar i, dat = 0;
- for (i = 0; i < 8; i++) {
- while (!Data)
- ;
- DHT11_delay_us(8); // 延时60ms,如果p3^6口仍然为高电平,则 为1,反之为0
- dat <<= 1;
- if (Data == 1)
- dat += 1;
- while (Data)
- ;
- }
- return dat;
- }
- // DHT11接收40位数据 void DHT11_receive()
- uchar *DHT11_receive(uchar rec_dat[])
- {
- uchar R_H, R_L, T_H, T_L, RH, RL, TH, TL, revise;
- DHT11_start();
- if (Data == 0) {
- while (Data == 0)
- ;
- DHT11_delay_us(40);
- R_H = DHT11_rec_byte(); // 接收湿度高八位
- R_L = DHT11_rec_byte(); // 接收湿度低八位
- T_H = DHT11_rec_byte(); // 接收温度高八位
- T_L = DHT11_rec_byte(); // 接收温度低八位
- revise = DHT11_rec_byte(); // 接收校正位
- DHT11_delay_us(25);
- if ((R_H + R_L + T_H + T_L) == revise) // 判断接收数据是否正确
- {
- RH = R_H;
- RL = R_L;
- TH = T_H;
- TL = T_L;
- }
- rec_dat[0] = RH; // 温度高位
- rec_dat[1] = RL; // 温度低位
- rec_dat[2] = TH; // 湿度高位
- rec_dat[3] = TL; // 湿度低位
- }
- return &rec_dat;
- }
- void DHT11() // 调用列子
- {
- uchar rec_dat[4]; // 定义一个温湿度存储数组01 存储温度高低位23存储湿度高低位
- float temp_float; // 温度值
- float HU_float; // 湿度值
- uchar *dis_str;
- int count;
- count++; // 统计采集次数
- DHT11_delay_ms(2000); // dht11上电后等待1秒,为了确保数据精确性,与采集间隔2秒限制,直接延迟2秒
- // 数据采集部分-----------------------------------------
- dis_str = DHT11_receive(&rec_dat);
- // 数据计算部分-----------------------------------------
- temp_float = rec_dat[0] + (float)((float)rec_dat[1] / 100);
- HU_float = rec_dat[2] + (float)((float)rec_dat[3] / 100);
- }
复制代码
DHT11.h
- #ifndef DHT11_H // 防止重复 include
- #define DHT11_H
- #endif
- #include <reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- // 声明全局变量
- sbit Data = P2 ^ 0; // 定义dht11数据线
- sbit rs = P3 ^ 5;
- sbit rw = P3 ^ 6;
- sbit en = P3 ^ 4;
- // uchar rec_dat[30]; // 接收1602显示数据数组
- sbit DU = P2 ^ 6; // 关闭数码段位
- sbit WE = P2 ^ 7; // 关闭数码管位
- // 声明计函数
- void DHT11_delay_ms(uint z);
- void DHT11_start();
- uchar DHT11_rec_byte();
- uchar *DHT11_receive(uchar rec_dat[]);
- void DHT11();
- void DHT11_delay_us(uchar n);
- void DHT11_delay_ms(uint z);
复制代码 LCD1602.C
- #include "LCD1602.h" //包含了STC89C52的头文件
- void delay(unsigned int i)
- { // 延迟函数,i为延迟时间
- unsigned int j;
- for (; i > 0; i--) {
- for (j = 0; j < 125; j++)
- ;
- }
- }
- void lcd_busy()
- { // 判断LCD是否忙的函数
- unsigned char busy;
- P0 = 0xFF; // 将P0口设为输入模式
- RS = 0; // RS置为低电平
- RW = 1; // RW置为高电平
- EN = 0; // 使能引脚EN置为低电平
- delay(5); // 延时5ms
- do {
- EN = 1; // 使能引脚EN置为高电平
- busy = P0; // 读取P0口的值
- EN = 0; // 使能引脚EN置为低电平
- } while (busy & 0x80); // 判断busy的最高位是否为1
- P0 = 0x00; // 将P0口设为输出模式
- }
- void lcd_write_cmd(unsigned char cmd)
- { // 发送命令的函数
- lcd_busy(); // 判断LCD是否忙
- RS = 0; // RS置为低电平
- RW = 0; // RW置为低电平
- EN = 0; // 使能引脚EN置为低电平
- P0 = cmd; // 将命令写入P0口
- EN = 1; // 使能引脚EN置为高电平
- EN = 0; // 使能引脚EN置为低电平
- }
- void lcd_write_data(unsigned char dat)
- { // 发送数据的函数
- lcd_busy(); // 判断LCD是否忙
- RS = 1; // RS置为高电平
- RW = 0; // RW置为低电平
- EN = 0; // 使能引脚EN置为低电平
- P0 = dat; // 将数据写入P0口
- EN = 1; // 使能引脚EN置为高电平
- EN = 0; // 使能引脚EN置为低电平
- }
- void lcd_set_pos(unsigned char x, unsigned char y)
- { // 设置显示位置的函数
- unsigned char pos;
- if (y == 0) { // 第一行
- pos = 0x80 + x; // 计算显示位置
- } else { // 第二行
- pos = 0xC0 + x; // 计算显示位置
- }
- lcd_write_cmd(pos); // 发送命令,设置显示位置
- }
- void lcd_init()
- { // LCD初始化函数
- lcd_write_cmd(0x38); // 设置LCD显示模式为2行,5*7点阵
- lcd_write_cmd(0x0C); // 显示开,不显示光标,不闪烁
- lcd_write_cmd(0x06); // 文字不动,地址自动+1
- lcd_write_cmd(0x01); // 清屏
- }
- void lcd_show_char(unsigned char x, unsigned char y, unsigned char dat)
- { // 显示单个字符的函数
- lcd_set_pos(x, y); // 设置显示位置
- lcd_write_data(dat); // 发送数据,显示字符
- }
- void lcd_show_str(unsigned char x, unsigned char y, char *str)
- { // 显示字符串的函数
- lcd_set_pos(x, y); // 设置显示位置
- while (*str) { // 当字符串不为空
- lcd_write_data(*str++); // 发送数据,显示字符
- }
- }
- /*
- 参数1 x:第几行
- 参数2 y:第几列
- 参数3 num:具体数值
- */
- void lcd_show_float(unsigned char x, unsigned char y, float num)
- { // 显示浮点数的函数
- int integer = (int)num; // 整数部分
- int integer2 = integer;
- int decimal = (int)((num - integer) * 100); // 小数部分,保留2位
- int wei_cout = 0;
- while (integer2) {
- integer2 /= 10;
- wei_cout++;
- }
- // 计算整数部分位数
- lcd_show_int(x, y, integer); // 先显示整数部分
- lcd_write_data('.'); // 小数点
- if (wei_cout == 0) { // 如果整数部分=0
- if (decimal > 10) { // 如果小数部分>0.1
- lcd_show_int(x + wei_cout + 2, y, decimal); // 再显示小数部分
- } else { // 如果小数部分<=0.1
- lcd_show_int(x + wei_cout + 2, y, 0);
- lcd_show_int(x + wei_cout + 3, y, decimal);
- }
- } else { // 如果整数部分大于0
- // lcd_show_int(x + wei_cout + 1, y, decimal); // 再显示小数部分
- if (decimal > 10) { // 如果小数部分>0.1
- lcd_show_int(x + wei_cout + 1, y, decimal); // 再显示小数部分
- } else { // 如果小数部分<=0.1
- lcd_show_int(x + wei_cout + 1, y, 0);
- lcd_show_int(x + wei_cout + 2, y, decimal);
- }
- }
- }
- void lcd_show_int(unsigned char x, unsigned char y, int num)
- { // 显示整数的函数
- char str[16]; // 定义一个字符串数组
- sprintf(str, "%d", num); // 将整数转换为字符串
- lcd_show_str(x, y, str); // 调用显示字符串的函数,显示整数
- }
- void LCD1602() // LCD1602 调用列子
- {
- lcd_init(); // 初始化LCD
- lcd_show_str(0, 0, "Hello World!"); // 显示字符串
- lcd_show_int(0, 1, 123); // 显示整数
- lcd_show_float(6, 1, 596.0422); // 显示浮点数
- while (1)
- ; // 循环等待
- }
复制代码
LCD1602.H
- #ifndef LCD1602_H // 防止重复 include
- #define LCD1602_H
- #endif
- #include <reg52.h>
- #include <stdio.h>
- // 声明全局变量
- sbit RS = P3 ^ 5; // 将寄存器选择引脚RS定义为P3.5
- sbit RW = P3 ^ 6; // 将读写选择引脚RW定义为P3.6
- sbit EN = P3 ^ 4; // 将使能引脚EN定义为P3.4
- // 声明函数
- void lcd_show_int(unsigned char x, unsigned char y, int num);
- void lcd_show_float(unsigned char x, unsigned char y, float num);
- void lcd_show_str(unsigned char x, unsigned char y, char *str);
- void lcd_show_char(unsigned char x, unsigned char y, unsigned char dat);
- void lcd_init();
- void lcd_set_pos(unsigned char x, unsigned char y);
- void lcd_write_data(unsigned char dat);
- void lcd_write_cmd(unsigned char cmd);
- void lcd_busy();
- void delay(unsigned int i);
- void LCD1602();
复制代码
|
|