个人成长笔记--使用89C52在1602液晶屏上显示日期和温度

个人成长笔记–使用89C52在1602液晶屏上显示日期和温度

LCD1602配置过程:

#include "config.h"
#include "Lcd1602.h"

//首先判断1602忙不忙
void Read_Busy()
{
	uint8 busy;
	LCD_DB = 0xFF;//首先复位数据总线
	LCD_RS = 0;
	LCD_RW = 1;
	do
	{
		LCD_EN = 1;//先使能,才可以发送数据
		busy = LCD_DB;//发送数据
		LCD_EN = 0;//拉低使能,以便下一次产生上升沿
	}while(busy & 0x80);//与D7相与,为1表示忙,程序一直循环等待
	//while(busy |= 0x01);//错了,D7是最高位,所以选择要与最高位相比较
}

//写命令
void Write_Cmd_Byte(uint8 cmd)
{
	Read_Busy();//记住先判断忙不忙
	LCD_RS = 0;
	LCD_RW = 0;
	LCD_DB = cmd;//写入指令
	LCD_EN = 1;//使能
	LCD_EN = 0;//每次都要记得拉低使能位,方便下次产生上升沿
}

//写数据
void Write_Data_Byte(uint8 dat)
{
	Read_Busy();//记住先判断忙不忙
	LCD_RS = 1;
	LCD_RW = 0;
	LCD_DB = dat;//写入数据
	LCD_EN = 1;//使能
	LCD_EN = 0;//每次都要记得拉低使能位,方便下次产生上升沿
}

//清屏
void Clear_Screen()
{
	Write_Cmd_Byte(0x01);//清除数据
}

//打开光标闪烁
void Open_Cursor()
{
	Write_Cmd_Byte(0x0F);//打开光标
}

//关闭光标
void Close_Cursor()
{
	Write_Cmd_Byte(0x0C);//关闭光标
}

//设置指令在哪个位置显示
void Set_Cursor(uint8 x,uint8 y)
{
	if(y)
	{
		x |= 0x40;//如果y=1;就在第二行显示,x等于多少就在多少列显示
	}
		x |= 0x80;//否则,在第一行显示,
	//还要写指令,不然怎样显示
	Write_Cmd_Byte(x);
}

//在指定位置显示一个字符串
void Dis_OneChar(uint8 x,uint8 y,uint8 dat)
{									 
	Set_Cursor(x,y);
	Write_Data_Byte(dat);
}

//在指定位置显示字符串
void Dis_Str(uint8 x,uint8 y,uint8 *str)
{
	Set_Cursor(x,y);
	while(*str != '\0')
	{
		Write_Data_Byte(*str++);
	}
}

//1602初始化
void LCD1602_Init()
{
	Write_Cmd_Byte(0x38);//显示模式设置
	Write_Cmd_Byte(0x0C);//开显示,关闭光标
	Write_Cmd_Byte(0x06);//读写一字节后地址指针加1
	Write_Cmd_Byte(0x01);//显示清屏
}

DS18B20配置过程:

#include "config.h"
#include "DS18B20.h"

//前提是晶振在11.0952情况下
//us延时函数,执行一次us---所需6.5us进入一次函数需要11.95us
void Delay_us(uchar us)
{
	while(us--);
}

//单总线初始化时序
bit Ds_Init()
{
	bit i;
	EA = 0;//禁止总中断
	DS18B20_IO = 1;//先置高释放一下总线
	_nop_();//延时5us,稳定一下
	DS18B20_IO = 0;//再把总线置低,开始复位
	Delay_us(75);//至少拉低480us,总线将全部被复位,75*6.5+11.95=499.45us
	DS18B20_IO = 1;//释放总线
	Delay_us(4);//延时4*6.5+11.95=37.95us,等待18B20发回存在信号
	i = DS18B20_IO;//把返回值赋值给i
	Delay_us(20);//延时20*6.5+11.95=141.95us,读取存在信号的时间
	DS18B20_IO = 1;//释放总线
	_nop_();//延时5us,稳定一下
	EA = 1;//使能总中断
	return(i);//如果i=0则存在总线上,并且DS18B20已经准备好了。
}

