关于LCD12864的显示问题

2019-07-15 23:07发布

最近在用LCD12864做一个数字时钟,时间部分已经基本搞定,就是往里面添加温度显示时,虽然可以显示温度,但是显示一会后就出现乱码了,而且添加在主函数里延时过大,影响功能按键的使用。
求大神帮忙看一下。时间显示,按键控制,温度显示,闹钟设置,AD转换识别系统,  还有一个我未实现的用串口来设置初始时间的问题。
#include<reg52.h>
#include<intrins.h>
#include<stdlib.h>
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P3^5;       //定义DS18B20数据线引脚端
char a,d2,d1,d0;
float f_temp;
uint i,j,temp,low,high;
/*端口定义*/
#define LCD_data P0
#include"24c02.h"
sbit RS = P2^7;
sbit RW = P2^6;
sbit EN = P2^5;
sbit s1 = P3^2;  //SW1定义为--功能键
sbit s2 = P3^3;  //SW2定义为--增大键
sbit s3 = P3^4;  //SW3定义为--减小键
sbit feng = P3^2;//蜂鸣器
/************************************************/
sbit adwr = P2^1;    //定义A/D的WR端口
sbit adrd = P2^2;  //定义A/D的RD端口
sbit adcs = P3^6;
/***********************************************/
uchar code dis1[]={"    现在时间    "};//10
uchar code dis2[]={"    --  --      "};
uchar code dis3[]={"    :   :       "};
uchar code dis4[]={"现在温度: 00.0度"};  //6
uchar t=0,s1num;
char miao,shi,fen,ri,yue,nian;
void delay(uint z)    //延时
{
uint r,w;
for(r=0;r<z;r++)
  for(w=0;w<110;w++);
}  
/*写指令数据到LCD*/
/*RS=0,RW=0,E=高脉冲,D0--D7=指令码。*/
void write_cmd(uchar cmd)
{
RS = 0;
RW = 0;
EN = 0;
P0 = cmd;
delay(5);
EN = 1;
delay(5);
EN = 0;
}
/*写显示数据到LCD*/
/*RS=1,RW=0,E=高脉冲,D0--D7=数据*/
void write_dat(uchar dat)   //写入
{
RS = 1;
RW = 0;
EN = 0;
P0 = dat;
delay(5);
EN = 1;
delay(5);
EN = 0;
}
/*设置显示位置*/
void lcd_pos(uchar X,uchar Y) //方便主函数调用点地址
{
uchar pos;
if(X==0)
{X=0x80;}
else if(X==1)
{X=0x90;}
else if(X==2)
{X=0x88;}
else if(X==3)
{X=0x98;}
pos = X+Y;
write_cmd(pos);     //显示地址
}
void write_sfm(uchar app,uchar add,uchar date) //写时分秒函数
{
uchar shi,ge;
shi = date/10;   //分解一个2位数的十位和个位
ge = date%10;
lcd_pos(app,add);  //设置显示位置
write_dat(0x30+shi);  //送去液晶显示十位
write_dat(0x30+ge);  //送去液晶显示个位
}  
void init()   /*LCD初始化设定*/
{
uint g;
write_cmd(0X30);  //基本指令操作
delay(5);
write_cmd(0X0C);  //显示开,关光标
delay(5);
write_cmd(0X01);  //清除LCD的显示内容
delay(5);

fen = 0;  //初始化分钟变量值
miao = 0;
shi = 0;
s1num = 0;
init_24c02();
//
lcd_pos(1,0);
g = 0;
while(dis2[g]!='')   //
{
  write_dat(dis2[g]);   //显示字符
  g++;
}
lcd_pos(2,0);
g = 0;
while(dis3[g]!='')   //
{
  write_dat(dis3[g]);   //显示字符
  g++;
}
//
miao = read_add(1); //首次上电从AT4C02中读取存储的数据
fen = read_add(2);
shi = read_add(3);
ri = read_add(4); //首次上电从AT4C02中读取存储的数据
yue = read_add(5);
nian = read_add(6);
write_sfm(2,5,miao);
write_sfm(2,3,fen);
write_sfm(2,1,shi);
write_sfm(1,5,ri);
write_sfm(1,3,yue);
write_sfm(1,1,nian);   
TMOD=0x01;   //设置定时器1为工作方式1
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
ET0 = 1;  //开定时器1中断
TR0 = 1;  //启动定时器1
EA = 1;   //开总中断
   
}

void bell()    //蜂鸣器定时
{
if(shi == 12)
{ if(fen == 12)
  {
  feng = 0;
  delay(1000);
  feng = 1;
  delay(1000);
  }
}
else
feng = 1;
}
void ad()
{  uchar adva1;
  adcs = 0;
  adwr = 1;
  _nop_();
  adwr = 0;
  _nop_();
  adwr = 1;
  delay(40);   
  P1 = 0xff;         
  adrd = 1;      
  _nop_();
  adrd = 0;
  _nop_();
  adva1 = P1;
  adrd = 1;   
  if(adva1 < 102)   
  {
  write_cmd( 0x08 );
  }//关了不可再打开,但加判断就会影响显示
  //设想 关了后 再次调整ad,然后按建就可显示
// else
// {
// write_cmd( 0x0c );
// }
}

