微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 闹铃程序转换1602界面时候乱码。。求指导

闹铃程序转换1602界面时候乱码。。求指导

时间:10-02 整理:3721RD 点击:
/*******************************************************************************
*标题:                    可调的DS1302时钟在LCD1602上显示                     *
*                                                                                                   *
********************************************************************************
*接线:JP8接JP5、蜂鸣器短路帽的左端接到P2^1(用一根杜邦线)                             *
*用杜邦线把P2^0连到led灯上(任意一个)                                                               *
*说明:本实验是在普中科技单片机开发板HC6800EM3上实现的                         *
********************************************************************************/                                       
#include<reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint  unsigned int
sbit SCK=P3^6;        //时钟       
sbit SDA=P3^4;        //数据       
sbit RST=P3^5;  // DS1302复位
sbit lcdrs=P2^6;
sbit lcdrw=P2^5;
sbit lcden=P2^7;
sbit key1=P1^0;                  //开调时键
sbit key2=P1^1;                  //调时加键
sbit key3=P1^2;                  //调时减键
sbit key4=P1^3;                  //开设定闹铃键
sbit key5=P1^4;                  //返回正常显示键
sbit key6=P1^5;                  //闹铃开关键
sbit DQ=P3^7;         //温度传感器数据通信位
sbit beep = P2^1;                  //蜂鸣器控制IO口
sbit led1 = P2^0;                  //led灯,闹铃响标志
bit  ReadRTC_Flag,Display_Flag,Alarm_Flag,flag;      //定义标志位
uchar miao,fen,shi,ri,yue,week,nian,T,C=0,k=0,m=0,n=0;
uchar set_miao,set_fen,set_shi,set_ri,set_yue,set_nian,TempBuffer[5],temp_value;
char l_tmpdate[7]={0x50,0x08,0x011,0x07,0x10,0x01,0x12};//设置初始时间,秒分时日月周年12-10-07 01:08:50
uchar code write_rtc_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c}; //秒分时日月周年 最低位写位
uchar code  read_rtc_address[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d}; //秒分时日月周年 最低位读位
uchar code table1[]="SUN";                           //星期字表
uchar code table2[]="MON";
uchar code table3[]="TUE";
uchar code table4[]="WED";
uchar code table5[]="THU";
uchar code table6[]="FRI";
uchar code table7[]="SAT";
uchar code tab1[]="20  -  -   ";
uchar code tab2[]="  :  :  ";
uchar code tab3[14]="  Set Alarm!  ";
char tab4[]={0,0,12};
/******************************************************************/
/*                    函数声明                                    */
/******************************************************************/                                                                                               
void Init_DS18B20(void);
unsigned char ReadOneChar(void);
void WriteOneChar(uchar dat);
void ReadTemp(void);
void temp_to_str();   //温度数据转换成液晶字符显示
void Write_Ds1302_byte(uchar temp);
void Write_Ds1302( uchar address,uchar dat );
uchar Read_Ds1302 ( uchar address );
void Read_RTC(void);
void Set_RTC(void);  
void delay(uchar a);
void delay1(uchar a);
void di();
void lcd_mang();
void write_lcd1602(uchar cmd,uchar i);
void ini_lcd1602();
void write_week(uchar xq);
void write_nyr(uchar add,uchar dat);
void write_sfm(uchar add,uchar dat);
void display();
void keyscan();
void alarm();
/******************************************************************/
/*                   主函数                                       */
/******************************************************************/
void main(void)   
{
    ini_lcd1602();
        Init_DS18B20();       
        //Set_RTC();                                     //写入时钟值,如果使用备用电池时候,不需要没每次上电写入,此程序应该屏蔽
        while(1)
        {
               
                ReadTemp();
                temp_to_str();
                keyscan();               
                if(ReadRTC_Flag==0)
                {
                          Read_RTC();
                       
                        if(Display_Flag==0)
                        {                               
                                display();                               
                        }
                        if(flag==1)
                        {
                                alarm();
                        }                                       
                }               
         }         
}