//写一个字节
void Write_Byte(uchar dat)
{
	//一次只能写一位,一个字节8位,所以循环8次
	uchar i;
	EA = 0;//禁止总中断
	for(i=0;i<8;i++)
	{
		DS18B20_IO = 0;//初始化化的时候已经释放总线了,现在直接拉低
		_nop_();//延时大于1us产生写时序
		DS18B20_IO = dat & 0x01;//从最低位开始写
		Delay_us(10);//10*6.5+11.95=76.95us,写0时需要60~120us。写1时需要60us以上,所以都符合
		DS18B20_IO = 1;//释放总线
		_nop_();//两个周期之间需要间隔大于1us
		dat>>=1;//把读到最低位放进高位,然后在把低位放高位,最后最低位就会到最低位
	}
	EA = 1;//使能总中断
}

//读一个字节
uchar Read_Byte()
{
	//一次只能读一位,一个字节8位,所以循环8次
	uchar i,j,dat;
	EA = 0;//禁止总中断
	for(i=0;i<8;i++)
	{
		DS18B20_IO = 0;//初始化化的时候已经释放总线了,现在直接拉低
		_nop_();//延时大于1us产生读时序
		DS18B20_IO = 1;//释放总线,交给18B20控制
		_nop_();
		j = DS18B20_IO;//从最低位读取,一个读一个位
		Delay_us(10);//10*6.5+11.95=76.95us,读一位需要延时60~120us
		DS18B20_IO = 1;//释放总线
		_nop_();//两个周期之间需要间隔大于1us
		dat = (j<<7) | (dat>>1);//j把读到最低位左移7位到达dat最高位,dat在整体左移一位
	}
	EA = 1;//使能总中断
	return(dat);
}

//启动一次18B20温度转换
bit Start_DS18B20()
{
	bit ack;
	ack = Ds_Init();//获取18B20应答
	if(ack == 0)//如果ack值为0,则应答,if语句就为真
	{
		Write_Byte(0xCC);//总线上只有一个18B20,所以跳过ROM操作
		Write_Byte(0x44);//启动一次温度转换
	}
	return ~ack;//ack等于0就是应答,取反就是1,返回1就代表启动成功
}

//读取DS18B20转换温度值
bit Get_DS18B20_Temp(int16 *temp)
{
	bit ack;
	uint8 LSB,MSB;//16位的温度值的低字节和高字节
	ack = Ds_Init();//获取18B20应答
	if(ack == 0)//如果ack值为0,则应答,if语句就为真
	{
		Write_Byte(0xCC);//总线上只有一个18B20,所以跳过ROM操作
		Write_Byte(0xBE);//发送读命令
		LSB = Read_Byte();//先读低位,一共8位,低位数据存在最低位
		MSB = Read_Byte();//在读高位,一共8位,高位数据存在最高位
		*temp = ((int16)MSB << 8) + LSB;//把MSB强制转换成16位,MSB左移8位,把高8位存到高八位,加LSB的低8位,正好转换成整型16位
	}
	return ~ack;//ack等于0就是应答,取反就是1,返回1就代表获取成功
}

然后再应用写调用函数:

//获取温度,并显示到液晶屏上
//ops:为0时,只有温度变化才刷新,非0则立即刷新
void RefreshTemp(uint8 ops)
{
	int16 temp;
	uint8 pdata str[6];
	static int16 backup = 0;
	
	Get_DS18B20_Temp(&temp);//获取当前温度值
	Start_DS18B20();//启动下一次转换
	temp >>= 4;//舍弃4位小数位
	if((backup!=temp) || (ops!=0))//按照需要刷新液晶显示
	{
		str[0] = (temp/10) + '0';//十位转ASCII码
		str[1] = (temp%10) + '0';//个位转ASCII码
		str[2] = '\'';//用'C代替°C
		str[3] = 'C';
		str[4] = '\0';//字符串结束符
		Dis_Str(12,1,str);//显示到液晶上
		backup = temp;//刷新上一次温度值
	}
}

