久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 2592|回復: 5
打印 上一主題 下一主題
收起左側

關于DS1302時鐘問題?

[復制鏈接]
跳轉到指定樓層
樓主
ID:687423 發表于 2020-2-15 15:15 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
這個程序是我在網上找到,自己又改了一下只是有幾個地方不是很明白,請求大家支援。
DS1302芯片是自動將我定義的time數組里的數據轉化成BCD碼嗎?
這兩天看了很多進制,有點蒙了,time數組里定義的數據的類型是16進制的嗎?
關于key2的程序中,為什么需要手動轉化BCD碼嗎,不應該是1302自動轉化嗎?
關于lcd1602中周的顯示,為什么星期是&0x07,這個進制轉換的怎么轉換啊?
星期的顯示地址我設置為0x80+0x40+0x0f,開始好使,按下k3后1602的第一行最后也有一個4(假設星期為4)。地址為0x80+0x0f的話4就出現在第1行第一個位置了,按下k3后第一行最后一個位置才出現4。這是為什么啊,是程序問題嗎?

#include <reg52.h>
#include <intrins.h>
#define lcd1602data P0
typedef unsigned char u8;
typedef unsigned int u16;
sbit E=P2^7;  
sbit RW=P2^5;   
sbit RS=P2^6;   
sbit  key1=P3^1;
sbit  key2=P3^0;
sbit  key3=P3^2;

sbit SCLK=P3^6;
sbit IO=P3^4;
sbit RST=P3^5;  
u16 read[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};  
u16 write[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};  
u8 time[]={0x15,0x27,0x09,0x15,0x02,0x06,0x20};  
u16 setmark,setplace;     
void delay_ms(u16 n);
void initConfiguration();
void lcdDisplay();
void lcdwrite_com(u8 datas);
void lcdwrite_datas(u8 datas);
void lcdinit();
void writebyte(u8 address,u8 datas);
u8 readbyte(u8 address);
void ds1302init();
void read_time();
void main()
{
  u16 i;
  initConfiguration();
  lcdinit();
  ds1302init();
  while(1)
  {
   if(setmark==0)   
   {
    read_time();
   }
   else      
   {
     if(key1==0)
    {
     delay_ms(1);
    if(key1==0)
    {
       setplace++;   
      setplace%=7;
    }
    while(i<50&&key1==0)   
     {
     i++;
     delay_ms(10);
     }
     i=0;
    }

    if(key2==0)
    {
      delay_ms(1);
     if(key2==0)      
     {
     time[setplace]++;
     if((time[setplace]&0x0f)>9)   
     {
      time[setplace]=time[setplace]+6;
     }
     if((time[setplace]>=0x60)&&(setplace<2))  
     {
      time[setplace]=0;
     }
     if((time[setplace]>=0x24)&&(setplace==2))
     {
      time[setplace]=0;
     }
     if((time[setplace]>=0x32)&&(setplace==3))
     {
      time[setplace]=0;
     }
     if((time[setplace]>=0x13)&&(setplace==4))  
      time[setplace]=0;
     }
     if((time[setplace]>=0x7)&&(setplace==5))
     {
      time[setplace]=1;
     }
                  
     }
     while((i<50)&&(0==key2))
     {
      i++;
     delay_ms(10);
     }
     i=0;
    }
   }
   lcdDisplay();
  }
}
void delay_ms(u16 n)   
{
u16 a,b;
for(;n>0;n--)
{
  for(a=199;a>0;a--)
  {
   for(b=1;b>0;b--)
   {
     ;
   }
  }
}
}

