找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

帖子
查看: 3383|回復(fù): 0
收起左側(cè)

工控項目源代碼

[復(fù)制鏈接]
ID:95059 發(fā)表于 2018-6-17 20:45 | 顯示全部樓層 |閱讀模式
/*開場白:
根據(jù)上一節(jié)的預(yù)告,本來這節(jié)要講關(guān)于串口的一個小項目,但是今天中午的時候,有個廈門客戶的出現(xiàn),讓我決定先插入這節(jié)內(nèi)容。
他叫鄭文顯,是做PLC開發(fā)的。今天中午他要我?guī)退麑懸粋€工控程序讓他來學(xué)習(xí),也是基于朱兆祺51單片機(jī)學(xué)習(xí)板的,他想把這個源代碼經(jīng)過自己修改后移植到他自己做的工控板上。我一開始報價4000元,被他砍價到1000元,我看一下也不算很難就答應(yīng)了下來。剛才下午花了3個小時終于做好了。鄭文顯爽快的付了款,并且在電話那里跟我講,他說獨(dú)樂樂不如眾樂樂,資源只有分享才能發(fā)揮它的最大價值,因此他決定要把這個源代碼捐贈出來給大家一起學(xué)。非常感謝他的慈善壯舉。種善因,得善果。好人一生平安。他的這個項目不難,跟我第25節(jié)內(nèi)容很類似,略加修改就可以了。具體功能需求請看以下第(2)點(diǎn)。

(1)硬件平臺:
基于朱兆祺51單片機(jī)學(xué)習(xí)板。

(2)實現(xiàn)功能:
他的系統(tǒng)要控制2個氣缸,沒有任何傳感器。第1個氣缸先伸出去,1秒鐘后再收回來。然后第2個氣缸再伸出去,1秒鐘后再收回來,算完成一個過程,然后重頭開始循環(huán)下去。每一個過程要計數(shù)加1顯示在右邊的4位數(shù)碼管上,左邊的4位數(shù)碼管顯示設(shè)定的最大計數(shù)上限,一旦超過這個計數(shù)上限就自動停止。有4個按鍵,一個按鍵用來啟動,一個按鍵用來急停。另外兩個按鍵是加減按鍵,用來設(shè)置左邊顯示的最大計數(shù)上限。斷電要求數(shù)據(jù)不丟失。如果同時按下加減兩個按鍵,可以清零當(dāng)前計數(shù)的內(nèi)容。
這4個按鍵都是獨(dú)立按鍵。S1鍵是加鍵,S5鍵是減鍵,S9鍵是啟動鍵,S13鍵是急停鍵。其中74HC595驅(qū)動絲印為D1的LED燈模擬第1個氣缸,絲印為D2的LED燈模擬第2個氣缸。

(3)源代碼講解如下:
*/
#include "REG52.H"

#define const_voice_short  40   //蜂鳴器短叫的持續(xù)時間
#define const_key_time1    20    //按鍵去抖動延時的時間
#define const_key_time2    20    //按鍵去抖動延時的時間
#define const_key_time3    20    //按鍵去抖動延時的時間
#define const_key_time4    20    //按鍵去抖動延時的時間
#define const_key_time12   20   //按鍵去抖動延時的時間

#define const_1s  500  //1秒鐘大概的定時中斷次數(shù)



void start24(void);  //開始位
void ack24(void);  //確認(rèn)位
void stop24(void);  //停止位
unsigned char read24(void);  //讀取一個字節(jié)的時序
void write24(unsigned char dd); //發(fā)送一個字節(jié)的時序
unsigned char read_eeprom(unsigned int address);   //從一個地址讀取出一個字節(jié)數(shù)據(jù)
void write_eeprom(unsigned int address,unsigned char dd); //往一個地址存入一個字節(jié)數(shù)據(jù)
unsigned int read_eeprom_int(unsigned int address);   //從一個地址讀取出一個int類型的數(shù)據(jù)
void write_eeprom_int(unsigned int address,unsigned int uiWriteData); //往一個地址存入一個int類型的數(shù)據(jù)


void initial_myself();   
void initial_peripheral();
void delay_short(unsigned int uiDelayShort);
void delay_long(unsigned int uiDelaylong);
//驅(qū)動數(shù)碼管的74HC595
void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01);  
void display_drive(); //顯示數(shù)碼管字模的驅(qū)動函數(shù)
void display_service(); //顯示的窗口菜單服務(wù)程序
//驅(qū)動LED的74HC595
void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01);
void T0_time();  //定時中斷函數(shù)
void key_service(); //按鍵服務(wù)的應(yīng)用程序
void key_scan();//按鍵掃描函數(shù) 放在定時中斷里

void run(); //設(shè)備自動控制程序
void left_to_right();  //從左邊移動到右邊
void right_to_left(); //從右邊返回到左邊
void up_to_down();   //從上邊移動到下邊
void down_to_up();    //從下邊返回到上邊
void led_update();  //LED更新函數(shù)

void delay_timer(unsigned int uiDelayTimerTemp);

sbit key_sr1=P0^0; //對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
sbit key_sr2=P0^1; //對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
sbit key_sr3=P0^2; //對應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
sbit key_sr4=P0^3; //對應(yīng)朱兆祺學(xué)習(xí)板的S13鍵

sbit key_gnd_dr=P0^4; //模擬獨(dú)立按鍵的地GND,因此必須一直輸出低電平
sbit beep_dr=P2^7; //蜂鳴器的驅(qū)動IO口
sbit led_dr=P3^5;  //作為中途暫停指示燈 亮的時候表示中途暫停

sbit dig_hc595_sh_dr=P2^0;     //數(shù)碼管的74HC595程序
sbit dig_hc595_st_dr=P2^1;  
sbit dig_hc595_ds_dr=P2^2;  
sbit hc595_sh_dr=P2^3;    //LED燈的74HC595程序
sbit hc595_st_dr=P2^4;  
sbit hc595_ds_dr=P2^5;  

