使用lcd1602在第一行显示“T:传感器读取的数据 A:传感器读取的数据”,在第二行显示“DO:传感器读取的数据”
这是main.c的代码
void Display_function(void)
{
switch(flag_display) //根据不同的显示模式标志位,显示不同的界面
{
case 0: //界面0:
lcd1602_display_str(1,0,"T:"); //显示温度
lcd1602_display_temp(1,2,temp_value);
lcd1602_display_str(1,10,"A:"); //显示氨氮
lcd1602_display_num_2(1,12,A_value);
lcd1602_display_str(2,0,"DO:"); //显示溶解氧
lcd1602_display_num(2,2,DO_value);
break;
请帮我看看这部分代码是否有问题
另外 我觉得问题出在显示函数上,以下是lcd函数
void lcd1602_display_num(uchar hang, uchar add, uint num)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(num >= 1000)
{
lcd1602_write_date(num/1000%10+48); //千
lcd1602_write_date(num/100%10+48); //百
lcd1602_write_date(num/10%10+48); //十
lcd1602_write_date(num/1%10+48); //个
}
else if(num >= 100)
{
lcd1602_write_date(num/100%10+48); //百
lcd1602_write_date(num/10%10+48); //十
lcd1602_write_date(num/1%10+48); //个
lcd1602_write_date(' '); //补空格
}
else if(num >= 10)
{
lcd1602_write_date(num/10+48); //十
lcd1602_write_date(num%10+48); //个
lcd1602_write_date(' '); //补空格
lcd1602_write_date(' '); //补空格
}
else
{
lcd1602_write_date(num+48); //个
lcd1602_write_date(' '); //补空格
lcd1602_write_date(' '); //补空格
lcd1602_write_date(' '); //补空格
}
}
/****
*******1602显示数字(2位)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* num:所要显示的数据,2位
*****/
void lcd1602_display_num_2(uchar hang, uchar add, uint num)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(num >= 10)
{
lcd1602_write_date(num/10+48); //十
lcd1602_write_date(num%10+48); //个
}
else
{
lcd1602_write_date(num+48); //个
lcd1602_write_date(' '); //补空格
}
}
/****
*******LCD1602显示温度函数(显示格式:**.*℃)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* temp:所要显示的温度
*****/
void lcd1602_display_temp(uchar hang, uchar add,int temp)
{
uchar display_temp_buf[8];
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(temp >= 0)
sprintf(display_temp_buf,"%d.%d",temp/10,temp%10);
else
sprintf(display_temp_buf,"-%d.%d",temp*(-1)/10,temp*(-1)%10);
lcd1602_display_str(hang,add,display_temp_buf);
lcd1602_write_date(0xdf); //显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码
lcd1602_write_date(0x43); //显示"C"符号,0x43是液晶屏字符库里大写C的地址码
lcd1602_write_date(' ');
lcd1602_write_date(' ');
}
/****
*******LCD1602显示函数(显示格式:****)
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* quality:所要显示的重量
*****/
void lcd1602_display_quality(uchar hang, uchar add,uint quality)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
if(quality >= 1000)
{
lcd1602_write_date(quality/1000%10+48); //千
lcd1602_write_date(quality/100%10+48); //百
lcd1602_write_date(quality/10%10+48); //十
lcd1602_write_date(quality/1%10+48); //个
}
else if(quality >= 100)
{
lcd1602_write_date(quality/100%10+48); //百
lcd1602_write_date(quality/10%10+48); //十
lcd1602_write_date(quality/1%10+48); //
}
else if(quality >= 10)
{
lcd1602_write_date(quality/10+48); //十
lcd1602_write_date(quality%10+48); //个
}
else
{
lcd1602_write_date(quality+48); //个
}
}
/****
*******LCD1602显示字符串函数
*******参量定义: hang:输入显示行数 1 第一行 2 第二行
******* add:偏移量,0-15
******* dat:所要显示的字符串,输入格式 " "
*****/
void lcd1602_display_str(uchar hang, uchar add, uchar *dat)
{
if(hang==1)
lcd1602_write_com(0x80+add); //第一行
else
lcd1602_write_com(0x80+0x40+add); //第二行
while(*dat != '\0')
{
lcd1602_write_date(*dat++);
}
}
现在的现象是什么?说出问题才好分析。
另外,别把data写成date好不好,虽然不影响程序运行,看起来真的很别扭
该回答通过自己思路及引用到GPTᴼᴾᴱᴺᴬᴵ搜索,得到内容具体如下:
根据您提供的代码,可以看出以下问题:
在 Display_function
函数中,显示第一行时只显示了 "T:" 和 "A:",但没有显示传感器读取的数据。您需要在调用 lcd1602_display_temp
和 lcd1602_display_num_2
函数时,将传感器读取的数据作为参数传递给这些函数。
在 Display_function
函数中,显示第二行时只显示了 "DO:",但也没有显示传感器读取的数据。您需要在调用 lcd1602_display_num
函数时,将传感器读取的数据作为参数传递给该函数。
在 lcd1602_display_str
函数中,输入的参数 dat
是一个指向字符数组的指针,但是该函数并没有对该指针所指向的字符数组进行空间分配或者初始化。因此,您需要在调用该函数时,将一个已经初始化并填充了内容的字符数组作为参数传递给该函数。
下面是修改后的代码:
void Display_function(void)
{
switch(flag_display) // 根据不同的显示模式标志位,显示不同的界面
{
case 0: // 界面0:
lcd1602_display_str(1,0,"T:"); // 显示温度
lcd1602_display_temp(1,2,temp_value);
lcd1602_display_str(1,10,"A:"); // 显示氨氮
lcd1602_display_num_2(1,12,A_value);
lcd1602_display_str(2,0,"DO:"); // 显示溶解氧
lcd1602_display_num(2,3,DO_value);
break;
}
}
注意,由于您的 LCD1602 显示函数可能存在一些特定的硬件接口要求,因此上述代码可能需要根据您的具体硬件环境进行适当的修改。
以下是修改后的完整代码,供参考:
#include <reg52.h>
#include <stdio.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit RS = P2^6;
sbit RW = P2^5;
sbit EN = P2^7;
void delay_ms(uint ms);
void lcd1602_write_com(uchar com);
void lcd1602_write_date(uchar date);
void lcd1602_init();
void lcd1602_clear();
void lcd1602_display_num(uchar hang, uchar add, uint num);
void lcd1602_display_num_2(uchar hang, uchar add, uint num);
void lcd1602_display_temp(uchar hang, uchar add,int temp);
void lcd1602_display_quality(uchar hang, uchar add,uint quality);
void lcd1602_display_str(uchar hang, uchar add, uchar *dat);
void Display_function(void);
int temp_value = 25;
int A_value = 100;
int DO_value = 80;
uchar flag_display = 0;
void main()
{
lcd1602_init();
while(1)
{
Display_function();
}
}
void Display_function(void)
{
switch(flag_display) // 根据不同的显示模式标志位,显示不同的界面
{
case 0: // 界面0:
lcd1602_display_str(1,0,"T:"); // 显示温度
lcd1602_display_temp(1,2,temp_value);
lcd1602_display_str(1,10,"A:"); // 显示氨氮
lcd1602_display_num_2(1,12,A_value);
lcd1602_display_str(2,0,"DO:"); // 显示溶解氧
lcd1602_display_num(2,3,DO_value);
break;
}
}
void delay_ms(uint ms)
{
uint i,j;
for(i=0;i<ms;i++)
for(j=0;j<114;j++);
}
void lcd1602_write_com(uchar com)
{
RS = 0;
RW = 0;
P0 = com;
EN = 1;
delay_ms(1);
EN = 0;
}
void lcd1602_write_date(uchar date)
{
RS = 1;
RW = 0;
P0 = date;
EN = 1;
delay_ms(1);
EN = 0;
}
void lcd1602_init()
{
lcd1602_write_com(0x38);
delay_ms(5);
lcd1602_write_com(0x38);
delay_ms(5);
lcd1602_write_com(0x38);
delay_ms(5);
lcd1602_write_com(0x08);
delay_ms(5);
lcd1602_write_com(0x01);
delay_ms(5);
lcd1602_write_com(0x06);
delay_ms(5);
lcd1602_write_com(0x0c);
delay_ms(5);
}
void lcd1602_clear()
{
lcd1602_write_com(0x01);
delay_ms(5);
}
void lcd1602_display_num(uchar hang, uchar add, uint num)
{
if(hang==1)
lcd1602_write_com(0x80+add); // 第一行
else
lcd1602_write_com(0x80+0x40+add); // 第二行
if(num >= 1000)
{
lcd1602_write_date(num/1000%10+48); // 千
lcd1602_write_date(num/100%10+48); // 百
lcd1602_write_date(num/10%10+48); // 十
lcd1602_write_date(num/1%10+48); // 个
}
else if(num >= 100)
{
lcd1602_write_date(num/100%10+48); // 百
lcd1602_write_date(num/10%10+48); // 十
lcd1602_write_date(num/1%10+48); // 个
lcd1602_write_date(' '); // 补空格
}
else if(num >= 10)
{
lcd1602_write_date(num/10+48); // 十
lcd1602_write_date(num%10+48); // 个
lcd1602_write_date(' '); // 补空格
lcd1602_write_date(' '); // 补空格
}
else
{
lcd1602_write_date(num+48); // 个
lcd1602_write_date(' '); // 补空格
lcd1602_write_date(' '); // 补空格
lcd1602_write_date(' '); // 补空格
}
}
void lcd1602_display_num_2(uchar hang, uchar add, uint num)
{
if(hang==1)
lcd1602_write_com(0x80+add); // 第一行
else
lcd1602_write_com(0x80+0x40+add); // 第二行
if(num >= 10)
{
lcd1602_write_date(num/10+48); // 十
lcd1602_write_date(num%10+48); // 个
}
else
{
lcd1602_write_date(num+48); // 个
lcd1602_write_date(' '); // 补空格
}
}
void lcd1602_display_temp(uchar hang, uchar add,int temp)
{
if(hang==1)
lcd1602_write_com(0x80+add); // 第一行
else
lcd1602_write_com(0x80+0x40+add); // 第二行
lcd1602_write_date(temp/10+48); // 十位
lcd1602_write_date('.'); // 小数点
lcd1602_write_date(temp%10+48); // 个位
lcd1602_write_date(0xdf); // °符号
lcd1602_write_date('C'); // 摄氏度符号
}
void lcd1602_display_quality(uchar hang, uchar add,uint quality)
{
if(hang==1)
lcd1602_write_com(0x80+add); // 第一行
else
lcd1602_write_com(0x80+0x40+add); // 第二行
if(quality >= 1000)
{
lcd1602_write_date(quality/1000%10+48); // 千
lcd1602_write_date(quality/100%10+48); // 百
lcd1602_write_date(quality/10%10+48); // 十
lcd1602_write_date(quality/1%10+48); // 个
}
else if(quality >= 100)
{
lcd1602_write_date(quality/100%10+48); // 百
lcd1602_write_date(quality/10%10+48); // 十
lcd1602_write_date(quality/1%10+48); // 个
lcd1602_write_date(' '); // 补空格
}
else if(quality >= 10)
{
lcd1602_write_date(quality/10+48); // 十
lcd1602_write_date(quality%10+48); // 个
lcd1602_write_date(' '); // 补空格
lcd1602_write_date(' '); // 补空格
}
else
{
lcd1602_write_date(quality+48); // 个
lcd1602_write_date(' '); // 补空格
lcd1602_write_date(' '); // 补空格
lcd1602_write_date(' '); // 补空格
}
}
void lcd1602_display_str(uchar hang, uchar add, uchar *dat)
{
if(hang==1)
lcd1602_write_com(0x80+add); // 第一行
else
lcd1602_write_com(0x80+0x40+add); // 第二行
while(*dat!='\0')
{
lcd1602_write_date(*dat);
dat++;
}
}
这个代码主要包括了液晶显示模块的初始化、清屏、显示数字、显示温度、显示字符串等功能函数,并且在主函数中实现了一些显示的逻辑,可以根据不同的标志位选择不同的显示模式。
如果以上回答对您有所帮助,点击一下采纳该答案~谢谢
以下是完整的主函数main
#include "main.h"
#include "lcd1602.h"
#include "key.h"
#include "timer.h"
#include "ds18b20.h"
#include "adc.h"
/**********************************
变量定义
**********************************/
uchar key_num = 0; //按键扫描标志位
uchar flag_display = 0; //显示界面标志位
uint time_num = 0; //10ms计时变量
uint A_value = 0; //氨氮值
uint A_max = 8; //氨氮最大值
uint A_min = 4; //氨氮最小值
uint temp_value = 0; //水温值
uint temp_max = 50; //水温最大值
uint temp_min = 20; //水温最小值
uint DO_value = 0; //溶解氧值
uint DO_max = 500; //溶解氧最大值
uint DO_min = 100; //溶解氧最小值
/**********************************
函数声明
**********************************/
void Delay_function(uint x); //延时函数(ms)
void Key_function(void); //按键函数
void Monitor_function(void); //监测函数
void Display_function(void); //显示函数
void Manage_function(void); //处理函数
/****
******* 主函数
*****/
void main()
{
Lcd1602_Init(); //LCD1602初始化
Delay_function(50); //延时50ms
lcd1602_clean(); //清屏
Delay_function(50); //延时50ms
Ds18b20_Init(); //DS18B20初始化函数
Delay_function(50); //延时50ms
while(1)
{
Key_function(); //按键函数
Monitor_function(); //监测函数
Display_function(); //显示函数
Manage_function(); //处理函数
Delay_function(10); //延时10ms
time_num++; //计时变量+1
if(time_num == 5000)
{
time_num = 0;
}
}
}
/****
******* 延时 x ms函数
*****/
void Delay_function(uint x)
{
uint m,n;
for(m=x;m>0;m--)
for(n=110;n>0;n--);
}
/****
*******按键函数
*****/
void Key_function(void)
{
key_num = Chiclet_Keyboard_Scan(0); //按键扫描
if(key_num != 0) //有按键按下
{
switch(key_num)
{
case 1: //按键1,切换设置界面
flag_display++;
if(flag_display >= 7)
flag_display = 0;
lcd1602_clean(); //清屏
break;
case 2: //按键2 加操作
switch(flag_display)
{
case 0: //界面0:
break;
case 1: //界面1:温度最大值+1
if(temp_max < 99)
temp_max++;
break;
case 2: //界面2:温度最小值+1
if(temp_min < temp_max-1)
temp_min++;
break;
case 3: //界面3:氨氮最大值+1
if(A_max < 14)
A_max++;
break;
case 4: //界面4:氨氮最小值+1
if(A_min < A_max-1)
A_min++;
break;
case 5: //界面5:溶解氧最大值+1
if(DO_max < 999)
DO_max++;
break;
case 6: //界面6:溶解氧最小值+1
if(DO_min < DO_max-1)
DO_min++;
break;
default:
break;
}
break;
case 3: //按键3,减操作
switch(flag_display)
{
case 0: //界面0:
break;
case 1: //界面1:温度最大值-1
if(temp_max > temp_min+1)
temp_max--;
break;
case 2: //界面2:温度最小值-1
if(temp_min > 0)
temp_min--;
break;
case 3: //界面3:氨氮最大值-1
if(A_max > A_min+1)
A_max--;
break;
case 4: //界面4:氨氮最小值-1
if(A_min > 0)
A_min--;
break;
case 5: //界面5:溶解氧最大值-1
if(DO_max > DO_min+1)
DO_max--;
break;
case 6: //界面6:溶解氧最小值-1
if(DO_min > 0)
DO_min--;
break;
default:
break;
}
break;
default:
break;
}
}
}
/****
*******监测函数
*****/
void Monitor_function(void)
{
if(time_num % 10== 0) //100ms检测一次
{
A_value = 14.9-(2.8*(Adc0832_Get_Value(0)/255.0)*5); //获取氨氮
DO_value = 1000-(200*(Adc0832_Get_Value(1)/255.0)*5); //获取溶解氧
temp_value = Ds18b20_Read_Temp(); //获取温度
}
}
/****
*******显示函数
*****/
void Display_function(void)
{
switch(flag_display) //根据不同的显示模式标志位,显示不同的界面
{
case 0: //界面0:
lcd1602_display_str(1,0,"T:"); //显示温度
lcd1602_display_temp(1,2,temp_value);
lcd1602_display_str(1,10,"A:"); //显示氨氮
lcd1602_display_num_2(1,12,A_value);
lcd1602_display_str(2,0,"DO:"); //显示溶解氧
lcd1602_display_num(2,2,DO_value);
break;
case 1: //界面1:显示设置温度最大值
lcd1602_display_str(1,2,"Set Temp Max");
if(time_num % 20 == 0)
{
lcd1602_display_num(2,7,temp_max);
}
if(time_num % 40 == 0)
{
lcd1602_display_str(2,7," ");
}
break;
case 2: //界面2:显示设置温度最小值
lcd1602_display_str(1,2,"Set Temp Min");
if(time_num % 20 == 0)
{
lcd1602_display_num(2,7,temp_min);
}
if(time_num % 40 == 0)
{
lcd1602_display_str(2,7," ");
}
break;
case 3: //界面3:显示设置氨氮最大值
lcd1602_display_str(1,3,"Set A Max");
if(time_num % 20 == 0)
{
lcd1602_display_num(2,7,A_max);
}
if(time_num % 40 == 0)
{
lcd1602_display_str(2,7," ");
}
break;
case 4: //界面4:显示设置氨氮最小值
lcd1602_display_str(1,3,"Set A Min");
if(time_num % 20 == 0)
{
lcd1602_display_num(2,7,A_min);
}
if(time_num % 40 == 0)
{
lcd1602_display_str(2,7," ");
}
break;
case 5: //界面5:显示设置溶解氧最大值
lcd1602_display_str(1,1,"Set DO Max");
if(time_num % 20 == 0)
{
lcd1602_display_num(2,7,DO_max);
}
if(time_num % 40 == 0)
{
lcd1602_display_str(2,7," ");
}
break;
case 6: //界面6:显示设置溶解氧最小值
lcd1602_display_str(1,1,"Set DO Min");
if(time_num % 20 == 0)
{
lcd1602_display_num(2,7,DO_min);
}
if(time_num % 40 == 0)
{
lcd1602_display_str(2,7," ");
}
break;
default:
break;
}
}
/****
*******处理函数
*****/
void Manage_function(void)
{
if(flag_display == 0) //测量界面
{
if(temp_value > temp_max*10 || temp_value < temp_min*10 || A_value > A_max || //温度超过设定值则声光报警
A_value < A_min || DO_value > DO_max || DO_value < DO_min)
{
if(time_num % 20 == 0)
{
BEEP = ~BEEP;
LED = ~LED;
}
}
else
{
BEEP =1;
LED = 1;
}
}
else //设置界面
{
BEEP =1;
LED = 1;
}
}
以下是完整的原理图
本实验使用到硬件资源如下:
(1)LCD1602 液晶
开发板上集成了一个 LCD1602 液晶接口,下面来看下开发板上 LCD1602 液晶接口电路,如下图所示:
从上图中可知,LCD1602 的 8 位数据口 DB0-DB7
与单片机的 P0.0-P0.7 管脚连接,LCD1602 的 RS、RW、E 脚与单片机的 P2.6、P2.5、P2.7 管脚连接。RJ1 是一个电位器,用来调节 LCD1602 对比度即显示亮度。
注意:这里原理图是使用的 8 位 LCD1602 接口设计,是可以兼容 4 位 LCD1602 的。对于非标准接口的 LCD1602,我们也会通过转接板将其转接为对应开发板接口的。对于 4 位 LCD1602 在传输数据的时候需要将 8 位的数据截成两段,先发送高四位,在发送低四位。其它引脚操作方法不变。