void initConfiguration()
{
EA=1;
IT0=1;
EX0=1;
}
void init0() interrupt 0
{
  delay_ms(10);
  if(key3==0)
  {
   setmark=~setmark;
  setplace=0;
  ds1302init();
  }
}
void lcdDisplay()   
{

lcdwrite_com(0x80+0x01);   
lcdwrite_datas('d');
lcdwrite_datas('a');
lcdwrite_datas('t');
lcdwrite_datas('e');
lcdwrite_datas(':');
lcdwrite_datas('2');
lcdwrite_datas('0');
lcdwrite_datas('0'+time[6]/16);  
lcdwrite_datas('0'+(time[6]&0x0f));
lcdwrite_datas('-');
lcdwrite_datas('0'+time[4]/16);
lcdwrite_datas('0'+(time[4]&0x0f));
lcdwrite_datas('-');  
lcdwrite_datas('0'+time[3]/16);
lcdwrite_datas('0'+(time[3]&0x0f));
lcdwrite_com(0x80+0x0f);
lcdwrite_datas('0'+(time[5]&0x07));
lcdwrite_com(0x80+0x40);        
lcdwrite_datas('t');
lcdwrite_datas('i');
lcdwrite_datas('m');
lcdwrite_datas('e');
lcdwrite_datas(':');
lcdwrite_datas('0'+time[2]/16);
lcdwrite_datas('0'+(time[2]&0x0f));
lcdwrite_datas('-');
lcdwrite_datas('0'+time[1]/16);
lcdwrite_datas('0'+(time[1]&0x0f));
lcdwrite_datas('-');
lcdwrite_datas('0'+time[0]/16);   
lcdwrite_datas('0'+(time[0]&0x0f));
}
void lcdwrite_com(u8 datas)   
{
E=0;
RW=0;
RS=0;
lcd1602data=datas;
delay_ms(1);
E=1;
delay_ms(1);
E=0;

}
void lcdwrite_datas(u8 datas)  
{
E=0;
RW=0;
RS=1;
lcd1602data=datas;
delay_ms(1);     
E=1;
delay_ms(1);
E=0;

}
void lcdinit()     
{
lcdwrite_com(0x38);  
lcdwrite_com(0x0c);   
lcdwrite_com(0x06);   
lcdwrite_com(0x01);   
lcdwrite_com(0x80);  
}