sbit eeprom_scl_dr=P3^7;    //時鐘線
sbit eeprom_sda_dr_sr=P3^6; //數(shù)據(jù)的輸出線和輸入線


//根據(jù)原理圖得出的共陰數(shù)碼管字模表
code unsigned char dig_table[]=
{
0x3f,  //0       序號0
0x06,  //1       序號1
0x5b,  //2       序號2
0x4f,  //3       序號3
0x66,  //4       序號4
0x6d,  //5       序號5
0x7d,  //6       序號6
0x07,  //7       序號7
0x7f,  //8       序號8
0x6f,  //9       序號9
0x00,  //無      序號10
0x40,  //-       序號11
0x73,  //P       序號12
};

unsigned char ucKeySec=0;   //被觸發(fā)的按鍵編號
unsigned int  uiVoiceCnt=0;  //蜂鳴器鳴叫的持續(xù)時間計數(shù)器


unsigned char ucDigShow8;  //第8位數(shù)碼管要顯示的內(nèi)容
unsigned char ucDigShow7;  //第7位數(shù)碼管要顯示的內(nèi)容
unsigned char ucDigShow6;  //第6位數(shù)碼管要顯示的內(nèi)容
unsigned char ucDigShow5;  //第5位數(shù)碼管要顯示的內(nèi)容
unsigned char ucDigShow4;  //第4位數(shù)碼管要顯示的內(nèi)容
unsigned char ucDigShow3;  //第3位數(shù)碼管要顯示的內(nèi)容
unsigned char ucDigShow2;  //第2位數(shù)碼管要顯示的內(nèi)容
unsigned char ucDigShow1;  //第1位數(shù)碼管要顯示的內(nèi)容

unsigned char ucDigDot8;  //數(shù)碼管8的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigDot7;  //數(shù)碼管7的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigDot6;  //數(shù)碼管6的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigDot5;  //數(shù)碼管5的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigDot4;  //數(shù)碼管4的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigDot3;  //數(shù)碼管3的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigDot2;  //數(shù)碼管2的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigDot1;  //數(shù)碼管1的小數(shù)點(diǎn)是否顯示的標(biāo)志
unsigned char ucDigShowTemp=0; //臨時中間變量
unsigned char ucDisplayDriveStep=1;  //動態(tài)掃描數(shù)碼管的步驟變量

unsigned char ucWd1Part1Update=1; //左邊4位數(shù)碼管更新顯示標(biāo)志
unsigned char ucWd1Part2Update=1; //右邊4位數(shù)碼管更新顯示標(biāo)志

unsigned int  uiSetData=18;  //需要被設(shè)置的計數(shù)上限
unsigned int  uiRunCnt=0; //實際運(yùn)行的計數(shù)值

unsigned char ucRunTimeFlag=0; //延時計數(shù)器的開關(guān)
unsigned int  uiRunTimeCnt=0;  //運(yùn)動中的時間延時計數(shù)器變量

unsigned char ucRunStep=1;  //運(yùn)動控制的步驟變量
unsigned char ucRunFlag=0;  //是否啟動運(yùn)行的標(biāo)志   1代表運(yùn)行

unsigned char ucDelayTimerFlag=0; //計時器的開關(guān)
unsigned int  uiDelayTimer=0;


unsigned char ucLed_dr1=0;   //代表16個燈的亮滅狀態(tài),0代表滅,1代表亮
unsigned char ucLed_dr2=0;
unsigned char ucLed_dr3=0;
unsigned char ucLed_dr4=0;
unsigned char ucLed_dr5=0;
unsigned char ucLed_dr6=0;
unsigned char ucLed_dr7=0;
unsigned char ucLed_dr8=0;
unsigned char ucLed_dr9=0;
unsigned char ucLed_dr10=0;
unsigned char ucLed_dr11=0;
unsigned char ucLed_dr12=0;
unsigned char ucLed_dr13=0;
unsigned char ucLed_dr14=0;
unsigned char ucLed_dr15=0;
unsigned char ucLed_dr16=0;

unsigned char ucLed_update=1;  //刷新變量。每次更改LED燈的狀態(tài)都要更新一次。


void main()
  {
   initial_myself();  
   delay_long(100);   
   initial_peripheral();
   while(1)  
   {
      key_service(); //按鍵服務(wù)的應(yīng)用程序
          run(); //設(shè)備自動控制程序
      display_service(); //顯示的窗口菜單服務(wù)程序
      led_update();  //LED更新函數(shù)
   }
}


void left_to_right()  //從左邊移動到右邊
{
   ucLed_dr1=1;   // 1代表左右氣缸從左邊移動到右邊

   ucLed_update=1;  //刷新變量。每次更改LED燈的狀態(tài)都要更新一次。
}
void right_to_left() //從右邊返回到左邊
{
   ucLed_dr1=0;   // 0代表左右氣缸從右邊返回到左邊

   ucLed_update=1;  //刷新變量。每次更改LED燈的狀態(tài)都要更新一次。
}
void up_to_down()   //從上邊移動到下邊
{
   ucLed_dr2=1;   // 1代表上下氣缸從上邊移動到下邊

   ucLed_update=1;  //刷新變量。每次更改LED燈的狀態(tài)都要更新一次。
}
void down_to_up()    //從下邊返回到上邊
{
   ucLed_dr2=0;   // 0代表上下氣缸從下邊返回到上邊

   ucLed_update=1;  //刷新變量。每次更改LED燈的狀態(tài)都要更新一次。
}