/******************************************************************/
/*                             毫秒级延时函数                                                       */
/******************************************************************/
void delay(uchar a)
{
     uchar i;
     while(a--)
           {
              for(i=0;i<250;i++)
                    {
                           _nop_();
               _nop_();
                           _nop_();
               _nop_();  
                        }
           }   
}
void delay1(uchar a)
{
     uchar i;
     while(a--)
           {
              for(i=0;i<5;i++)
                    {}
           }   
}
/******************************************************************/
/*                                     蜂鸣器发声函数                                         */
/******************************************************************/
void di()
{
        uchar i;
        while(key1==0||key2==0||key3==0||key4==0||key5==0||key6==0)
        {
                for(i=0;i<50;i++)
                {
                        delay1(4);
                        beep=~beep;
                }               
        }
}
/******************************************************************/
/*                     ds18b20延迟子函数(晶振12MHz)                              */
/******************************************************************/
void delay_18B20(unsigned int i)
{
        while(i--);
}
/******************************************************************/
/*                                     ds18b20初始化函数                                     */
/******************************************************************/
void Init_DS18B20(void)
{
         unsigned char x=0;
         DQ = 1;          //DQ复位
         delay_18B20(8);  //稍做延时
         DQ = 0;          //单片机将DQ拉低
         delay_18B20(80); //精确延时 大于 480us
         DQ = 1;          //拉高总线
         delay_18B20(14);
         x  = DQ;          //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
         delay_18B20(20);
         DQ = 1;
}
/******************************************************************/
/*                                     ds18b20读一个字节                                     */
/******************************************************************/
unsigned char ReadOneChar(void)
{
        uchar i=0;
        uchar dat = 0;
        for (i=8;i>0;i--)
         {
                  DQ = 0; // 给脉冲信号
                  dat>>=1;
                  DQ = 1; // 给脉冲信号
                  if(DQ)
                  dat|=0x80;
                  delay_18B20(4);
         }
        return(dat);
}
/******************************************************************/
/*                                     ds18b20写一个字节                                     */
/******************************************************************/
void WriteOneChar(uchar dat)
{
        unsigned char i=0;
        for (i=8; i>0; i--)
        {
                  DQ = 0;
                DQ = dat&0x01;
            delay_18B20(5);
                DQ = 1;
            dat>>=1;
}
}
/******************************************************************/
/*                                     读取ds18b20当前温度                                     */
/******************************************************************/
void ReadTemp(void)
{
        unsigned char a=0;
        unsigned char b=0;
        unsigned char t=0;
        Init_DS18B20();
        WriteOneChar(0xCC);            // 跳过读序号列号的操作
        WriteOneChar(0x44);         // 启动温度转换
        delay_18B20(100);       // this message is wery important
        Init_DS18B20();
        WriteOneChar(0xCC);         //跳过读序号列号的操作
        WriteOneChar(0xBE);         //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
        delay_18B20(100);
        a=ReadOneChar();            //读取温度值低位
        b=ReadOneChar();                   //读取温度值高位
        temp_value=b<<4;
        temp_value+=(a&0xf0)>>4;               
}
/******************************************************************/
/*                                     温度数据转换                                                     */
/******************************************************************/
void temp_to_str()   //温度数据转换成液晶字符显示
{
  TempBuffer[0]=temp_value/10+'0';  //十位
  TempBuffer[1]=temp_value%10+'0';  //个位
  //TempBuffer[2]=0xdf;   //温度符号
  //TempBuffer[3]='C';
  //TempBuffer[4]='\0';
}
/******************************************************************/
/*                                             LCD1602判忙函数                                         */
/******************************************************************/
void lcd_mang()
{
           lcdrs=0;
           lcdrw=1;
           lcden=1;
           _nop_();
        _nop_();
        _nop_();
        _nop_();
           while(P0&0x80);
           lcden=0;
}                                                                          
/******************************************************************/
/*                             LCD1602写指令(i=0)、数据(i=1)函数                            */
/******************************************************************/
void write_lcd1602(uchar cmd,uchar i)
{                                                                                                                                          
    lcd_mang();
        lcdrs=i;
        lcdrw=0;
        lcden=0;
        _nop_();
        _nop_();       
        lcden=1;
        _nop_();
        _nop_();
        P0=cmd;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        lcden=0;       
}
/******************************************************************/
/*                             LCD1602初始化函数                                             */
/******************************************************************/
void ini_lcd1602()
{
  uchar i;
  led1=1;
  Alarm_Flag=0;
  write_lcd1602(0x38,0);
  delay(1);  
  write_lcd1602(0x0c,0);
  delay(1);
  write_lcd1602(0x06,0);
  delay(1);
  write_lcd1602(0x01,0);
  delay(1);
  write_lcd1602(0x80+1,0);
  for(i=0;i<8;i++)
  {
            write_lcd1602(tab1,1);
  }
  write_lcd1602(0x80+0x40+2,0);
  for(i=0;i<6;i++)
  {
            write_lcd1602(tab2,1);
  }
  write_lcd1602(0x80+0x40+14,0);
  write_lcd1602(0xdf,1);
  write_lcd1602('C',1);
}
/******************************************************************/
/*     BCD转换成LCD1602能显示的16进制数,秒、分、时               */
/******************************************************************/
void write_sfm(uchar add,uchar dat)                                 
{
        uchar gw,sw;
        gw=dat%10;
        sw=dat/10;
        write_lcd1602(0x80+0x40+add,0);
        write_lcd1602(sw+'0',1);
        write_lcd1602(gw+'0',1);       
}
/******************************************************************/
/*     BCD转换成LCD1602能显示的16进制数,日、月、年               */
/******************************************************************/
void write_nyr(uchar add,uchar dat)                               
{
        uchar gw,sw;
        gw=dat%10;
        sw=dat/10;
        write_lcd1602(0x80+add,0);
        write_lcd1602(sw+'0',1);
        write_lcd1602(gw+'0',1);       
}
/******************************************************************/
/*                                             显示星期                                                     */
/******************************************************************/
void write_week(uchar xq)                                               
{
        uchar x;
        write_lcd1602(0x80+12,0);
        switch(xq)
        {
                case 1:
                for(x=0;x<3;x++)
                {
                        write_lcd1602(table1[x],1);
                }
                break;
                case 2:
                for(x=0;x<3;x++)
                {
                        write_lcd1602(table2[x],1);
                }
                break;
                case 3:
                for(x=0;x<3;x++)
                {
                        write_lcd1602(table3[x],1);
                }
                break;
                case 4:
                for(x=0;x<3;x++)
            {
                        write_lcd1602(table4[x],1);
                }
                break;
                case 5:
                for(x=0;x<3;x++)
                {
                        write_lcd1602(table5[x],1);
                }
                break;
                case 6:
                for(x=0;x<3;x++)
                {
                        write_lcd1602(table6[x],1);
                }
                break;
                case 7:
                for(x=0;x<3;x++)
                {
                        write_lcd1602(table7[x],1);
                }
                break;
        }
        write_lcd1602(0x80+12,0);       
}
/******************************************************************/
/*                                             显示函数                                                     */
/******************************************************************/
void display()
{
        uchar i;
        Read_RTC();
        write_sfm(8,miao);
        write_sfm(5,fen);
        write_sfm(2,shi);
        write_nyr(3,nian);
        write_nyr(6,yue);       
        write_nyr(9,ri);
        write_week(week);
        ReadTemp();
        temp_to_str();
        write_lcd1602(0x80+0x40+12,0);
        for(i=0;i<2;i++)
        {
                write_lcd1602(TempBuffer,1);
        }
}
/******************************************************************/
/*                   DS1302写一个字节                             */
/******************************************************************/
void Write_Ds1302_Byte(uchar temp)
{
         uchar i;
         for (i=0;i<8;i++)             //循环8次 写入数据
          {
           SCK=0;
             SDA=temp&0x01;     //每次传输低字节
             temp>>=1;                  //右移一位
             SCK=1;
           }  
}   
/******************************************************************/
/*                  写入DS1302                                    */
/******************************************************************/
void Write_Ds1302( uchar address,uchar dat )     
{
        RST=0;
        _nop_();
        SCK=0;
        _nop_();
        RST=1;       
           _nop_();                    //启动
        Write_Ds1302_Byte(address);        //发送地址
        Write_Ds1302_Byte(dat);                //发送数据
        RST=0;                                              //恢复
}
/******************************************************************/
/*                   读出DS1302数据                               */
/******************************************************************/
uchar Read_Ds1302 ( uchar address )
{
        uchar i,temp=0x00;
        RST=0;
        _nop_();
        _nop_();
        SCK=0;
        _nop_();
        _nop_();
        RST=1;
        _nop_();
        _nop_();
        Write_Ds1302_Byte(address);
        for (i=0;i<8;i++)                 //循环8次 读取数据
        {               
                if(SDA)
                temp|=0x80;                        //每次传输低字节
                SCK=0;
                temp>>=1;                        //右移一位
           _nop_();
           _nop_();
           _nop_();
                SCK=1;
        }
        RST=0;
        _nop_();                          //以下为DS1302复位的稳定时间
        _nop_();
        RST=0;
        SCK=0;
        _nop_();
        _nop_();
        _nop_();
        _nop_();
        SCK=1;
        _nop_();
        _nop_();
        SDA=0;
        _nop_();
        _nop_();
        SDA=1;
        _nop_();
        _nop_();
        return (temp);                                //返回
}
/******************************************************************/
/*                   读时钟数据                                   */
/******************************************************************/
void Read_RTC(void)                //读取 日历
{
         uchar i,*p;
         p=read_rtc_address;             //地址传递
         for(i=0;i<7;i++)                    //分7次读取 秒分时日月周年
         {
                  l_tmpdate=Read_Ds1302(*p);
                  p++;
                                                                                                       
                  miao=((l_tmpdate[0]&0x70)>>4)*10 + (l_tmpdate[0]&0x0f);
                  fen =((l_tmpdate[1]&0x70)>>4)*10 + (l_tmpdate[1]&0x0f);
                  shi =((l_tmpdate[2]&0x70)>>4)*10 + (l_tmpdate[2]&0x0f);
                  ri  =((l_tmpdate[3]&0x70)>>4)*10 + (l_tmpdate[3]&0x0f);
                  yue =((l_tmpdate[4]&0x70)>>4)*10 + (l_tmpdate[4]&0x0f);
                  week=((l_tmpdate[5]&0x70)>>4)*10 + (l_tmpdate[5]&0x0f);
                   nian=((l_tmpdate[6]&0x70)>>4)*10 + (l_tmpdate[6]&0x0f);                    
         }
}
/******************************************************************/
/*                  设定时钟数据                                  */
/******************************************************************/
void Set_RTC(void)                    //设定 日历
{
        uchar i,*p;
        /*for(i=0;i<7;i++)
         {       //BCD处理
                tmp=l_tmpdate/10;
                l_tmpdate=l_tmpdate%10;
                l_tmpdate=l_tmpdate+tmp*16;
        }*/
         
        Write_Ds1302(0x8E,0X00);         //允许写,禁止写保护       
        p=write_rtc_address;             //传地址       
        for(i=0;i<7;i++)                     //7次写入 秒分时日月周年
        {
                  Write_Ds1302(*p,l_tmpdate);
                  p++;  
         }
         Write_Ds1302(0x8E,0x80);           //打开写保护
}
/******************************************************************/
/*                                             键盘扫描函数                                             */
/******************************************************************/
void keyscan()
{
        uchar i;
        if(Display_Flag==0)
        {
                if(key1==0)                                                         //调时功能键
                {
                        delay(9);
                        if(key1==0)
                        {
                                di();
                                while(!key1);                                                                                         //松手检测
                                ++n;
                                ReadRTC_Flag=1;                                                                                         //停止走时
                                switch(n)
                                {
                                        case 1: write_lcd1602(0x80+0x40+9,0);                                 //按一次功能键秒闪烁
                                                        write_lcd1602(0x0f,0);
                                                        Write_Ds1302(0x8e,0x00);                                         //允许写,禁止写保护
                                                        Write_Ds1302(0x80,((miao/10)*16+miao%10));                                 //写入DS1302秒位
                                                        Write_Ds1302(0x8e,0x80);                                         //打开写保护
                                                        break;
                                        case 2: write_lcd1602(0x80+0x40+6,0);                                 //按两次功能键分闪烁                               
                                                        break;
                                        case 3: write_lcd1602(0x80+0x40+3,0);                                 //按三次功能键时闪烁                                                               
                                                        break;
                                        case 4: write_lcd1602(0x80+10,0);                                          //按四次功能键日闪烁                                               
                                                        break;
                                        case 5: write_lcd1602(0x80+7,0);                                          //按五次功能键月闪烁                                               
                                                        break;
                                        case 6:write_lcd1602(0x80+4,0);                                          //按六次功能键年闪烁
                                                        break;
                                        case 7: write_lcd1602(0x80+12,0);                                         //按七次功能键周闪烁       
                                                        break;
                                        case 8: n=0;                                                                        //按八次功能键开始走时,停止闪烁
                                                        ReadRTC_Flag=0;                                               
                                                        write_lcd1602(0x0c,0);
                                                        Write_Ds1302(0x8e,0x00);
                                                        Write_Ds1302(0x80,((miao/10)*16+miao%10));
                                                        Write_Ds1302(0x8e,0x80);
                                                        C=0;
                                                        break;
                                }
                        }               
                }
         }
        if(key4==0)                                                                 //闹铃功能键
        {
                delay(9);
                if(key4==0)
                {
                        di();
                        while(!key4);
                        m++;
                        Display_Flag=1;                                                 //屏蔽调时功能键,进入调闹铃功能
                        Alarm_Flag=0;                                                 //初始化闹铃标志位,闹铃不响
                        flag=1;                                                                 //开启闹钟检测
                        write_lcd1602(0x80+0x40,0);                         //在时间前面显示闹钟开启标志‘A’
                        write_lcd1602('A',1);
                        switch(m)
                        {
                                case 1:        n=0;
                                                ReadRTC_Flag=0;                                        //开显示       
                                                write_lcd1602(0x0c,0);                        //停止闪烁
                                                Write_Ds1302(0x8e,0x00);
                                                Write_Ds1302(0x80,((miao/10)*16+miao%10));
                                                Write_Ds1302(0x8e,0x80);

                                                write_lcd1602(0x80+1,0);                  //首行写入Set Alarm!
                                                for(i=0;i<14;i++)
                                                {
                                                        write_lcd1602(tab3,1);
                                                }
                                                write_lcd1602(0x80+0x40+2,0);          //第二行写入设定的时间
                                                for(i=0;i<6;i++)
                                                {
                                                        write_lcd1602(tab2,1);       
                                                }
                                                write_lcd1602(0x80+0x40+8,0);
                                                write_lcd1602(tab4[0]/10+'0',1);
                                                   write_lcd1602(tab4[0]%10+'0',1);
                                                write_lcd1602(0x80+0x40+5,0);
                                                write_lcd1602(tab4[1]/10+'0',1);
                                                write_lcd1602(tab4[1]%10+'0',1);
                                                write_lcd1602(0x80+0x40+2,0);
                                                write_lcd1602(tab4[2]/10+'0',1);
                                                write_lcd1602(tab4[2]%10+'0',1);
                                                break;
                                case 2: write_lcd1602(0x80+0x40+9,0);                   //开始设定闹铃,秒位闪烁可调
                                                write_lcd1602(0x0f,0);
                                                break;
                                case 3: write_lcd1602(0x80+0x40+6,0);                   //分位闪烁可调
                                                break;
                                case 4:        write_lcd1602(0x80+0x40+3,0);                   //时位闪烁可调
                                                break;
                                case 5: Display_Flag=0;                                                                   //关闭对调时功能间的屏蔽
                                                m=0;                                                                   //关闭更更改闹铃时间
                                                C=0;                                         //屏蔽掉在正常显示时间时key5复位键对显示的影响
                                                write_lcd1602(0x0c,0);
                                                write_lcd1602(0x80+1,0);  //清掉Set Alarm                          
                                                for(i=0;i<11;i++)
                                                {
                                                        write_lcd1602(tab1,1);
                                                }
                                                display();                                                           //返回时间显示
                        }
                }
        }
        if(n!=0||m!=0)                                                                                                                //功能加键
        {
                if(key2==0)
                {
                        delay(9);
                        if(key2==0)
                        {                                       
                                di();
                                while(!key2);
                                if(Display_Flag==0)
                                {
                                        switch(n)
                    &nb

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top