void writebyte(u8 address,u8 datas)   
{
u8 i;
RST=0;
_nop_();
SCLK=0;
_nop_();
RST=1;
_nop_();
for(i=0;i<8;i++)
{
  IO=address&0x01;
  address>>=1;
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
for(i=0;i<8;i++)
{
  IO=datas&0x01;
  datas>>=1;
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
RST=0;
}
u8 readbyte(u8 address)   
{
u8 i,datas,dat;
RST=0;
_nop_();
SCLK=0;
_nop_();
RST=1;
_nop_();
for(i=0;i<8;i++)
{
  IO=address&0x01;
  address>>=1;
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
_nop_();
for(i=0;i<8;i++)
{
  dat=IO;
  datas=(datas>>1)|(dat<<7);
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
RST=0;
_nop_();
SCLK=1;
_nop_();
IO=0;
_nop_();
IO=1;
_nop_();
return datas;
}
void ds1302init()     
{
u8 i;
writebyte(0x8e,0x00);   
for(i=0;i<7;i++)
{
  writebyte(write[i],time[i]);
}
writebyte(0x8e,0x80);   
}
void read_time()     
{
u8 i;
for(i=0;i<7;i++)
{
  time[i]=readbyte(read[i]);
}
}
分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏1 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:235200 發表于 2020-2-15 16:11 | 只看該作者
你的問題加了注釋如下:
#include <reg52.h>
#include <intrins.h>
#define lcd1602data P0
typedef unsigned char u8;
typedef unsigned int u16;
sbit E=P2^7;  
sbit RW=P2^5;   
sbit RS=P2^6;   
sbit  key1=P3^1;
sbit  key2=P3^0;
sbit  key3=P3^2;

sbit SCLK=P3^6;
sbit IO=P3^4;
sbit RST=P3^5;  
u16 read[]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};      //這是讀DS1302時鐘數據的地址"秒 分 小時 日 月 星期 年"
u16 write[]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};     //這是寫DS1302時鐘數據的地址"秒 分 小時 日 月 星期 年"  
u8 time[]={0x15,0x27,0x09,0x15,0x02,0x06,0x20};       //這是設置DS1302時鐘數據"秒 分 小時 日 月 星期 年"
//以上數據不需要轉換,可以認為是十六制數,可以認為BCD碼,16進制數只是BCD碼的一種表現形式,即BCD數據中不可能出現A-F數碼
u16 setmark,setplace;     
void delay_ms(u16 n);
void initConfiguration();
void lcdDisplay();
void lcdwrite_com(u8 datas);
void lcdwrite_datas(u8 datas);
void lcdinit();
void writebyte(u8 address,u8 datas);
u8 readbyte(u8 address);
void ds1302init();
void read_time();
void main()
{
  u16 i;
  initConfiguration();
  lcdinit();
  ds1302init();
  while(1)
  {
   if(setmark==0)   
   {
    read_time();
   }
   else      
   {
     if(key1==0)      //按鍵1操作
    {
     delay_ms(1);
    if(key1==0)
    {
       setplace++;   
      setplace%=7;
    }
    while(i<50&&key1==0)   
     {
     i++;
     delay_ms(10);
     }
     i=0;
    }

    if(key2==0)    //按鍵2操作
    {
      delay_ms(1);
     if(key2==0)      
     {
     time[setplace]++;             //按鍵設置的時鐘數據處理
     if((time[setplace]&0x0f)>9)   //每次加1后出現A-F數據不符合BCD,所以要保證數據只有0-9
     {
      time[setplace]=time[setplace]+6;
     }
     if((time[setplace]>=0x60)&&(setplace<2))    //保證分鐘在十進制00-59間變化
     {
      time[setplace]=0;
     }
     if((time[setplace]>=0x24)&&(setplace==2))   //保證小時在十進制00-23之間變化
     {
      time[setplace]=0;
     }
     if((time[setplace]>=0x32)&&(setplace==3))   //保證日期在十進制1-31之間變化
     {
      time[setplace]=0;
     }
     if((time[setplace]>=0x13)&&(setplace==4))   //保證月份在十進制1-12之間變化
      time[setplace]=0;
     }
     if((time[setplace]>=0x7)&&(setplace==5))    //保證星期在十進制0-6之間變化 0表示星期天 1-6表示星期一至六
     {
      time[setplace]=1;
     }
                  
     }
     while((i<50)&&(0==key2))
     {
      i++;
     delay_ms(10);
     }
     i=0;
    }
   }
   lcdDisplay();
  }
}
void delay_ms(u16 n)   
{
u16 a,b;
for(;n>0;n--)
{
  for(a=199;a>0;a--)
  {
   for(b=1;b>0;b--)
   {
     ;
   }
  }
}
}

void initConfiguration()
{
EA=1;
IT0=1;
EX0=1;
}
void init0() interrupt 0
{
  delay_ms(10);
  if(key3==0)          //按鍵3在中斷里判斷是不行的  這個中斷程序是有問題的
  {
   setmark=~setmark;
  setplace=0;
  ds1302init();
  }
}
void lcdDisplay()        //LCD顯示程序
{

lcdwrite_com(0x80+0x01);   
lcdwrite_datas('d');
lcdwrite_datas('a');
lcdwrite_datas('t');
lcdwrite_datas('e');
lcdwrite_datas(':');
lcdwrite_datas('2');
lcdwrite_datas('0');
lcdwrite_datas('0'+time[6]/16);      //顯示年份十位
lcdwrite_datas('0'+(time[6]&0x0f));  //顯示年份個位
lcdwrite_datas('-');
lcdwrite_datas('0'+time[4]/16);      //顯示月份十位
lcdwrite_datas('0'+(time[4]&0x0f));  //顯示月份個位
lcdwrite_datas('-');  
lcdwrite_datas('0'+time[3]/16);      //顯示日期十位
lcdwrite_datas('0'+(time[3]&0x0f));  //顯示日期個位
lcdwrite_com(0x80+0x0f);
lcdwrite_datas('0'+(time[5]&0x07));  //顯示星期 讀出的星期數據只有最低3位是表示星期,其它位可能表示12時制或24時制
//&07的目的去掉不需的內容
lcdwrite_com(0x80+0x40);        
lcdwrite_datas('t');
lcdwrite_datas('i');
lcdwrite_datas('m');
lcdwrite_datas('e');
lcdwrite_datas(':');
lcdwrite_datas('0'+time[2]/16);
lcdwrite_datas('0'+(time[2]&0x0f));
lcdwrite_datas('-');
lcdwrite_datas('0'+time[1]/16);
lcdwrite_datas('0'+(time[1]&0x0f));
lcdwrite_datas('-');
lcdwrite_datas('0'+time[0]/16);   
lcdwrite_datas('0'+(time[0]&0x0f));
}
void lcdwrite_com(u8 datas)   
{
E=0;
RW=0;
RS=0;
lcd1602data=datas;
delay_ms(1);
E=1;
delay_ms(1);
E=0;

}
void lcdwrite_datas(u8 datas)  
{
E=0;
RW=0;
RS=1;
lcd1602data=datas;
delay_ms(1);     
E=1;
delay_ms(1);
E=0;

}
void lcdinit()     
{
lcdwrite_com(0x38);  
lcdwrite_com(0x0c);   
lcdwrite_com(0x06);   
lcdwrite_com(0x01);   
lcdwrite_com(0x80);  
}


void writebyte(u8 address,u8 datas)   
{
u8 i;
RST=0;
_nop_();
SCLK=0;
_nop_();
RST=1;
_nop_();
for(i=0;i<8;i++)
{
  IO=address&0x01;
  address>>=1;
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
for(i=0;i<8;i++)
{
  IO=datas&0x01;
  datas>>=1;
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
RST=0;
}
u8 readbyte(u8 address)   
{
u8 i,datas,dat;
RST=0;
_nop_();
SCLK=0;
_nop_();
RST=1;
_nop_();
for(i=0;i<8;i++)
{
  IO=address&0x01;
  address>>=1;
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
_nop_();
for(i=0;i<8;i++)
{
  dat=IO;
  datas=(datas>>1)|(dat<<7);
  SCLK=1;
  _nop_();
  SCLK=0;
  _nop_();
}
RST=0;
_nop_();
SCLK=1;
_nop_();
IO=0;
_nop_();
IO=1;
_nop_();
return datas;
}
void ds1302init()     
{
u8 i;
writebyte(0x8e,0x00);   
for(i=0;i<7;i++)
{
  writebyte(write[i],time[i]);
}
writebyte(0x8e,0x80);   
}
void read_time()     
{
u8 i;
for(i=0;i<7;i++)
{
  time[i]=readbyte(read[i]);
}
}
回復

使用道具 舉報

板凳
ID:687423 發表于 2020-2-15 18:37 | 只看該作者
csmyldl 發表于 2020-2-15 16:11
你的問題加了注釋如下:
#include
#include

感謝啊,講的很詳細。我想了解一下為什么不能再中斷里判斷按鍵
回復

使用道具 舉報

地板
ID:235200 發表于 2020-2-15 19:47 | 只看該作者
。。jj 發表于 2020-2-15 18:37
感謝啊,講的很詳細。我想了解一下為什么不能再中斷里判斷按鍵

按鍵消抖方式改一下,不要在中斷程序里加入延時,進入中斷后如果要判斷,再好把中斷屏敞掉(EX0=0),處理完后再開啟(EX0=1)
回復

使用道具 舉報

5#
ID:687423 發表于 2020-2-16 19:13 | 只看該作者
csmyldl 發表于 2020-2-15 19:47
按鍵消抖方式改一下,不要在中斷程序里加入延時,進入中斷后如果要判斷,再好把中斷屏敞掉(EX0=0),處理完后 ...

對于按鍵消抖來說,不是應該按鍵按下去之后才能消抖嗎,可是按鍵一按下去不就中斷了嗎,按照你說的是按鍵按下去,進入中斷,在中斷的程序時先關閉中斷在延時在看起中斷嗎,你看我按照你的話這么寫程序對嗎。這樣寫和中斷寫延時里有什么區別,還有就是如果在中斷的程序關閉中斷的話中斷內部的程序還會進行嗎?
//k3按鍵按下后進入中斷
void init0() interrupt 1
{
      EX0=0;
      delay(100);
      if(k3==0)
      {
                EX1=0;
               其他程序
      }
}
回復

使用道具 舉報

6#
ID:235200 發表于 2020-2-17 20:18 | 只看該作者
從你的程序看,K3鍵主要是進入設置狀態,K1是選擇調整的內容,K2是進行選擇的內容進行加1運算,如果是這樣,可以設置按下K3鍵標記一下
void init0() interrupt 1
{
      EX0=0;               //屏幕中斷
            
    FLAG=~FLAG;       //用一個標記來表示是設置狀態還是非設置狀態
    TH0=1;                //開啟定時計數器,時間到才允許再次開啟外部中斷
}
在主程序中加上判斷
  if (FLAG==1)
   {
       //判斷K1  K2并執行相應的動作
}
何時開啟外部中斷呢?可以用一個定時計數器
Time0() interrupt 1
{
    EX1=1;         //開啟外部中斷
    TH0=0;        //12M晶振約65ms
    TL0=0;
    ET0=0;        //關閉  下次按鍵時才開啟
}
這樣就達到所需功能,K3鍵按一次進入設置 再按一次退出設置
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 亚洲精品乱码久久久久久9色 | 天天视频一区二区三区 | 91超碰在线观看 | 欧美三级不卡 | 在线免费小视频 | 久久精品亚洲国产奇米99 | 国产视频福利 | 欧美一级片免费看 | 国产一区二区视频在线 | 亚洲乱码一区二区 | 嫩呦国产一区二区三区av | 成人欧美一区二区三区1314 | 国产精品视频免费播放 | 欧美日韩国产中文 | 欧美日韩一区二区三区四区 | 亚洲视频国产 | 欧美人妖网站 | 亚洲免费在线视频 | 九九在线视频 | 欧美自拍第一页 | 欧美国产日韩在线观看 | 午夜免费电影院 | 日韩av一区二区在线观看 | 国产精品久久久久久婷婷天堂 | 久久福利网站 | 午夜三级在线观看 | 亚洲午夜视频在线观看 | 国产精品久久久久久久模特 | 欧美在线视频一区二区 | 午夜影院操 | 日韩中文字幕一区二区 | 欧美色性 | 黄色片av | 99久久婷婷国产综合精品电影 | 国精久久| 国产乱码精品一区二区三区中文 | 狠狠爱免费视频 | 一区视频在线免费观看 | 国产亚洲一区二区三区在线 | 国产欧美在线视频 | 久久久久国产精品一区二区 |