void dat_dis()
{
lcd_pos(3,5);  //显示温度
write_dat(0x30+d2);
write_dat(0x30+d1);
lcd_pos(3,6);  //显示温度
write_dat(0x2e);  //写入“.”号
write_dat(0x30+d0);
}
void init_temp()
{
DQ=0;  //拉低总线,产生复位信号
i=80;while(i>0)i--;  //延时480~960us
DQ=1;  //拉高总线
i=4;while(i>0)i--;  //延时15~60us
while(DQ);  //等待产生应答脉冲
i=70;while(i>0)i--;  //延时至少480us
}
//------------------获温部分:写函数-------------------------------
void wr_temp(uchar dat)  //写1个字节
{
bit testb;
for(j=8;j>0;j--)
{
   testb=dat&0x01;
   dat=dat>>1;
   if(testb)  //写1
   {
    DQ=0;  //拉低总线,产生写时间隙
    i++;  //延时大于1us
    DQ=1;  //拉高总线
    i=8;while(i>0)i--;  //延时至少60us,供DS18B20采样
   }
   else    //写0
   {
    DQ=0;  //拉低总线,产生写时间隙
    i=8;while(i>0)i--;  //保持至少60us,供DS18B20采样
    DQ=1;  //拉高总线
    i++;i++;
   }
}
}
//------------------获温部分:读函数-------------------------------
uchar rd_temp()  //读1个字节
{
bit b;  //定义存放接收到的1个字节
uchar i_b;
uchar rdbyte;
for(j=8;j>0;j--)
{
  DQ=0;  //拉低总线,产生读时隙
  i++;  //延时大于1us
  DQ=1;  //释放总线
  i++;i++;  //给一定时间让总线释放
  b=DQ;  //读取数据
  i=8;while(i>0)i--;  //延时至少60us
  i_b=b;
  rdbyte=(i_b<<7)|(rdbyte>>1);  //将读取到得一位值左移7位,存放读取的数据变量rdbyte右移1位
}
return rdbyte;
}
//----------------------温度获取函数---------------------------
void get_temp()
{
init_temp();  //初始化,复位并获取应答信号
wr_temp(0xcc);  //跳过ROM
wr_temp(0x44);  //开始温度转换
delay(1000);  //等待温度转换完成
init_temp();  //将DS18B20复位
wr_temp(0xcc);  //跳过ROM
wr_temp(0xbe);  //读暂存器
low=rd_temp();  //读取低8位
high=rd_temp();  //读取高8位
temp=high;
temp<<=8;
temp=temp|low;  //将读取的低8位和高8位合并
f_temp=temp*0.0625;  //温度在寄存器中为12位 分辨率位0.0625°
temp=f_temp*10+0.5;  //精确到十分位,四舍五入
d2=temp/100;  //显示数据:十位
d1=temp%100/10;  //显示数据:个位
d0=temp%10;  //显示数据:十分位
}
void xianshi()
{ uchar g;
lcd_pos(0,0);
g = 0;
while(dis1[g]!='')   //
{
  write_dat(dis1[g]);   //显示字符
  g++;
}
lcd_pos(3,0);
g = 0;
while(dis4[g]!='')   //
{
  write_dat(dis4[g]);   //显示字符
  g++;
}
}
void keyscan()  //键盘扫描函数
{

if(s1==0)
{
  delay(5);
  if(s1==0)   //确认功能键被按下
  {
   s1num++;   //功能键按下次数计数
   delay(5);
   while(!s1);  //释放确认
      
   if(s1num==1)  //第一次被按下时
   {
    TR0 = 0;   //关闭定时器
    lcd_pos(2,5);  //光标移动到秒位置
    write_cmd(0x0f);   //光标开始闪烁
   }
   if(s1num==2)    //第二次按下光标闪烁定位到分钟位置
   {
    lcd_pos(2,3);
   }
   if(s1num==3)  //第三次按下光标闪烁定位到小时位置
   {
    lcd_pos(2,1);
   }
    if(s1num==4)  //第三次按下光标闪烁定位到小时位置
   {
    lcd_pos(1,5);
   }
    if(s1num==5)  //第三次按下光标闪烁定位到小时位置
   {
    lcd_pos(1,3);
   }
    if(s1num==6)  //第三次按下光标闪烁定位到小时位置
   {
    lcd_pos(1,1);
   }
   if(s1num==7)   //第四次按下
   {
    s1num = 0;  //记录按键数清0
    write_cmd(0x0c); //取消光标闪烁
    TR0 = 1;    //启动定时器时钟开始走
   }
  }
}
if(s1num!=0)
{
  if(s2==0)
  {
   delay(5);
   if(s2==0)
   {
    delay(5);
    while(!s2);
    if(s1num==1)
    {
     miao++;
     if(miao==60)
      miao = 0;
     write_sfm(2,5,miao);
     lcd_pos(2,5);
     write_add(1,miao);
    }
    if(s1num==2)
    {
     fen++;
     if(fen==60)
      fen = 0;
     write_sfm(2,3,fen);
     lcd_pos(2,3);
     write_add(2,fen);
    }
    if(s1num==3)
    {
     shi++;
     if(shi==24)
      shi = 0;
     write_sfm(2,1,shi);
     lcd_pos(2,1);
     write_add(3,shi);
    }
    if(s1num==4)
    {
     ri++;
     if(ri==31)
      ri = 0;
     write_sfm(1,5,ri);
     lcd_pos(1,5);
     write_add(4,ri);
    }
    if(s1num==5)
    {
     yue++;
     if(yue==13)
      yue = 0;
     write_sfm(1,3,yue);
     lcd_pos(1,3);
     write_add(5,yue);
    }
    if(s1num==6)
    {
     nian++;
     if(nian==100)
      nian = 0;
     write_sfm(1,1,nian);
     lcd_pos(1,1);
     write_add(6,nian);
    }
   }
  }
if(s3==0)
  {
   delay(5);
   if(s3==0)
   {
    while(!s3);
    if(s1num==1)
    {
     miao--;
     if(miao==-1)
      miao = 59;
     write_sfm(2,5,miao);
     lcd_pos(2,5);
     write_add(1,miao);
    }
    if(s1num==2)
    {
     fen--;
     if(fen==-1)
      fen = 59;
     write_sfm(2,3,fen);
     lcd_pos(2,3);
     write_add(2,fen);
    }
    if(s1num==3)
    {
     shi--;
     if(shi==-1)
      shi = 23;
     write_sfm(2,1,shi);
     lcd_pos(2,1);
     write_add(3,shi);
    }
    if(s1num==4)
    {
     ri--;
     if(ri==-1)
      ri = 30;
     write_sfm(1,5,ri);
     lcd_pos(1,5);
     write_add(4,ri);
    }
    if(s1num==5)
    {
     yue--;
     if(yue==-1)
      yue = 12;
     write_sfm(1,3,yue);
     lcd_pos(1,3);
     write_add(5,yue);
    }
    if(s1num==6)
    {
     nian--;
     if(nian==-1)
      nian = 99;
     write_sfm(1,1,nian);
     lcd_pos(1,1);
     write_add(6,nian);
    }
   }
  }  
}
}
void main()    //主函数
{

//delay(10);
init();
xianshi();

while(1)
{
  keyscan();
  if(s1num==0)
{
    get_temp();
  dat_dis();
  bell();     
}
  ad();
}
}
void timer0() interrupt 1          //中断
{
TH0 = (65536-45000) / 256;
TL0 = (65536-45000) % 256;
t++;
   
if(t == 20)
  {   
   t = 0;
         miao++;
   if(miao == 60)
   {
    miao = 0;
    fen++;
    if(fen == 60)
    {
     fen = 0;
     shi++;
     if(shi == 24)
     {
      shi = 0;
      ri++;
      if(ri == 31)
      {
       ri = 0;
       yue++;
       if(yue == 13)
       {
        yue = 0;
        nian++;
         if(nian == 100)
        {
         nian = 0;
        }   
        write_sfm(1,1,nian);
        write_add(6,nian);
       }
       write_sfm(1,3,yue);
       write_add(5,yue);
      }
      write_sfm(1,5,ri);
      write_add(4,ri);
        }
     write_sfm(2,1,shi);
     write_add(3,shi);
    }
    write_sfm(2,3,fen);
    write_add(2,fen);
   }
   write_sfm(2,5,miao);
   write_add(1,miao);   
  }
  
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
8条回答
syzy2012941005
2019-07-16 04:51
woshiaokeman 发表于 2013-8-11 09:17
这么长。。建议你看看模块化编写程序的方法,还有“从单片机初学者迈向单片机工程师”这个文档 ...

多谢提醒,模块化的我也看过一些,就是自己编写的时候除了点问题,若是简单的在12864上显示文字,还是能编写的,可是就是不知道为什么,编写一个可控制时钟时就是编译不了,貌似是调用函数时出了点问题,一大堆警告没错误,且生成不了HEX文件,作为一个初学者,相当的苦恼。

C语言模块化编程(我见过最好的).pdf 下载积分: 积分 -1 分

1.28 MB, 下载次数: 358, 下载积分: 积分 -1 分

一周热门 更多>