void run() //設(shè)備自動控制程序
{
   if(ucRunFlag==1)  //是否啟動運(yùn)行的標(biāo)志
   {
       switch(ucRunStep)
       {

          case 1:    //機(jī)械手從左邊往右邊移動
               left_to_right();
                           ucRunTimeFlag=0; //延時計數(shù)器關(guān)  在清零uiRunTimeCnt變量前,最好先關(guān)閉計時器開關(guān),起到跟中斷互鎖作用
                             uiRunTimeCnt=0;  //時間計數(shù)器清零,為接下來延時1秒鐘做準(zhǔn)備
               ucRunTimeFlag=1; //延時計數(shù)器開    感謝鄭文顯捐助本節(jié)源代碼
               ucRunStep=2;  //這就是鴻哥傳說中的怎樣靈活控制步驟變量
               break;
          case 2:    //延時1秒
               if(uiRunTimeCnt>const_1s)  //延時1秒
               {
                  ucRunStep=3;  //這就是鴻哥傳說中的怎樣靈活控制步驟變量
               }
               break;
          case 3:    //機(jī)械手從右邊往左邊移動
               right_to_left();
                           ucRunTimeFlag=0; //延時計數(shù)器關(guān)  在清零uiRunTimeCnt變量前,最好先關(guān)閉計時器開關(guān),起到跟中斷互鎖作用
                             uiRunTimeCnt=0;  //時間計數(shù)器清零,為接下來延時1秒鐘做準(zhǔn)備
               ucRunTimeFlag=1; //延時計數(shù)器開
               ucRunStep=4;  //這就是鴻哥傳說中的怎樣靈活控制步驟變量
               break;
          case 4:    //延時1秒
               if(uiRunTimeCnt>const_1s)  //延時1秒
               {
                  ucRunStep=5;  //這就是鴻哥傳說中的怎樣靈活控制步驟變量
               }
               break;
          case 5:    //機(jī)械手//從上邊移動到下邊
               up_to_down();   
                           ucRunTimeFlag=0; //延時計數(shù)器關(guān)  在清零uiRunTimeCnt變量前,最好先關(guān)閉計時器開關(guān),起到跟中斷互鎖作用
                             uiRunTimeCnt=0;  //時間計數(shù)器清零,為接下來延時1秒鐘做準(zhǔn)備
               ucRunTimeFlag=1; //延時計數(shù)器開
               ucRunStep=6;  //這就是鴻哥傳說中的怎樣靈活控制步驟變量
               break;
          case 6:    //延時1秒
               if(uiRunTimeCnt>const_1s)  //延時1秒
               {
                  ucRunStep=7;  //這就是鴻哥傳說中的怎樣靈活控制步驟變量
               }
               break;
          case 7:    //機(jī)械手從下邊返回到上邊
               down_to_up();   
                           ucRunTimeFlag=0; //延時計數(shù)器關(guān)  在清零uiRunTimeCnt變量前,最好先關(guān)閉計時器開關(guān),起到跟中斷互鎖作用
                             uiRunTimeCnt=0;  //時間計數(shù)器清零,為接下來延時1秒鐘做準(zhǔn)備
               ucRunTimeFlag=1; //延時計數(shù)器開  感謝鄭文顯捐助本節(jié)源代碼
               ucRunStep=8;  //這就是鴻哥傳說中的怎樣靈活控制步驟變量
               break;
          case 8:    //延時1秒
               if(uiRunTimeCnt>const_1s)  //延時1秒
               {
                  uiRunCnt++; //實際運(yùn)行的計數(shù)值累加
                                  if(uiRunCnt>9999)  //數(shù)碼管最大顯示4位9999,如果超過了,繼續(xù)默認(rèn)為9999
                  {
                                     uiRunCnt=9999;
                                  }
                  ucWd1Part2Update=1;  //右邊4位數(shù)碼管更新顯示

                  write_eeprom_int(2,uiRunCnt); //及時把數(shù)據(jù)存進(jìn)EEPROM,避免掉電丟失數(shù)據(jù)

                                  if(uiRunCnt>=uiSetData) //如果實際的計數(shù)大于或者等于設(shè)定上限,則停止
                                  {
                                     ucRunFlag=0;  //停止
                                         ucRunStep=1;  //切換到第一步為下一次準(zhǔn)備
                                  }
                                  else
                                  {
                     ucRunStep=1;  //切換到第一步繼續(xù)運(yùn)行
                                  }
               }
               break;
       }
   }
}