结果显示:
这里以上代码对温度的显示,日期和时间是之前所写。

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
LCD1602液晶显示DS1302时钟实验例程C51单片机KEIL工程源码文件: void main (void) { unsigned char i; unsigned char temp[16];//定义显示区域临时存储数组 LCD_Init(); //初始化液晶 DelayMs(20); //延时有助于稳定 LCD_Clear(); //清屏 Init_Timer0(); //定时器0初始化 Ds1302_Init(); //ds1302初始化 UART_Init(); //串口初始化 Ds1302_Read_Time(); //首次读取时间 if((time_buf1[2]+time_buf1[7])==0) //如果所有参数都为0,写入一个初始值 Ds1302_Write_Time(); while (1) //主循环 { if(SetFlag) //如果接收到串口信息则更新时钟 { for(i=0;i<8;i++) { time_buf1[i]=time_buf2[2*i]*10+time_buf2[2*i+1];//数据整合,如2个数 1和5整合成15 } Ds1302_Write_Time();//接收更新的时间然后写入ds1302 SetFlag=0; //时钟信息更新后标志位清零 } if(ReadTimeFlag==1) //定时读取ds1302 定时时间到 则标志位置1,处理过时间参数标志位清零 { ReadTimeFlag=0; //标志位清零 Ds1302_Read_Time();//读取时间参数 sprintf(temp,"DATE %02d-%02d-%02d %d",(int)time_buf1[1],(int)time_buf1[2],(int)time_buf1[3],(int)time_buf1[7]);//年月日周 LCD_Write_String(0,0,temp);//显示第一行 sprintf(temp,"TIME %02d:%02d:%02d",(int)time_buf1[4],(int)time_buf1[5],(int)time_buf1[6]);//时分秒 LCD_Write_String(0,1,temp);//显示第二行 } } } /*------------------------------------------------ 串口通讯初始化 ------------------------------------------------*/ void UART_Init(void) { SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收 TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装 TH1 = 0xFD; // TH1: 重装值 9600 波特率 晶振 11.0592MHz TR1 = 1; // TR1: timer 1 打开 EA = 1; //打开总中断 ES = 1; //打开串口中断 } /*------------------------------------------------ 定时器初始化子程序 ------------------------------------------------*/ void Init_Timer0(void) { TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 //TH0=0x00; //给定初值 //TL0=0x00; EA=1; //总中断打开 ET0=1; //定时器中断打开 TR0=1; //定时器开关打开 } /*-----------------------------------------------
您可以使用C语言编程,结合C51单片机和DHT11传感器与LCD1602显示屏进行温度显示。下面是一个示例代码,您可以参考: ```c #include <reg51.h> #include <stdio.h> #include <string.h> #define LCD_RS P2_0 #define LCD_RW P2_1 #define LCD_EN P2_2 #define LCD_DATA P0 void delay(unsigned int time) { unsigned int i, j; for (i = 0; i < time; i++) for (j = 0; j < 1275; j++); } void lcd_command(unsigned char cmd) { LCD_RS = 0; LCD_RW = 0; LCD_DATA = cmd; LCD_EN = 1; delay(1); LCD_EN = 0; } void lcd_data(unsigned char dat) { LCD_RS = 1; LCD_RW = 0; LCD_DATA = dat; LCD_EN = 1; delay(1); LCD_EN = 0; } void lcd_init() { lcd_command(0x38); // 8-bit数据接口,显示2行,5x7点阵字符 lcd_command(0x0C); // 显示开,光标和闪烁关闭 lcd_command(0x06); // 光标右移 lcd_command(0x01); // 清屏 } void lcd_display_string(unsigned char row, unsigned char column, unsigned char *str) { if (row == 0) lcd_command(0x80 + column); else if (row == 1) lcd_command(0xC0 + column); while (*str != '\0') { lcd_data(*str); str++; } } void dht11_read(unsigned char *temp, unsigned char *humi) { // 读取DHT11数据的代码,请根据您的具体硬件和引脚定义进行修改 // ... // 将温度和湿度值存入temp和humi指针指向的变量中 } void main() { unsigned char temp_str[16]; unsigned char humi_str[16]; unsigned char temp, humi; lcd_init(); while (1) { dht11_read(&temp, &humi); sprintf(temp_str, "Temp: %d C", temp); sprintf(humi_str, "Humi: %d %%", humi); lcd_display_string(0, 0, temp_str); lcd_display_string(1, 0, humi_str); delay(1000); // 延时1秒钟 } } ``` 请注意,以上代码仅供参考,具体的引脚定义和DHT11传感器的读取代码可能需要根据您的实际硬件进行修改。另外,LCD1602显示屏的引脚连接也需要根据您的具体情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值