<li id="8g3ty"><tbody id="8g3ty"><th id="8g3ty"></th></tbody></li>
    <label id="8g3ty"><samp id="8g3ty"></samp></label>
  • <span id="8g3ty"></span>

    1. <center id="8g3ty"><optgroup id="8g3ty"></optgroup></center>
    2. <bdo id="8g3ty"><meter id="8g3ty"><bdo id="8g3ty"></bdo></meter></bdo><center id="8g3ty"><optgroup id="8g3ty"></optgroup></center>
      <label id="8g3ty"><samp id="8g3ty"></samp></label>

    3. 電子開發(fā)網(wǎng)

      電子開發(fā)網(wǎng)電子設(shè)計(jì) | 電子開發(fā)網(wǎng)Rss 2.0 會(huì)員中心 會(huì)員注冊(cè)
      搜索: 您現(xiàn)在的位置: 電子開發(fā)網(wǎng) >> 電子開發(fā) >> 單片機(jī) >> 正文

      單片機(jī)電子時(shí)鐘程序設(shè)計(jì)

      作者:佚名    文章來源:本站原創(chuàng)    點(diǎn)擊數(shù):    更新時(shí)間:2018-03-10
      共用體除非必要,否則我們不推薦使用,枚舉的用法比較簡(jiǎn)單,在本書 19 章的項(xiàng)目實(shí)踐中有很好的示例,這節(jié)課我們先來練習(xí)一下結(jié)構(gòu)體的使用。下邊這個(gè)程序的功能是一個(gè)帶日期的電子鐘,相當(dāng)于一個(gè)簡(jiǎn)易萬年歷了,并且加入了按鍵調(diào)時(shí)功能。學(xué)有余力的同學(xué)看到這里,不妨先不看我們提供的代碼,自己寫寫試試。如果能夠獨(dú)立寫一個(gè)按鍵可調(diào)的萬年歷程序,單片機(jī)可以說基本入門了。如果自己還不能夠獨(dú)立完成這個(gè)程序,那么還是老規(guī)矩,先抄并且理解,而后自己獨(dú)立默寫出來,并且要邊默寫邊理解。

      本例直接忽略了星期這項(xiàng)內(nèi)容,通過上、下、左、右、回車、ESC 這 6 個(gè)按鍵可以調(diào)整時(shí)間。這也是一個(gè)具有綜合練習(xí)性質(zhì)的實(shí)例,雖然在功能實(shí)現(xiàn)上沒有多少難度,但要進(jìn)行的操作卻比較多而且煩瑣,同學(xué)們可以從中體會(huì)到把繁雜的功能實(shí)現(xiàn)分解為一步步函數(shù)操作的必要性以及方便靈活性。簡(jiǎn)單說一下這個(gè)程序的幾個(gè)要點(diǎn),方便大家閱讀理解程序。
      1. 把 DS1302 的底層操作封裝為一個(gè) DS1302.c 文件,對(duì)上層應(yīng)用提供基本的實(shí)時(shí)時(shí)間的操作接口,這個(gè)文件也是我們的又一個(gè)功能模塊了,我們的積累也越來越多了。
      2. 定義一個(gè)結(jié)構(gòu)體類型 sTime 用來封裝日期時(shí)間的各個(gè)元素,又用該結(jié)構(gòu)體定義了一個(gè)時(shí)間緩沖區(qū)變量 bufTime 來暫存從 DS1302 讀出的時(shí)間和設(shè)置時(shí)間時(shí)的設(shè)定值。需要注意的是在其它文件中要使用這個(gè)結(jié)構(gòu)體變量時(shí),必須首先再聲明一次 sTime 類型;
      3. 定義一個(gè)變量 setIndex 來控制當(dāng)前是否處于設(shè)置時(shí)間的狀態(tài),以及設(shè)置時(shí)間的哪一位,該值為 0 就表示正常運(yùn)行,1~12 分別代表可以修改日期時(shí)間的 12 個(gè)位;
      4. 由于這節(jié)課的程序功能要進(jìn)行時(shí)間調(diào)整,用到了 1602 液晶的光標(biāo)功能,添加了設(shè)置光標(biāo)的函數(shù),我們要改變哪一位的數(shù)字,就在 1602 對(duì)應(yīng)位置上進(jìn)行光標(biāo)閃爍,所以 Lcd1602.c在之前文件的基礎(chǔ)上添加了兩個(gè)控制光標(biāo)的函數(shù);
      5. 時(shí)間的顯示、增減、設(shè)置移位等上層功能函數(shù)都放在 main.c 中來實(shí)現(xiàn),當(dāng)按鍵需要這些函數(shù)時(shí)則在按鍵文件中做外部聲明,這樣做是為了避免一組功能函數(shù)分散在不同的文件內(nèi)而使程序顯得凌亂。
       
      /***************************DS1302.c 文件程序源代碼*****************************/ 
      #include <reg52.h> 
      sbit DS1302_CE = P1^7; 
      sbit DS1302_CK = P3^5; 
      sbit DS1302_IO = P3^4; 
      struct sTime { //日期時(shí)間結(jié)構(gòu)體定義 
      unsigned int year; //年 
      unsigned char mon; //月 
      unsigned char day; //日 
      unsigned char hour; //時(shí) 
      unsigned char min; //分 
      unsigned char sec; //秒 
      unsigned char week; //星期 
      }; 
      /* 發(fā)送一個(gè)字節(jié)到 DS1302 通信總線上 */ 
      void DS1302ByteWrite(unsigned char dat){ 
      unsigned char mask; 
      for (mask=0x01; mask!=0; mask<<=1){ //低位在前,逐位移出 
      if ((mask&dat) != 0){ //首先輸出該位數(shù)據(jù) 
      DS1302_IO = 1; 
      }else{ 
      DS1302_IO = 0; 
      } 
      DS1302_CK = 1; //然后拉高時(shí)鐘 
      DS1302_CK = 0; //再拉低時(shí)鐘,完成一個(gè)位的操作 
      } 
      DS1302_IO = 1; //最后確保釋放 IO 引腳 
      } 
      /* 由 DS1302 通信總線上讀取一個(gè)字節(jié) */ 
      unsigned char DS1302ByteRead(){ 
      unsigned char mask; 
      unsigned char dat = 0; 
      for (mask=0x01; mask!=0; mask<<=1){ //低位在前,逐位讀取 
      if (DS1302_IO != 0){ //首先讀取此時(shí)的 IO 引腳,并設(shè)置 dat 中的對(duì)應(yīng)位 
      dat |= mask; 
      } 
      DS1302_CK = 1; //然后拉高時(shí)鐘 
      DS1302_CK = 0; //再拉低時(shí)鐘,完成一個(gè)位的操作 
      } 
      return dat; //最后返回讀到的字節(jié)數(shù)據(jù) 
      } 
      /* 用單次寫操作向某一寄存器寫入一個(gè)字節(jié),reg-寄存器地址,dat-待寫入字節(jié) */ 
      void DS1302SingleWrite(unsigned char reg, unsigned char dat){ 
      DS1302_CE = 1; //使能片選信號(hào) 
      DS1302ByteWrite((reg<<1)|0x80); //發(fā)送寫寄存器指令 
      DS1302ByteWrite(dat); //寫入字節(jié)數(shù)據(jù) 
      DS1302_CE = 0; //除能片選信號(hào) 
      } 
      /* 用單次讀操作從某一寄存器讀取一個(gè)字節(jié),reg-寄存器地址,返回值-讀到的字節(jié) */ 
      unsigned char DS1302SingleRead(unsigned char reg){ 
      unsigned char dat; 
      DS1302_CE = 1; //使能片選信號(hào) 
      DS1302ByteWrite((reg<<1)|0x81); //發(fā)送讀寄存器指令 
      dat = DS1302ByteRead(); //讀取字節(jié)數(shù)據(jù) 
      DS1302_CE = 0; //除能片選信號(hào) 
      return dat; 
      } 
      /* 用突發(fā)模式連續(xù)寫入 8 個(gè)寄存器數(shù)據(jù),dat-待寫入數(shù)據(jù)指針 */ 
      void DS1302BurstWrite(unsigned char *dat){ 
      unsigned char i; 
      DS1302_CE = 1; 
      DS1302ByteWrite(0xBE); //發(fā)送突發(fā)寫寄存器指令 
      for (i=0; i<8; i++){ //連續(xù)寫入 8 字節(jié)數(shù)據(jù) 
      DS1302ByteWrite(dat[i]); 
      } 
      DS1302_CE = 0; 
      } 
      /* 用突發(fā)模式連續(xù)讀取 8 個(gè)寄存器的數(shù)據(jù),dat-讀取數(shù)據(jù)的接收指針 */ 
      void DS1302BurstRead(unsigned char *dat){ 
      unsigned char i; 
      DS1302_CE = 1; 
      DS1302ByteWrite(0xBF); //發(fā)送突發(fā)讀寄存器指令 
      for (i=0; i<8; i++){ //連續(xù)讀取 8 個(gè)字節(jié) 
      dat[i] = DS1302ByteRead(); 
      } 
      DS1302_CE = 0; 
      } 
      /* 獲取實(shí)時(shí)時(shí)間,即讀取 DS1302 當(dāng)前時(shí)間并轉(zhuǎn)換為時(shí)間結(jié)構(gòu)體格式 */ 
      void GetRealTime(struct sTime *time){ 
      unsigned char buf[8]; 
      DS1302BurstRead(buf); 
      time->year = buf[6] + 0x2000; 
      time->mon = buf[4]; 
      time->day = buf[3]; 
      time->hour = buf[2]; 
      time->min = buf[1]; 
      time->sec = buf[0]; 
      time->week = buf[5]; 
      } 
      /* 設(shè)定實(shí)時(shí)時(shí)間,時(shí)間結(jié)構(gòu)體格式的設(shè)定時(shí)間轉(zhuǎn)換為數(shù)組并寫入 DS1302 */ 
      void SetRealTime(struct sTime *time){ 
      unsigned char buf[8]; 
      buf[7] = 0; 
      buf[6] = time->year; 
      buf[5] = time->week; 
      buf[4] = time->mon; 
      buf[3] = time->day; 
      buf[2] = time->hour; 
      buf[1] = time->min; 
      buf[0] = time->sec; 
      DS1302BurstWrite(buf); 
      } 
      /* DS1302 初始化,如發(fā)生掉電則重新設(shè)置初始時(shí)間 */ 
      void InitDS1302(){ 
      unsigned char dat; 
      struct sTime code InitTime[] = { //2013 年 10 月 8 日 12:30:00 星期二 
      0x2013,0x10,0x08, 0x12,0x30,0x00, 0x02 
      }; 
      DS1302_CE = 0; //初始化 DS1302 通信引腳 
      DS1302_CK = 0; 
      dat = DS1302SingleRead(0); //讀取秒寄存器 
      if ((dat & 0x80) != 0){ //由秒寄存器最高位 CH 的值判斷 DS1302 是否已停止 
      DS1302SingleWrite(7, 0x00); //撤銷寫保護(hù)以允許寫入數(shù)據(jù) 
      SetRealTime(&InitTime); //設(shè)置 DS1302 為默認(rèn)的初始時(shí)間 
      } 
      }
      DS1302.c 最終向外提供出與具體時(shí)鐘芯片寄存器位置無關(guān)的、由時(shí)間結(jié)構(gòu)類型 sTime 作為接口的實(shí)時(shí)時(shí)間的讀取和設(shè)置函數(shù),如此處理體現(xiàn)了我們前面提到過的層次化編程的思想。應(yīng)用層可以不關(guān)心底層實(shí)現(xiàn)細(xì)節(jié),底層實(shí)現(xiàn)的改變也不會(huì)對(duì)應(yīng)用層造成影響,比如說日后你可能需要換一款時(shí)鐘芯片,而它與 DS1302 的操作和時(shí)間寄存器順序是不同的,那么你需要做的也僅是針對(duì)這款新的時(shí)鐘芯片設(shè)計(jì)出底層操作函數(shù),最終提供出同樣的以 sTime 為接口的操作函數(shù)即可,應(yīng)用層無需做任何的改動(dòng)。
       
      /***************************Lcd1602.c 文件程序源代碼*****************************/ 
      #include <reg52.h> 
      #define LCD1602_DB P0 
      sbit LCD1602_RS = P1^0; 
      sbit LCD1602_RW = P1^1; 
      sbit LCD1602_E = P1^5; 
      /* 等待液晶準(zhǔn)備好 */ 
      void LcdWaitReady(){ 
      unsigned char sta; 
      LCD1602_DB = 0xFF; 
      LCD1602_RS = 0; 
      LCD1602_RW = 1; 
      do { 
      LCD1602_E = 1; 
      sta = LCD1602_DB; //讀取狀態(tài)字 
      LCD1602_E = 0; 
      } while (sta & 0x80); //bit7 等于 1 表示液晶正忙,重復(fù)檢測(cè)直到其等于 0 為止 
      } 
      /* 向 LCD1602 液晶寫入一字節(jié)命令,cmd-待寫入命令值 */ 
      void LcdWriteCmd(unsigned char cmd){ 
      LcdWaitReady(); 
      LCD1602_RS = 0; 
      LCD1602_RW = 0; 
      LCD1602_DB = cmd; 
      LCD1602_E = 1; 
      LCD1602_E = 0; 
      } 
      /* 向 LCD1602 液晶寫入一字節(jié)數(shù)據(jù),dat-待寫入數(shù)據(jù)值 */ 
      void LcdWriteDat(unsigned char dat){ 
      LcdWaitReady(); 
      LCD1602_RS = 1; 
      LCD1602_RW = 0; 
      LCD1602_DB = dat; 
      LCD1602_E = 1; 
      LCD1602_E = 0; 
      } 
      /* 設(shè)置顯示 RAM 起始地址,亦即光標(biāo)位置,(x,y)-對(duì)應(yīng)屏幕上的字符坐標(biāo) */ 
      void LcdSetCursor(unsigned char x, unsigned char y){ 
      unsigned char addr; 
      if (y == 0){ //由輸入的屏幕坐標(biāo)計(jì)算顯示 RAM 的地址 
      addr = 0x00 + x; //第一行字符地址從 0x00 起始 
      }else{ 
      addr = 0x40 + x; //第二行字符地址從 0x40 起始 
      } 
      LcdWriteCmd(addr | 0x80); //設(shè)置 RAM 地址 
      } 
      /* 在液晶上顯示字符串,(x,y)-對(duì)應(yīng)屏幕上的起始坐標(biāo),str-字符串指針 */ 
      void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str){ 
      LcdSetCursor(x, y); //設(shè)置起始地址 
      while (*str != '\0'){ //連續(xù)寫入字符串?dāng)?shù)據(jù),直到檢測(cè)到結(jié)束符 
      LcdWriteDat(*str++); 
      } 
      } 
      /* 打開光標(biāo)的閃爍效果 */ 
      void LcdOpenCursor(){ 
      LcdWriteCmd(0x0F); 
      } 
      /* 關(guān)閉光標(biāo)顯示 */ 
      void LcdCloseCursor(){ 
      LcdWriteCmd(0x0C); 
      } 
      /* 初始化 1602 液晶 */ 
      void InitLcd1602(){ 
      LcdWriteCmd(0x38); //16*2 顯示,5*7 點(diǎn)陣,8 位數(shù)據(jù)接口 
      LcdWriteCmd(0x0C); //顯示器開,光標(biāo)關(guān)閉 
      LcdWriteCmd(0x06); //文字不動(dòng),地址自動(dòng)+1 
      LcdWriteCmd(0x01); //清屏 
      }
      為了本例的具體需求,在之前文件的基礎(chǔ)上添加兩個(gè)控制光標(biāo)效果打開和關(guān)閉的函數(shù),雖然函數(shù)都很簡(jiǎn)單,但為了保持程序整體上良好的模塊化和層次化,還是應(yīng)該在液晶驅(qū)動(dòng)文件內(nèi)以函數(shù)的形式提供,而不是由應(yīng)用層代碼直接來調(diào)用具體的液晶寫命令操作。
      /***************************keyboard.c 文件程序源代碼****************************/
      (此處省略,可參考之前章節(jié)的代碼)
       /*****************************main.c 文件程序源代碼******************************/ 
      #include <reg52.h> 
      struct sTime { //日期時(shí)間結(jié)構(gòu)體定義 
      unsigned int year; 
      unsigned char mon; 
      unsigned char day; 
      unsigned char hour; 
      unsigned char min; 
      unsigned char sec; 
      unsigned char week; 
      }; 
      bit flag200ms = 1; //200ms 定時(shí)標(biāo)志 
      struct sTime bufTime; //日期時(shí)間緩沖區(qū) 
      unsigned char setIndex = 0; //時(shí)間設(shè)置索引 
      unsigned char T0RH = 0; //T0 重載值的高字節(jié) 
      unsigned char T0RL = 0; //T0 重載值的低字節(jié) 
      void ConfigTimer0(unsigned int ms); 
      void RefreshTimeShow(); 
      extern void InitDS1302(); 
      extern void GetRealTime(struct sTime *time); 
      extern void SetRealTime(struct sTime *time); 
      extern void KeyScan(); 
      extern void KeyDriver(); 
      extern void InitLcd1602(); 
      extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str); 
      extern void LcdSetCursor(unsigned char x, unsigned char y); 
      extern void LcdOpenCursor(); 
      extern void LcdCloseCursor(); 
      void main(){ 
      unsigned char psec=0xAA; //秒備份,初值 AA 確保首次讀取時(shí)間后會(huì)刷新顯示 
      EA = 1; //開總中斷 
      ConfigTimer0(1); //T0 定時(shí) 1ms 
      InitDS1302(); //初始化實(shí)時(shí)時(shí)鐘 
      InitLcd1602(); //初始化液晶 
      //初始化屏幕上固定不變的內(nèi)容 
      LcdShowStr(3, 0, "20 - - "); 
      LcdShowStr(4, 1, " : : "); 
      while (1){ 
      KeyDriver(); //調(diào)用按鍵驅(qū)動(dòng) 
      if (flag200ms && (setIndex == 0)){ //每隔 200ms 且未處于設(shè)置狀態(tài)時(shí), 
      flag200ms = 0; 
      GetRealTime(&bufTime); //獲取當(dāng)前時(shí)間 
      if (psec != bufTime.sec){ //檢測(cè)到時(shí)間有變化時(shí)刷新顯示 
      RefreshTimeShow(); 
      psec = bufTime.sec; //用當(dāng)前值更新上次秒數(shù) 
      } 
      } 
      } 
      } 
      /* 將一個(gè) BCD 碼字節(jié)顯示到屏幕上,(x,y)-屏幕起始坐標(biāo),bcd-待顯示 BCD 碼 */ 
      void ShowBcdByte(unsigned char x, unsigned char y, unsigned char bcd){ 
      unsigned char str[4]; 
      str[0] = (bcd >> 4) + '0'; 
      str[1] = (bcd&0x0F) + '0'; 
      str[2] = '\0'; 
      LcdShowStr(x, y, str); 
      } 
      /* 刷新日期時(shí)間的顯示 */ 
      void RefreshTimeShow(){ 
      ShowBcdByte(5, 0, bufTime.year); 
      ShowBcdByte(8, 0, bufTime.mon); 
      ShowBcdByte(11, 0, bufTime.day); 
      ShowBcdByte(4, 1, bufTime.hour); 
      ShowBcdByte(7, 1, bufTime.min); 
      ShowBcdByte(10, 1, bufTime.sec); 
      } 
      /* 刷新當(dāng)前設(shè)置位的光標(biāo)指示 */ 
      void RefreshSetShow(){ 
      switch (setIndex){ 
      case 1: LcdSetCursor(5, 0); break; 
      case 2: LcdSetCursor(6, 0); break; 
      case 3: LcdSetCursor(8, 0); break; 
      case 4: LcdSetCursor(9, 0); break; 
      case 5: LcdSetCursor(11, 0); break; 
      case 6: LcdSetCursor(12, 0); break; 
      case 7: LcdSetCursor(4, 1); break; 
      case 8: LcdSetCursor(5, 1); break; 
      case 9: LcdSetCursor(7, 1); break; 
      case 10: LcdSetCursor(8, 1); break; 
      case 11: LcdSetCursor(10, 1); break; 
      case 12: LcdSetCursor(11, 1); break; 
      default: break; 
      } 
      } 
      /* 遞增一個(gè) BCD 碼的高位 */ 
      unsigned char IncBcdHigh(unsigned char bcd){ 
      if ((bcd&0xF0) < 0x90){ 
      bcd += 0x10; 
      }else{ 
      bcd &= 0x0F; 
      } 
      return bcd; 
      } 
      /* 遞增一個(gè) BCD 碼的低位 */ 
      unsigned char IncBcdLow(unsigned char bcd){ 
      if ((bcd&0x0F) < 0x09){ 
      bcd += 0x01; 
      }else{ 
      bcd &= 0xF0; 
      } 
      return bcd; 
      } 
      /* 遞減一個(gè) BCD 碼的高位 */ 
      unsigned char DecBcdHigh(unsigned char bcd){ 
      if ((bcd&0xF0) > 0x00){ 
      bcd -= 0x10; 
      }else{ 
      bcd |= 0x90; 
      } 
      return bcd; 
      } 
      /* 遞減一個(gè) BCD 碼的低位 */ 
      unsigned char DecBcdLow(unsigned char bcd){ 
      if ((bcd&0x0F) > 0x00){ 
      bcd -= 0x01; 
      }else{ 
      bcd |= 0x09; 
      } 
      return bcd; 
      } 
      /* 遞增時(shí)間當(dāng)前設(shè)置位的值 */ 
      void IncSetTime(){ 
      switch (setIndex){ 
      case 1: bufTime.year = IncBcdHigh(bufTime.year); break; 
      case 2: bufTime.year = IncBcdLow(bufTime.year); break; 
      case 3: bufTime.mon = IncBcdHigh(bufTime.mon); break; 
      case 4: bufTime.mon = IncBcdLow(bufTime.mon); break; 
      case 5: bufTime.day = IncBcdHigh(bufTime.day); break; 
      case 6: bufTime.day = IncBcdLow(bufTime.day); break; 
      case 7: bufTime.hour = IncBcdHigh(bufTime.hour); break; 
      case 8: bufTime.hour = IncBcdLow(bufTime.hour); break; 
      case 9: bufTime.min = IncBcdHigh(bufTime.min); break; 
      case 10: bufTime.min = IncBcdLow(bufTime.min); break; 
      case 11: bufTime.sec = IncBcdHigh(bufTime.sec); break; 
      case 12: bufTime.sec = IncBcdLow(bufTime.sec); break; 
      default: break; 
      } 
      RefreshTimeShow(); 
      RefreshSetShow(); 
      } 
      /* 遞減時(shí)間當(dāng)前設(shè)置位的值 */ 
      void DecSetTime(){ 
      switch (setIndex){ 
      case 1: bufTime.year = DecBcdHigh(bufTime.year); break; 
      case 2: bufTime.year = DecBcdLow(bufTime.year); break; 
      case 3: bufTime.mon = DecBcdHigh(bufTime.mon); break; 
      case 4: bufTime.mon = DecBcdLow(bufTime.mon); break; 
      case 5: bufTime.day = DecBcdHigh(bufTime.day); break; 
      case 6: bufTime.day = DecBcdLow(bufTime.day); break; 
      case 7: bufTime.hour = DecBcdHigh(bufTime.hour); break; 
      case 8: bufTime.hour = DecBcdLow(bufTime.hour); break; 
      case 9: bufTime.min = DecBcdHigh(bufTime.min); break; 
      case 10: bufTime.min = DecBcdLow(bufTime.min); break; 
      case 11: bufTime.sec = DecBcdHigh(bufTime.sec); break; 
      case 12: bufTime.sec = DecBcdLow(bufTime.sec); 
      default: break; 
      } 
      RefreshTimeShow(); 
      RefreshSetShow(); 
      } 
      /* 右移時(shí)間設(shè)置位 */ 
      void RightShiftTimeSet(){ 
      if (setIndex != 0){ 
      if (setIndex < 12){ 
      setIndex++; 
      }else{ 
      setIndex = 1; 
      } 
      RefreshSetShow(); 
      } 
      } 
      /* 左移時(shí)間設(shè)置位 */ 
      void LeftShiftTimeSet(){ 
      if (setIndex != 0){ 
      if (setIndex > 1){ 
      setIndex--; 
      }else{ 
      setIndex = 12; 
      } 
      RefreshSetShow(); 
      } 
      } 
      /* 進(jìn)入時(shí)間設(shè)置狀態(tài) */ 
      void EnterTimeSet(){ 
      setIndex = 2; //把設(shè)置索引設(shè)置為 2,即可進(jìn)入設(shè)置狀態(tài) 
      LeftShiftTimeSet(); //再利用現(xiàn)成的左移操作移到位置 1 并完成顯示刷新 
      LcdOpenCursor(); //打開光標(biāo)閃爍效果 
      } 
      /* 退出時(shí)間設(shè)置狀態(tài),save-是否保存當(dāng)前設(shè)置的時(shí)間值 */ 
      void ExitTimeSet(bit save){ 
      setIndex = 0; //把設(shè)置索引設(shè)置為 0,即可退出設(shè)置狀態(tài) 
      if (save){ //需保存時(shí)即把當(dāng)前設(shè)置時(shí)間寫入 DS1302 
      SetRealTime(&bufTime); 
      } 
      LcdCloseCursor(); //關(guān)閉光標(biāo)顯示 
      } 
      /* 按鍵動(dòng)作函數(shù),根據(jù)鍵碼執(zhí)行相應(yīng)的操作,keycode-按鍵鍵碼 */ 
      void KeyAction(unsigned char keycode){ 
      if ((keycode>='0') && (keycode<='9')){ //本例中不響應(yīng)字符鍵 
      }else if (keycode == 0x26){ //向上鍵,遞增當(dāng)前設(shè)置位的值 
      IncSetTime(); 
      }else if (keycode == 0x28){ //向下鍵,遞減當(dāng)前設(shè)置位的值 
      DecSetTime(); 
      }else if (keycode == 0x25){ //向左鍵,向左切換設(shè)置位 
      LeftShiftTimeSet(); 
      }else if (keycode == 0x27){ //向右鍵,向右切換設(shè)置位 
      RightShiftTimeSet(); 
      }else if (keycode == 0x0D){ //回車鍵,進(jìn)入設(shè)置模式/啟用當(dāng)前設(shè)置值 
      if (setIndex == 0){ //不處于設(shè)置狀態(tài)時(shí),進(jìn)入設(shè)置狀態(tài) 
      EnterTimeSet(); 
      }else{ //已處于設(shè)置狀態(tài)時(shí),保存時(shí)間并退出設(shè)置狀態(tài) 
      ExitTimeSet(1); 
      } 
      }else if (keycode == 0x1B){ //Esc 鍵,取消當(dāng)前設(shè)置 
      ExitTimeSet(0); 
      } 
      } 
      /* 配置并啟動(dòng) T0,ms-T0 定時(shí)時(shí)間 */ 
      void ConfigTimer0(unsigned int ms){ 
      unsigned long tmp; //臨時(shí)變量 
      tmp = 11059200 / 12; //定時(shí)器計(jì)數(shù)頻率 
      tmp = (tmp * ms) / 1000; //計(jì)算所需的計(jì)數(shù)值 
      tmp = 65536 - tmp; //計(jì)算定時(shí)器重載值 
      tmp = tmp + 28; //補(bǔ)償中斷響應(yīng)延時(shí)造成的誤差 
      T0RH = (unsigned char)(tmp>>8); //定時(shí)器重載值拆分為高低字節(jié) 
      T0RL = (unsigned char)tmp; 
      TMOD &= 0xF0; //清零 T0 的控制位 
      TMOD |= 0x01; //配置 T0 為模式 1 
      TH0 = T0RH; //加載 T0 重載值 
      TL0 = T0RL; 
      ET0 = 1; //使能 T0 中斷 
      TR0 = 1; //啟動(dòng) T0 
      } 
      /* T0 中斷服務(wù)函數(shù),執(zhí)行按鍵掃描和 200ms 定時(shí) */ 
      void InterruptTimer0() interrupt 1{ 
      static unsigned char tmr200ms = 0; 
      TH0 = T0RH; //重新加載重載值 
      TL0 = T0RL; 
      KeyScan(); //按鍵掃描 
      tmr200ms++; 
      if (tmr200ms >= 200){ //定時(shí) 200ms 
      tmr200ms = 0; 
      flag200ms = 1; 
      } 
      }
      main.c 主文件,負(fù)責(zé)所有應(yīng)用層的功能實(shí)現(xiàn),文件比較長,還是那句話“不難但比較煩瑣”,希望對(duì)具體問題分析細(xì)化能力還不太強(qiáng)的同學(xué)們把這個(gè)文件多練習(xí)幾遍,學(xué)習(xí)一下其中把具體問題逐步細(xì)化并一步步實(shí)現(xiàn)出來的編程思想,多進(jìn)行此類練習(xí),鍛煉程序思維能力,將來遇到具體項(xiàng)目設(shè)計(jì)需求的時(shí)候,你很快就可以找到方法并實(shí)現(xiàn)它們了。
      Tags:單片機(jī)電子時(shí)鐘,程序設(shè)計(jì),單片機(jī)時(shí)鐘,c語言  
      責(zé)任編輯:admin
      請(qǐng)文明參與討論,禁止漫罵攻擊,不要惡意評(píng)論、違禁詞語。 昵稱:
      1分 2分 3分 4分 5分

      還可以輸入 200 個(gè)字
      [ 查看全部 ] 網(wǎng)友評(píng)論
      關(guān)于我們 - 聯(lián)系我們 - 廣告服務(wù) - 友情鏈接 - 網(wǎng)站地圖 - 版權(quán)聲明 - 在線幫助 - 文章列表
      返回頂部
      刷新頁面
      下到頁底
      晶體管查詢
      主站蜘蛛池模板: 97色伦图片97综合影院| 国产成人亚洲综合网站不卡| 狠狠色丁香婷婷久久综合五月| 亚洲婷婷五月综合狠狠爱| 亚洲综合日韩中文字幕v在线| 99久久综合狠狠综合久久一区| 小说区综合区首页| 久久99精品久久久久久综合| 五月综合色婷婷影院在线观看 | 久久久久青草线蕉综合超碰| 亚洲国产日韩综合久久精品| 狠狠综合久久av一区二区| 久久综合国产乱子伦精品免费| 亚洲欧美日韩综合久久久久| 狠狠色婷婷综合天天久久丁香| 国产成人+综合亚洲+天堂| 色狠狠色狠狠综合一区| 国产在线视频色综合| 六月婷婷缴清综合在线| 亚洲综合无码一区二区| 久久无码无码久久综合综合| 狠狠综合视频精品播放| 狠狠色丁香婷婷综合潮喷 | 色综合久久精品中文字幕首页 | 99久久国产综合精品五月天| 伊人久久中文大香线蕉综合| 国产性天天综合网| 国产成人精品综合| 一本大道无香蕉综合在线| 天天综合色一区二区三区| 色综合久久综合网| 色婷婷综合中文久久一本| 婷婷激情综合色五月久久| 久久综合久久综合亚洲| 婷婷亚洲综合一区二区| 久久93精品国产91久久综合| 国产成人综合久久精品尤物| 综合三区后入内射国产馆| 亚洲一区综合在线播放| 天天综合天天添夜夜添狠狠添 | 亚洲伊人久久综合影院|