void display_service() //顯示的窗口菜單服務(wù)程序
{
  //加了static關(guān)鍵字后,此局部變量不會每次進(jìn)來函數(shù)都初始化一次,這樣減少了一點(diǎn)指令消耗的時間。
            static unsigned char ucTemp4;   //中間過渡變量
            static unsigned char ucTemp3;   //中間過渡變量
            static unsigned char ucTemp2;   //中間過渡變量
            static unsigned char ucTemp1;   //中間過渡變量

            //左邊4位數(shù)碼管顯示設(shè)置的計數(shù)上限
            if(ucWd1Part1Update==1)  //左邊4位數(shù)碼管要全部更新顯示
            {
               ucWd1Part1Update=0;  //及時清零標(biāo)志,避免一直進(jìn)來掃描

              //先分解數(shù)據(jù)用來顯示每一位
               ucTemp4=uiSetData/1000;     
               ucTemp3=uiSetData%1000/100;
               ucTemp2=uiSetData%100/10;
               ucTemp1=uiSetData%10;


               if(uiSetData<1000)   
               {
                  ucDigShow8=10;  //如果小于1000,千位顯示無
               }
               else
               {
                  ucDigShow8=ucTemp4;  //第8位數(shù)碼管要顯示的內(nèi)容
               }

               if(uiSetData<100)
               {
                  ucDigShow7=10;  //如果小于100,百位顯示無
               }
               else
               {
                  ucDigShow7=ucTemp3;  //第7位數(shù)碼管要顯示的內(nèi)容
               }

               if(uiSetData<10)
               {
                  ucDigShow6=10;  //如果小于10,十位顯示無
               }
               else
               {
                  ucDigShow6=ucTemp2;  //第6位數(shù)碼管要顯示的內(nèi)容
               }

                ucDigShow5=ucTemp1;  //第5位數(shù)碼管要顯示的內(nèi)容
            }

            //右邊4位數(shù)碼管顯示實際的計數(shù)
            if(ucWd1Part2Update==1)  //右邊4位數(shù)碼管要全部更新顯示
            {
               ucWd1Part2Update=0;  //及時清零標(biāo)志,避免一直進(jìn)來掃描


              //先分解數(shù)據(jù)用來顯示每一位
               ucTemp4=uiRunCnt/1000;     
               ucTemp3=uiRunCnt%1000/100;
               ucTemp2=uiRunCnt%100/10;
               ucTemp1=uiRunCnt%10;


               if(uiRunCnt<1000)   
               {
                  ucDigShow4=10;  //如果小于1000,千位顯示無
               }
               else
               {
                  ucDigShow4=ucTemp4;  //第8位數(shù)碼管要顯示的內(nèi)容
               }

               if(uiRunCnt<100)
               {
                  ucDigShow3=10;  //如果小于100,百位顯示無
               }
               else
               {
                  ucDigShow3=ucTemp3;  //第7位數(shù)碼管要顯示的內(nèi)容
               }

               if(uiRunCnt<10)
               {
                  ucDigShow2=10;  //如果小于10,十位顯示無
               }
               else
               {
                  ucDigShow2=ucTemp2;  //第6位數(shù)碼管要顯示的內(nèi)容
               }

                ucDigShow1=ucTemp1;  //第5位數(shù)碼管要顯示的內(nèi)容
            }
}

void key_scan()//按鍵掃描函數(shù) 放在定時中斷里
{  
  //加了static關(guān)鍵字后,此局部變量不會每次進(jìn)來函數(shù)都被初始化一次,這樣可以記錄保存上一次執(zhí)行本函數(shù)后的數(shù)值
static unsigned int  uiKeyTimeCnt1=0; //按鍵去抖動延時計數(shù)器
static unsigned char ucKeyLock1=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
static unsigned int  uiKeyTimeCnt2=0; //按鍵去抖動延時計數(shù)器
static unsigned char ucKeyLock2=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
static unsigned int  uiKeyTimeCnt3=0; //按鍵去抖動延時計數(shù)器
static unsigned char ucKeyLock3=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志
static unsigned int  uiKeyTimeCnt4=0; //按鍵去抖動延時計數(shù)器
static unsigned char ucKeyLock4=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志

static unsigned int  uiKeyTimeCnt12=0; //按鍵去抖動延時計數(shù)器
static unsigned char ucKeyLock12=0; //按鍵觸發(fā)后自鎖的變量標(biāo)志

  if(key_sr1==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
  {
     ucKeyLock1=0; //按鍵自鎖標(biāo)志清零
     uiKeyTimeCnt1=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。      
  }
  else if(ucKeyLock1==0)//有按鍵按下,且是第一次被按下
  {
     uiKeyTimeCnt1++; //累加定時中斷次數(shù)
     if(uiKeyTimeCnt1>const_key_time1)
     {
        uiKeyTimeCnt1=0;
        ucKeyLock1=1;  //自鎖按鍵置位,避免一直觸發(fā)
        ucKeySec=1;    //觸發(fā)1號鍵
     }
  }
  if(key_sr2==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
  {
     ucKeyLock2=0; //按鍵自鎖標(biāo)志清零
     uiKeyTimeCnt2=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。      
  }
  else if(ucKeyLock2==0)//有按鍵按下,且是第一次被按下
  {
     uiKeyTimeCnt2++; //累加定時中斷次數(shù)
     if(uiKeyTimeCnt2>const_key_time2)
     {
        uiKeyTimeCnt2=0;
        ucKeyLock2=1;  //自鎖按鍵置位,避免一直觸發(fā)
        ucKeySec=2;    //觸發(fā)2號鍵
     }
  }
  if(key_sr3==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
  {
     ucKeyLock3=0; //按鍵自鎖標(biāo)志清零
     uiKeyTimeCnt3=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。      
  }
  else if(ucKeyLock3==0)//有按鍵按下,且是第一次被按下
  {
     uiKeyTimeCnt3++; //累加定時中斷次數(shù)
     if(uiKeyTimeCnt3>const_key_time3)
     {
        uiKeyTimeCnt3=0;
        ucKeyLock3=1;  //自鎖按鍵置位,避免一直觸發(fā)
        ucKeySec=3;    //觸發(fā)3號鍵
     }
  }

  if(key_sr4==1)//IO是高電平,說明按鍵沒有被按下,這時要及時清零一些標(biāo)志位
  {
     ucKeyLock4=0; //按鍵自鎖標(biāo)志清零
     uiKeyTimeCnt4=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。      
  }
  else if(ucKeyLock4==0)//有按鍵按下,且是第一次被按下
  {
     uiKeyTimeCnt4++; //累加定時中斷次數(shù)
     if(uiKeyTimeCnt4>const_key_time4)
     {
        uiKeyTimeCnt4=0;
        ucKeyLock4=1;  //自鎖按鍵置位,避免一直觸發(fā)
        ucKeySec=4;    //觸發(fā)4號鍵
     }
  }

//5號組合鍵
if(key_sr1==1||key_sr2==1)//IO是高電平,說明兩個按鍵沒有全部被按下,這時要及時清零一些標(biāo)志位
  {
         ucKeyLock12=0; //按鍵自鎖標(biāo)志清零
         uiKeyTimeCnt12=0;//按鍵去抖動延時計數(shù)器清零,此行非常巧妙,是我實戰(zhàn)中摸索出來的。      
  }
  else if(ucKeyLock12==0)//有按鍵按下,且是第一次被按下
  {
     uiKeyTimeCnt12++; //累加定時中斷次數(shù)
     if(uiKeyTimeCnt12>const_key_time12)
     {
        uiKeyTimeCnt12=0;
        ucKeyLock12=1;  //自鎖按鍵置位,避免一直觸發(fā)
        ucKeySec=5;    //觸發(fā)5號組合鍵

     }
  }


}

void key_service() //按鍵服務(wù)的應(yīng)用程序
{
  switch(ucKeySec) //按鍵服務(wù)狀態(tài)切換
  {
    case 1:// 加按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S1鍵
          if(ucRunFlag==0)  //如果系統(tǒng)還沒運(yùn)行
                  {
             uiSetData++;    //被設(shè)置的計數(shù)上限
             if(uiSetData>9999) //最大值是9999
             {
                uiSetData=9999;
             }
             ucWd1Part1Update=1;  //左邊4位數(shù)碼管更新顯示

                  write_eeprom_int(0,uiSetData); //及時保存數(shù)據(jù)進(jìn)EEPROM,避免掉電丟失
             uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
                  }
          ucKeySec=0;  //響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
          break;   

    case 2:// 減按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S5鍵
          if(ucRunFlag==0)  //如果系統(tǒng)還沒運(yùn)行
                  {
             uiSetData--;   
             if(uiSetData>9999)  //unsigned int 類型的0減去1會變成65535(0xffff)
             {
                uiSetData=0;  //最小值是0
             }
             ucWd1Part1Update=1;  //左邊4位數(shù)碼管更新顯示

             write_eeprom_int(0,uiSetData); //及時保存數(shù)據(jù)進(jìn)EEPROM,避免掉電丟失                  
             uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
                  }
          ucKeySec=0;  //響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
          break;  
    case 3://啟動按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
          if(ucRunFlag==0&&uiRunCnt<uiSetData)  //如果系統(tǒng)還沒運(yùn)行,并且實際運(yùn)行的次數(shù)小于設(shè)定的最大次數(shù),則啟動
                  {
                      ucRunFlag=1;
              ucRunStep=1;
              uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
                  }

          ucKeySec=0;  //響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
          break;  
    case 4://急停按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的S9鍵
          ucRunFlag=0; //急停
          ucRunStep=1;
          right_to_left(); //從右邊返回到左邊
          down_to_up();    //從下邊返回到上邊

          uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
          ucKeySec=0;  //響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
          break;

    case 5://清零的組合按鍵 對應(yīng)朱兆祺學(xué)習(xí)板的(S1+S5)組合鍵
          if(ucRunFlag==0)  //如果系統(tǒng)還沒運(yùn)行
                  {
             uiRunCnt=0; //實際計數(shù)清零
             ucWd1Part2Update=1;  //右邊4位數(shù)碼管更新顯示

             write_eeprom_int(2,uiRunCnt); //存入uiRunCnt,內(nèi)部占用2個字節(jié)地址
             uiVoiceCnt=const_voice_short; //按鍵聲音觸發(fā),滴一聲就停。
                  }
          ucKeySec=0;  //響應(yīng)按鍵服務(wù)處理程序后,按鍵編號清零,避免一致觸發(fā)
          break;        
  }               
}



void led_update()  //LED更新函數(shù)
{
  //加了static關(guān)鍵字后,此局部變量不會每次進(jìn)來函數(shù)都被初始化一次,這樣可以記錄保存上一次執(zhí)行本函數(shù)后的數(shù)值
static unsigned char ucLedStatus16_09=0;   //代表底層74HC595輸出狀態(tài)的中間變量
static unsigned char ucLedStatus08_01=0;   //代表底層74HC595輸出狀態(tài)的中間變量

   if(ucLed_update==1)
   {
       ucLed_update=0;   //及時清零,讓它產(chǎn)生只更新一次的效果,避免一直更新。

       if(ucLed_dr1==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x01;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0xfe;
           }

       if(ucLed_dr2==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x02;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0xfd;
           }

       if(ucLed_dr3==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x04;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0xfb;
           }

       if(ucLed_dr4==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x08;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0xf7;
           }


       if(ucLed_dr5==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x10;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0xef;
           }


       if(ucLed_dr6==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x20;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0xdf;
           }


       if(ucLed_dr7==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x40;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0xbf;
           }


       if(ucLed_dr8==1)
           {
              ucLedStatus08_01=ucLedStatus08_01|0x80;
           }
           else
           {
              ucLedStatus08_01=ucLedStatus08_01&0x7f;
           }

       if(ucLed_dr9==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x01;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0xfe;
           }

       if(ucLed_dr10==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x02;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0xfd;
           }

       if(ucLed_dr11==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x04;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0xfb;
           }

       if(ucLed_dr12==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x08;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0xf7;
           }


       if(ucLed_dr13==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x10;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0xef;
           }


       if(ucLed_dr14==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x20;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0xdf;
           }


       if(ucLed_dr15==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x40;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0xbf;
           }


       if(ucLed_dr16==1)
           {
              ucLedStatus16_09=ucLedStatus16_09|0x80;
           }
           else
           {
              ucLedStatus16_09=ucLedStatus16_09&0x7f;
           }

       hc595_drive(ucLedStatus16_09,ucLedStatus08_01);  //74HC595底層驅(qū)動函數(shù)

   }
}


void display_drive()  
{
   //以下程序,如果加一些數(shù)組和移位的元素,還可以壓縮容量。但是鴻哥追求的不是容量,而是清晰的講解思路
   switch(ucDisplayDriveStep)
   {
      case 1:  //顯示第1位
           ucDigShowTemp=dig_table[ucDigShow1];
                   if(ucDigDot1==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
                   }
           dig_hc595_drive(ucDigShowTemp,0xfe);
               break;
      case 2:  //顯示第2位
           ucDigShowTemp=dig_table[ucDigShow2];
                   if(ucDigDot2==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
                   }
           dig_hc595_drive(ucDigShowTemp,0xfd);
               break;
      case 3:  //顯示第3位
           ucDigShowTemp=dig_table[ucDigShow3];
                   if(ucDigDot3==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
                   }
           dig_hc595_drive(ucDigShowTemp,0xfb);
               break;
      case 4:  //顯示第4位
           ucDigShowTemp=dig_table[ucDigShow4];
                   if(ucDigDot4==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
                   }
           dig_hc595_drive(ucDigShowTemp,0xf7);
               break;
      case 5:  //顯示第5位
           ucDigShowTemp=dig_table[ucDigShow5];
                   if(ucDigDot5==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
                   }
           dig_hc595_drive(ucDigShowTemp,0xef);
               break;
      case 6:  //顯示第6位
           ucDigShowTemp=dig_table[ucDigShow6];
                   if(ucDigDot6==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
                   }
           dig_hc595_drive(ucDigShowTemp,0xdf);
               break;
      case 7:  //顯示第7位
           ucDigShowTemp=dig_table[ucDigShow7];
                   if(ucDigDot7==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
           }
           dig_hc595_drive(ucDigShowTemp,0xbf);
               break;
      case 8:  //顯示第8位
           ucDigShowTemp=dig_table[ucDigShow8];
                   if(ucDigDot8==1)
                   {
                      ucDigShowTemp=ucDigShowTemp|0x80;  //顯示小數(shù)點(diǎn)
                   }
           dig_hc595_drive(ucDigShowTemp,0x7f);
               break;
   }
   ucDisplayDriveStep++;
   if(ucDisplayDriveStep>8)  //掃描完8個數(shù)碼管后,重新從第一個開始掃描
   {
     ucDisplayDriveStep=1;
   }

}

//數(shù)碼管的74HC595驅(qū)動函數(shù)
void dig_hc595_drive(unsigned char ucDigStatusTemp16_09,unsigned char ucDigStatusTemp08_01)
{
   unsigned char i;
   unsigned char ucTempData;
   dig_hc595_sh_dr=0;
   dig_hc595_st_dr=0;
   ucTempData=ucDigStatusTemp16_09;  //先送高8位
   for(i=0;i<8;i++)
   {
         if(ucTempData>=0x80)dig_hc595_ds_dr=1;
         else dig_hc595_ds_dr=0;
         dig_hc595_sh_dr=0;     //SH引腳的上升沿把數(shù)據(jù)送入寄存器
         delay_short(1);
         dig_hc595_sh_dr=1;
         delay_short(1);
         ucTempData=ucTempData<<1;
   }
   ucTempData=ucDigStatusTemp08_01;  //再先送低8位
   for(i=0;i<8;i++)
   {
         if(ucTempData>=0x80)dig_hc595_ds_dr=1;
         else dig_hc595_ds_dr=0;
         dig_hc595_sh_dr=0;     //SH引腳的上升沿把數(shù)據(jù)送入寄存器
         delay_short(1);
         dig_hc595_sh_dr=1;
         delay_short(1);
         ucTempData=ucTempData<<1;
   }
   dig_hc595_st_dr=0;  //ST引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
   delay_short(1);
   dig_hc595_st_dr=1;
   delay_short(1);
   dig_hc595_sh_dr=0;    //拉低,抗干擾就增強(qiáng)
   dig_hc595_st_dr=0;
   dig_hc595_ds_dr=0;
}

//LED燈的74HC595驅(qū)動函數(shù)
void hc595_drive(unsigned char ucLedStatusTemp16_09,unsigned char ucLedStatusTemp08_01)
{
   unsigned char i;
   unsigned char ucTempData;
   hc595_sh_dr=0;
   hc595_st_dr=0;
   ucTempData=ucLedStatusTemp16_09;  //先送高8位
   for(i=0;i<8;i++)
   {
         if(ucTempData>=0x80)hc595_ds_dr=1;
         else hc595_ds_dr=0;
         hc595_sh_dr=0;     //SH引腳的上升沿把數(shù)據(jù)送入寄存器
         delay_short(1);
         hc595_sh_dr=1;
         delay_short(1);
         ucTempData=ucTempData<<1;
   }
   ucTempData=ucLedStatusTemp08_01;  //再先送低8位
   for(i=0;i<8;i++)
   {
         if(ucTempData>=0x80)hc595_ds_dr=1;
         else hc595_ds_dr=0;
         hc595_sh_dr=0;     //SH引腳的上升沿把數(shù)據(jù)送入寄存器
         delay_short(1);
         hc595_sh_dr=1;
         delay_short(1);
         ucTempData=ucTempData<<1;
   }
   hc595_st_dr=0;  //ST引腳把兩個寄存器的數(shù)據(jù)更新輸出到74HC595的輸出引腳上并且鎖存起來
   delay_short(1);
   hc595_st_dr=1;
   delay_short(1);
   hc595_sh_dr=0;    //拉低,抗干擾就增強(qiáng)
   hc595_st_dr=0;
   hc595_ds_dr=0;
}



//AT24C02驅(qū)動程序
void start24(void)  //開始位
{

    eeprom_sda_dr_sr=1;
    eeprom_scl_dr=1;
        delay_short(15);
    eeprom_sda_dr_sr=0;
        delay_short(15);
    eeprom_scl_dr=0;   
}


void ack24(void)  //確認(rèn)位時序
{
    eeprom_sda_dr_sr=1; //51單片機(jī)在讀取數(shù)據(jù)之前要先置一,表示數(shù)據(jù)輸入

    eeprom_scl_dr=1;
        delay_short(15);
    eeprom_scl_dr=0;
        delay_short(15);

//在本驅(qū)動程序中,我沒有對ACK信號進(jìn)行出錯判斷,因為我這么多年一直都是這樣用也沒出現(xiàn)過什么問題。
//有興趣的朋友可以自己增加出錯判斷,不一定非要按我的方式去做。
}

void stop24(void)  //停止位
{
    eeprom_sda_dr_sr=0;
    eeprom_scl_dr=1;
        delay_short(15);
    eeprom_sda_dr_sr=1;
}



unsigned char read24(void)  //讀取一個字節(jié)的時序
{
        unsigned char outdata,tempdata;


        outdata=0;
                eeprom_sda_dr_sr=1; //51單片機(jī)的IO口在讀取數(shù)據(jù)之前要先置一,表示數(shù)據(jù)輸入
        delay_short(2);
        for(tempdata=0;tempdata<8;tempdata++)
        {
            eeprom_scl_dr=0;
            delay_short(2);
            eeprom_scl_dr=1;
            delay_short(2);
            outdata<<=1;
            if(eeprom_sda_dr_sr==1)outdata++;      
            eeprom_sda_dr_sr=1; //51單片機(jī)的IO口在讀取數(shù)據(jù)之前要先置一,表示數(shù)據(jù)輸入
            delay_short(2);
        }
    return(outdata);

}

void write24(unsigned char dd) //發(fā)送一個字節(jié)的時序
{

        unsigned char tempdata;
        for(tempdata=0;tempdata<8;tempdata++)
        {
                if(dd>=0x80)eeprom_sda_dr_sr=1;
                else eeprom_sda_dr_sr=0;
                dd<<=1;
                delay_short(2);
                eeprom_scl_dr=1;
                delay_short(4);
                eeprom_scl_dr=0;
        }


}



unsigned char read_eeprom(unsigned int address)   //從一個地址讀取出一個字節(jié)數(shù)據(jù)
{

   unsigned char dd,cAddress;  

   cAddress=address; //把低字節(jié)地址傳遞給一個字節(jié)變量。

   EA=0; //禁止中斷

   start24(); //IIC通訊開始

   write24(0xA0); //此字節(jié)包含讀寫指令和芯片地址兩方面的內(nèi)容。
                  //指令為寫指令。地址為"000"的信息,此信息由A0,A1,A2的引腳決定

   ack24(); //發(fā)送應(yīng)答信號   
   write24(cAddress); //發(fā)送讀取的存儲地址(范圍是0至255)
   ack24(); //發(fā)送應(yīng)答信號

   start24(); //開始
   write24(0xA1); //此字節(jié)包含讀寫指令和芯片地址兩方面的內(nèi)容。
                  //指令為讀指令。地址為"000"的信息,此信息由A0,A1,A2的引腳決定
   ack24(); //發(fā)送應(yīng)答信號
   dd=read24(); //讀取一個字節(jié)
   ack24(); //發(fā)送應(yīng)答信號
   stop24();  //停止
   EA=1; //允許中斷
   delay_timer(2); //一氣呵成的定時器延時方式,在延時的時候還可以動態(tài)掃描數(shù)碼管

   return(dd);
}

void write_eeprom(unsigned int address,unsigned char dd) //往一個地址存入一個字節(jié)數(shù)據(jù)
{
   unsigned char cAddress;   

   cAddress=address; //把低字節(jié)地址傳遞給一個字節(jié)變量。


   EA=0; //禁止中斷

   start24(); //IIC通訊開始

   write24(0xA0); //此字節(jié)包含讀寫指令和芯片地址兩方面的內(nèi)容。
                  //指令為寫指令。地址為"000"的信息,此信息由A0,A1,A2的引腳決定
   ack24(); //發(fā)送應(yīng)答信號
   write24(cAddress);   //發(fā)送寫入的存儲地址(范圍是0至255)
   ack24(); //發(fā)送應(yīng)答信號
   write24(dd);  //寫入存儲的數(shù)據(jù)
   ack24(); //發(fā)送應(yīng)答信號
   stop24();  //停止
   EA=1; //允許中斷
   delay_timer(4); //一氣呵成的定時器延時方式,在延時的時候還可以動態(tài)掃描數(shù)碼管

}


unsigned int read_eeprom_int(unsigned int address)   //從一個地址讀取出一個int類型的數(shù)據(jù)
{
   unsigned char ucReadDataH;
   unsigned char ucReadDataL;
   unsigned int  uiReadDate;

   ucReadDataH=read_eeprom(address);    //讀取高字節(jié)
   ucReadDataL=read_eeprom(address+1);  //讀取低字節(jié)

   uiReadDate=ucReadDataH;  //把兩個字節(jié)合并成一個int類型數(shù)據(jù)
   uiReadDate=uiReadDate<<8;
   uiReadDate=uiReadDate+ucReadDataL;

   return uiReadDate;

}

void write_eeprom_int(unsigned int address,unsigned int uiWriteData) //往一個地址存入一個int類型的數(shù)據(jù)
{
   unsigned char ucWriteDataH;
   unsigned char ucWriteDataL;

   ucWriteDataH=uiWriteData>>8;
   ucWriteDataL=uiWriteData;

   write_eeprom(address,ucWriteDataH); //存入高字節(jié)
   write_eeprom(address+1,ucWriteDataL); //存入低字節(jié)

}


void T0_time() interrupt 1
{
  TF0=0;  //清除中斷標(biāo)志
  TR0=0; //關(guān)中斷

  if(ucRunTimeFlag==1) //void run函數(shù)中的延時計數(shù)器開關(guān)
  {
     uiRunTimeCnt++; //延時計數(shù)器
  }

  if(ucDelayTimerFlag==1)//delay_timer函數(shù)中的延時計數(shù)器開關(guān)
  {
     if(uiDelayTimer>0)
         {
           uiDelayTimer--;   //一氣呵成的定時器延時方式的計時器
         }

  }

  key_scan(); //按鍵掃描函數(shù)
  if(uiVoiceCnt!=0)
  {
     uiVoiceCnt--; //每次進(jìn)入定時中斷都自減1,直到等于零為止。才停止鳴叫
     beep_dr=0;  //蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
//     beep_dr=1;  //蜂鳴器是PNP三極管控制,低電平就開始鳴叫。
  }
  else
  {
     ; //此處多加一個空指令,想維持跟if括號語句的數(shù)量對稱,都是兩條指令。不加也可以。
     beep_dr=1;  //蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
//     beep_dr=0;  //蜂鳴器是PNP三極管控制,高電平就停止鳴叫。
  }
  display_drive();  //數(shù)碼管字模的驅(qū)動函數(shù)

  TH0=0xfe;   //重裝初始值(65535-500)=65035=0xfe0b
  TL0=0x0b;
  TR0=1;  //開中斷
}

void delay_timer(unsigned int uiDelayTimerTemp)
{
    ucDelayTimerFlag=0; //延時計時器關(guān)  在設(shè)置參數(shù)前,先關(guān)閉計時器
    uiDelayTimer=uiDelayTimerTemp;
    ucDelayTimerFlag=1; //延時計時器開  

    while(uiDelayTimer!=0);  //一氣呵成的定時器方式延時等待

}

void delay_short(unsigned int uiDelayShort)
{
   unsigned int i;  
   for(i=0;i<uiDelayShort;i++)
   {
     ;   //一個分號相當(dāng)于執(zhí)行一條空語句
   }
}

void delay_long(unsigned int uiDelayLong)
{
   unsigned int i;
   unsigned int j;
   for(i=0;i<uiDelayLong;i++)
   {
      for(j=0;j<500;j++)  //內(nèi)嵌循環(huán)的空指令數(shù)量
          {
             ; //一個分號相當(dāng)于執(zhí)行一條空語句
          }
   }
}

void initial_myself()  //第一區(qū) 初始化單片機(jī)
{
/* 注釋一:
* 矩陣鍵盤也可以做獨(dú)立按鍵,前提是把某一根公共輸出線輸出低電平,
* 模擬獨(dú)立按鍵的觸發(fā)地,本程序中,把key_gnd_dr輸出低電平。
* 朱兆祺51學(xué)習(xí)板的S1就是本程序中用到的一個獨(dú)立按鍵。
*/
  key_gnd_dr=0; //模擬獨(dú)立按鍵的地GND,因此必須一直輸出低電平
  led_dr=0;  //關(guān)閉獨(dú)立LED燈 感謝鄭文顯捐助本節(jié)源代碼
  beep_dr=1; //用PNP三極管控制蜂鳴器,輸出高電平時不叫。
  hc595_drive(0x00,0x00);  //關(guān)閉所有經(jīng)過另外兩個74HC595驅(qū)動的LED燈
  TMOD=0x01;  //設(shè)置定時器0為工作方式1
  TH0=0xfe;   //重裝初始值(65535-500)=65035=0xfe0b
  TL0=0x0b;
}
void initial_peripheral() //第二區(qū) 初始化外圍
{

   ucDigDot8=0;   //小數(shù)點(diǎn)全部不顯示
   ucDigDot7=0;  
   ucDigDot6=0;
   ucDigDot5=0;  
   ucDigDot4=0;
   ucDigDot3=0;  
   ucDigDot2=0;
   ucDigDot1=0;
   EA=1;     //開總中斷
   ET0=1;    //允許定時中斷
   TR0=1;    //啟動定時中斷

   uiSetData=read_eeprom_int(0);  //讀取uiSetData,內(nèi)部占用2個字節(jié)地址
   if(uiSetData>9999)   //不在范圍內(nèi)
   {
       uiSetData=0;   //填入一個初始化數(shù)據(jù)
       write_eeprom_int(0,uiSetData); //存入uiSetData,內(nèi)部占用2個字節(jié)地址
   }

   uiRunCnt=read_eeprom_int(2);  //讀取uiRunCnt,內(nèi)部占用2個字節(jié)地址
   if(uiRunCnt>9999)//不在范圍內(nèi)
   {
       uiRunCnt=0;  //填入一個初始化數(shù)據(jù)
       write_eeprom_int(2,uiRunCnt); //存入uiRunCnt,內(nèi)部占用2個字節(jié)地址
   }

}
/*總結(jié)陳詞:
再次感謝鄭文顯的無私奉獻(xiàn)。前面第38節(jié)到第45節(jié)是講串口的,我的串口程序大部分都是通過靠時間來識別每一串?dāng)?shù)據(jù)是否接收完畢,只要第41節(jié)內(nèi)容不是靠時間來判斷,而是根據(jù)特定關(guān)鍵字來快速識別數(shù)據(jù)串是否接收完畢,下一節(jié)我打算結(jié)合我最新的一個項目經(jīng)驗,繼續(xù)講一個這方面的例子。欲知詳情,請聽下回分解----當(dāng)主機(jī)連續(xù)不斷地發(fā)送一串串?dāng)?shù)據(jù)給從機(jī)時,從機(jī)串口如何快速截取有效數(shù)據(jù)串。
*/

工控項目源代碼.rar

104.45 KB, 下載次數(shù): 24, 下載積分: 黑幣 -5

評分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎勵!

查看全部評分

回復(fù)

使用道具 舉報

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

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表