網路城邦
上一篇 回創作列表 下一篇   字體:
鬧鐘2.0加強版功能說明
2019/01/26 20:51:43瀏覽378|回應0|推薦0

鬧鐘2.0加強版功能說明

         有鑑於上次發表之"單晶片MCU STC12C5608AD的時鐘程式"一文中的介紹,因為未設計按鍵操控,在此次特別將增加4只按鍵,4只LED指示燈,CDS光耦電阻與BUZZ蜂鳴器元件於焊接樣品中,而顯示器沿用I2C-LCM,因為單晶片MCU STC12C5608AD的程式容量可達8K大小,因此增加了一個11組鬧鐘時間設定,與判別光敏耦合電阻,當然程式比對鬧鐘時間有任一組吻合時,就啟動蜂鳴器一分鐘,之所以有11組,是設想RAM記憶體足夠,因此利用矩陣方式,共設定了11組,將來可再附加功能,設想將來再擴展時,可以一星期7天以上,另保留4組記憶組可供其他方面使用,再者是增加了4個按鍵可操控的功能。

SW1功能介紹:

        此按鍵在顯示幾個在內部的參數,分別如下:

        CDS_cnt : 就是CDS光敏耦合電阻被慼應次數,每次有光線照應於光敏耦合電阻表面一次,內部的CDS_cnt將加一次.

        CTx: 此為TIMER 0的計時器,目前使用4ms一次中斷,但是XTAL石英振盪晶體22.1184MHZ,

會隨著溫度有所漂移,因此在程式增加正補償參數CTx,此參數愈增加,對應的是時間將走慢。

        CTy: 此為負補償參數,愈是增加時間會走的愈快。

        CTz: 則是提供在CTx,CTy的正負補償仍無法滿足修正時鐘之準確性時,可用CTz來做為補秒之用 .

 


 線路圖 :
 LT-TEST_05線路圖
實作樣品照片:
實作照片圖示各元件 

 

 

 

 

範例程式 :  ( 各位同好,以下之程式,因為隨時會更迎或擴充功能而修改,請見諒,會於程式TITLE上標示更新日期。)

 

/*-----------------------------------------------

檔案名稱:LT-TEST_05.c @2019/01/28 AM 05:00

/*-----------------------------------------------
檔案名稱:LT-TEST_05.c @2019/01/31 PM 13:00
程式說明: 此程式在撰寫一個由MCU內部的 Timmer 0 計時器來實現時鐘,
  而重點在構思不使用 RTC DS1302 晶片下, 只利用計時器定時中斷的功能,
  並且在程式責寫時加入三個 CTx,CTy,CTz變數,來修正石英振盪晶體的頻率
  之差異,而且可以利用UART指令來設定修正的數值.
附註 : STC12C5608AD 單晶片MCU
@2019/01/24 STC12C5608AD, XTALL=22.1184MHZ,I2C-LCM
@2019/01/25 added BUZZ & ALARM command
@2019/01/26 added SW1~SW4 functions
@2019/01/26 ALARM array had 11 sets,
@2019/01/28 added 1 more ALARM array
@2019/01/31 added ALARM for the UART checksum error & UART command error
------------------------------------------------*/
#include "reg52.h"
#include "stdio.h"
#include "stdlib.h"
#include "intrins.h"
#include "string.h"
#include "delay.c"
#include "I2CPCF8574.c"  //I2C LCM 副程式

unsigned char* RC ="TEST_05 2019-01-30\r\n";
unsigned char* SPC="                    ";
#define XTAL  22118400 //XTAL 外部石英晶體 22.1184 Mhz
#define BAUDRATE 115200  //UART BAUDRATE 115200,8,N,1
#define UARTSIZE 12      //Uart buffer size
#define BS    0x08  //\b backspace code
#define WAIT  10
#define WAIT5  5
#define IEPROM   0x1ff9
typedef unsigned char BYTE;
typedef unsigned int WORD;
typedef unsigned long DWORD;

sbit CDS  = P3^2; //CDS sensor input
//sbit    = P3^3; //
//sbit LCM_SDA  = P3^4; //PCF8574AT SDA
//sbit LCM_SCL  = P3^5; //PCF8574AT SCL
sbit ALARM  = P3^7; //ALARM out

sbit OUT0  = P1^0; //
sbit OUT1  = P1^1; //
sbit OUT2  = P1^2; //
sbit OUT3  = P1^3; //
sbit OUT4  = P1^4; //
sbit OUT5  = P1^5; //
sbit OUT6  = P1^4; //
sbit OUT7  = P1^5; //

sbit LED_GRN =P2^7;
sbit LED_YEW =P2^6;
sbit LED_BLU =P2^5;
sbit LED_RED =P2^4;
sbit SW4  =P2^3;
sbit SW3  =P2^2;
sbit SW2  =P2^1;
sbit SW1  =P2^0;
/*------------------------------------------------
                整體變數宣告
------------------------------------------------*/
bit Turn_flag=0,SetFlag=0,busy=0,LCD_flag,DISP_flag=0,BUZZ=0,CDS_flag,CT_flag=0; 

unsigned char  temp[40];
unsigned char  UART_buf[UARTSIZE]; //UART RCV Buffer
unsigned char  ALM[12][2]= {{0,7},{5,7},{10,7},{15,7},{20,7},{25,7},{30,7},{35,7},{40,7},{45,7},{50,7},{55,7}}; //ALARM array
unsigned xdata AC_ms=0,Rcv_idx,AC_sec,AC_min,AC_hrs,AC_day,AC_mth,AC_yer,CTx,CTy,CTz;
unsigned xdata ALM_no;   //ALARM set no.
unsigned short CT,CDS_cnt;
/*------------------------------------------------
                  函數聲明
------------------------------------------------*/
void Init_Timer0(void);
void Init_Timer1(void);
void Uart_SendStr(unsigned char *value,unsigned int leng);
void Uart_PutChar(unsigned char dat);
void Uart_ISR_Handle(void);
void Uart_cmd(void);  // UART接收指令處理副程式
void Sent_Uart(void);  // UART送出訊息
void CHECK_year(void);  // 萬年曆檢查副程式
void LED_flash(void);  // LED閃爍
/*------------------------------------------------
                    主程式
------------------------------------------------*/
void main(void)
{ unsigned char i=0,k; //
 
 P1 = P2 = P3 =0xff; AUXR &= 0xbf;
 CT=58921;   // Timer 0 count down參數基值
 Init_Timer0();  // 計時器初始化
 Init_Timer1();  // UART baus rate
 LCD1602_Device_Init(XIO_ID); //啟動I2C LCD介面板與 1602液晶螢幕
 DelayMs(WAIT5);     //需延遲待待LCD螢幕內部運作
 CDS_cnt=0;DISP_flag=0;
 for(i=0;i<UARTSIZE;i++) { UART_buf[i]=0x00;LED_flash();} //
 SetFlag=0;      // 完成 I2C-LCM的初啟程式.清除旗號
 LCD1602_Write_Command(XIO_ID,0x01);  //清除螢幕內容, XIO_ID 需依 I2C PCF8574T(0x40) 或 PCF8574AT(0x70)
 DelayMs(WAIT5);
 AC_sec=AC_min=0,AC_hrs=7;AC_day=31;AC_mth=1;AC_yer=19;
 ET0=1;
 TR0=1;
 ES=1;
 EA=1;  //打開總中斷
//**********************************
 Uart_SendStr(RC,22);   //system start, sent the system information to UART
 DelayMs(WAIT5);
 sprintf(temp,"%2d/%d/%d ",(int)AC_yer,(int)AC_mth,(int)AC_day); // 顯示 年/月/日 時間;
 if(RI==0) { LCD1602_Write_String(XIO_ID,0,0,temp); }
 Rcv_idx=0;
 CDS_flag=0;
 while(1) //主程式
 { BUZZ=1;ALM_no=0;CTx=0;CTy=50;CTz=0;
  START:
  //**************************
  ES=1;LED_YEW=~BUZZ;
  
  if(SetFlag==1)  //UART HAD COMMAND RECIVED
  { DISP_flag=0;LED_BLU=0;
   k=0;
   //****** UART CHECKSUM
   for(i=0;i<10;i++) {k=k%256+(int)UART_buf[i];}      
   if((int)UART_buf[11] == k)   //比對CHECKSUM值
   { Uart_cmd(); }
   else { BUZZ=1;DelayMs(100);BUZZ=0;BUZZ=1;DelayMs(100);BUZZ=0; }
   //顯示接收到的 UART DATA
   if(DISP_flag==0)
   { sprintf(temp,"%02x%02x%02x%02x",(int)UART_buf[2],(int)UART_buf[3],(int)UART_buf[4],(int)UART_buf[5]);
    LCD1602_Write_String(XIO_ID,0,1,temp);
    sprintf(temp,"%02x %02x<%02x",(int)UART_buf[6],(int)UART_buf[11],(int)k);
    LCD1602_Write_String(XIO_ID,8,1,temp);
   }
      SetFlag=0;Rcv_idx=0;LED_BLU=1;
  }   
  //****************************
  if(Turn_flag==1 )   
  { LED_GRN=~LED_GRN;
   if(AC_min>=60 )    // 是否時間"分"已滿60分
   { AC_min=0;AC_hrs++; 
    if(CTz >= AC_hrs)  // 判斷是否需要補加"秒"數
    { AC_sec++; }
   }
   if(AC_hrs>=24 )    // 判斷是否已滿24小時
   { AC_hrs=0;AC_day++;
    CHECK_year();   // 萬年曆檢核    
   }
   if((AC_sec/3)>11 )   // 顯示 ALARM時間 lister
   { sprintf(temp,"%d/%d/%d ",(int)AC_yer,(int)AC_mth,(int)AC_day); } // 顯示 年/月/日 時間;
   else
   { LCD1602_Write_String(XIO_ID,0,0,"        ");
    sprintf(temp,"%d %d:%d ",(int)AC_sec/3,(int)ALM[AC_sec/3][1],(int)ALM[AC_sec/3][0]); }    
   if(RI==0) { LCD1602_Write_String(XIO_ID,0,0,temp); }   
   sprintf(temp,"%2d:%2d:%2d",(int)AC_hrs,(int)AC_min,(int)AC_sec); //顯示 CLOCK 時間  
   if(RI==0) { LCD1602_Write_String(XIO_ID,8,0,temp); }
   for(i=0;i<12;i++)   // vertify the ALARM set & current time
   { if(ALM[i][1]==AC_hrs && ALM[i][0]==AC_min && (AC_sec%2)==0) { BUZZ=1;goto AAA; } // 比對 ALARM時間是否吻合
    if(ALM[i][1]!=AC_hrs || ALM[i][0]!=AC_min ) { BUZZ=0; }    
   }
   AAA:
   if(CDS==0 && CDS_flag==0) { CDS_cnt++;LED_RED=0;CDS_flag=~CDS_flag;CT_flag=1;BUZZ=1;DelayMs(100); BUZZ=0;}  //check CDS detector ON
   else { if(CDS==1 && CDS_flag==1) { LED_RED=1;CDS_flag=~CDS_flag; } }   //check CDS detector OFF
   if(SW1==0 )   //check SW1 for display CDS_cnt, CTx, CTy, CTz data
   { while(SW1==0)
    { LED_flash();  }
    LCD1602_Write_String(XIO_ID,0,1,SPC);
    CT_flag=1;
    sprintf(temp,"CDS_cnt=%5d, CTx=%2x, CTy=%2x, CTz=%2x\r\n",(short)CDS_cnt,(int)CTx,(int)CTy,(int)CTz); //列印 CDS_cnt, CTx, CTy與 CTz 的數值   
    Uart_SendStr(temp,strlen(temp)); 
   }
   if(SW2==0)   // auto set the alarm by 5 minters
   { while(SW2==0)
    { LED_flash();  }
    for(i=0;i<12;i++)
    { ALM[i][1]=AC_hrs; }    
   }
   if(SW3==0)   // 設定5分鐘後蜂鳴器提醒
   { while(SW3==0)
    { LED_flash();  }
    ALM[0][1]=AC_hrs;
    ALM[0][0]=AC_min+5;
    if( ALM[0][0]>=60) {ALM[0][0]=ALM[0][0]-60;ALM[0][1]++; }
    if( ALM[0][1]>=24) {ALM[0][1]=ALM[0][1]-24; }
   }
   if(SW4==0)    // 設定10分鐘後蜂鳴器提醒
   { while(SW4==0)
    { LED_flash();  }
    ALM[0][1]=AC_hrs;
    ALM[0][0]=AC_min+10;
    if( ALM[0][0]>=60) {ALM[0][0]=ALM[0][0]-60;ALM[0][1]++; }
    if( ALM[0][1]>=24) {ALM[0][1]=ALM[0][1]-24; }
   }
   if(CT_flag==1)
   { LCD1602_Write_String(XIO_ID,0,1,SPC);
    sprintf(temp,"%5d ",(short)CDS_cnt);
    if(RI==0) {LCD1602_Write_String(XIO_ID,0,1,temp);}
    sprintf(temp,"%2d %2d %2d ",(int)CTx,(int)CTy,(int)CTz); //顯示 CDS_cnt, CTx, CTy與 CTz 的數值  
    if(RI==0) {LCD1602_Write_String(XIO_ID,7,1,temp);}
    CT_flag=0;
   }
   Turn_flag=0;   
  }       
  goto START; 
 }
}
//********************************
void LED_flash(void)
{ LED_RED=LED_GRN=LED_BLU=LED_YEW=0;DelayMs(100);
 LED_RED=LED_GRN=LED_BLU=LED_YEW=1;DelayMs(100);
}
void CHECK_year(void)
{ if((AC_mth==4 || AC_mth==6 || AC_mth==9 || AC_mth==11) && AC_day>=31) {AC_day=1;AC_mth++;goto C0;} //判斷有31日的月份
 else { if(AC_mth==2 && AC_day>=29 && (AC_yer%4)!=0) {AC_day=1;AC_mth++;goto C0;}    //判斷是否閏年之2月28日     
 else { if(AC_mth==2 && AC_day>=30 && (AC_yer%4)==0) {AC_day=1;AC_mth++;goto C0;}    //判斷是否閏年之2月29日
 else { if((AC_mth==1 || AC_mth==3 || AC_mth==5 || AC_mth==7 || AC_mth==8 || AC_mth==10 || AC_mth==12) && AC_day>=32) {AC_day=1;AC_mth++;goto C0;} } //判斷有30日的月份
 } }
 C0:
 if(AC_mth>=13) {AC_yer++;AC_mth=1;} // 判斷月份是否已滿12月
 return;
}
//******************
void Uart_cmd(void)

 switch((int)UART_buf[2])
 { case 0x80: //WIFI下傳時間.
     AC_hrs=(UART_buf[5]/16)*10+(UART_buf[5]%16); //16進制轉為10進制
     AC_min=(UART_buf[4]/16)*10+(UART_buf[4]%16);
     AC_sec=(UART_buf[3]/16)*10+(UART_buf[3]%16);
     break;
  case 0x81: //WIFI下傳日期
     AC_yer=(UART_buf[5]/16)*10+(UART_buf[5]%16); //16進制轉為10進制
     AC_mth=(UART_buf[4]/16)*10+(UART_buf[4]%16);
     AC_day=(UART_buf[3]/16)*10+(UART_buf[3]%16);
     sprintf(temp,"%2d/%d/%d ",(int)AC_yer,(int)AC_mth,(int)AC_day); // 顯示 年/月/日 時間;
     if(RI==0) { LCD1602_Write_String(XIO_ID,0,0,temp); }
     break;
  //*******************
  case 0x82: CTx=(UART_buf[3]/16)*10+(UART_buf[3]%16);  // CTx參數, 補正差
     CTy=(UART_buf[4]/16)*10+(UART_buf[4]%16);  // CTy參數, 扣負差
     CTz=(UART_buf[5]/16)*10+(UART_buf[5]%16);  // CTz參數, 補秒數
     CT_flag=1;
     break;
  case 0x83: CT_flag=1;
     DISP_flag=1;   //設定顯示時間修正參數值
     break;
  case 0x84:  ALM_no=UART_buf[3];  //ALARM 編組 NO
     if(ALM_no>=12) break;
     ALM[ALM_no][1]=(UART_buf[5]/16)*10+(UART_buf[5]%16);  // ALARM 小時
     ALM[ALM_no][0]=(UART_buf[4]/16)*10+(UART_buf[4]%16); // ALARM 分鐘
     break;
  default: { BUZZ=1;DelayMs(100);BUZZ=0;BUZZ=1;DelayMs(100);BUZZ=0; }break;
 } 
}
/*------------------------------------------------
  計數器0的初始化 for w/o RTC
------------------------------------------------*/
void Init_Timer0(void)    // 計數器0的初始化
{ TMOD |= 0x01;     // 選擇為計時器0模式,工作方式 1,僅用TR0打開啟動。
 AUXR &= ~0x80;
 TH0 = (65536-(CT+CTx-CTy))>>8; // 設置計時器初始值, 4ms
 TL0 = (65536-(CT+CTx-CTy));  //
 
 TR0 = 1;  //打開計時器      
}
/*------------------------------------------------
  計時器 TIMER0 中斷處理 for w/o RTC
------------------------------------------------*/
void TIMER0(void) interrupt 1 using 1
{ unsigned int i;
 TH0 = (65536-(CT+CTx-CTy))>>8; // 重設計時器初始值
 TL0 = (65536-(CT+CTx-CTy));  //
 i++;
 if(BUZZ==1) ALARM= ~ALARM;  // 如何ALARM旗號被啟動,就輸出 BUZZL信號
 else ALARM=0;
 if(i>=250)      // 確認是否滿足1秒鐘
 { AC_sec++;if(AC_sec>=60) {AC_sec=0;AC_min++;} 
  i=0;Turn_flag=1;   // 設定足秒旗號
 }
}
/*------------------------------------------------
  計數器 1 的初始化 115200,8,N,1 @ 1T / 22.1184Mhz
------------------------------------------------*/
void Init_Timer1(void)

 SCON = 0x5a;
 AUXR |= 0x40;
 TMOD = 0x20; // setting Timer1 to 8bits autoload
 TL1 = (256-(XTAL/32/BAUDRATE)); // @22.1184Mhz, for 115200bps
 TH1 = (256-(XTAL/32/BAUDRATE));
 TR1 = 1;   // Timer1 running enable
 ES = 1;   // serial port interrupt enable
 EA = 1;   // interrupt enable
}
/*------------------------------------------------
  發送一個位元組
------------------------------------------------*/
void Uart_PutChar(unsigned char dat)
{ while(busy);
 busy=1;
 SBUF = dat;
}
/*------------------------------------------------
  發送一個字串
------------------------------------------------*/
void Uart_SendStr(unsigned char *value,unsigned int leng)
{ while(leng>0) //
 { Uart_PutChar(*value);
  value++;
  leng--;
 } 
}
/*------------------------------------------------
  串口中斷程式
---------------------------------------------*/
void Uart_ISR_Handle (void) interrupt 4 
{ if(RI==1)
 { UART_buf[Rcv_idx]=SBUF;
  if(UART_buf[Rcv_idx-1]==0x20 && UART_buf[Rcv_idx]==0xa5) {Rcv_idx=1;UART_buf[0]=0x20;UART_buf[1]=0xa5;}
  Rcv_idx++;  
  if(Rcv_idx>=UARTSIZE) //連續接收16個字元資訊
  { Rcv_idx=0;
   SetFlag=1;   //接收完成,標誌旗號設定 1
  }  
  RI = 0;
 }
 if(TI==1)     //如果是發送標誌位元,清零
 { TI=0;
  busy=0;     //清除傳送旗號
 }
}
//*********************************

 

 

程式說明:      (在此主要說明2.0版擴充程式之功能說明)

CDS SENSOR檢知部份:

AAA:

if(CDS==0 && CDS_flag==0)      { CDS_cnt++;LED_RED=0;CDS_flag=~CDS_flag;CT_flag=1;    }           //check CDS detector ON

else {      if(CDS==1 && CDS_flag==1) {      LED_RED=1;CDS_flag=~CDS_flag;      }     }                 //check CDS detector OFF

        在線路中增加了CDS SENSOR光耦合電阻偵測電路,何以增加此電路是在配合其他專案,用來偵測LED燈具被點亮的次數做一記錄器,請看線路中的CDS SENSOR有一提升電阻100K歐姆,當有光線照至CDS SENSOR時,會讓CDS SENSOR的電阻值降至10K歐姆以下,如此就會將MCU P32的電位由高電位(HIGH準位)降至低電位(LOW準位),而這兩條程式就是在判斷CDS準位由HIGH轉至LOW,再由LOW轉至HIGH,這樣的一回合,才會將CDS_cnt增加一次計數。

按鍵#1顯示參數設定值功能說明:顯示CDS次數與CTx,CTy,CTz三個時間正負補償的設定值

if(SW1==0 )      //check SW1 for display CDS_cnt, CTx, CTy, CTz data

{      while(SW1==0)

      {      LED_RED=LED_GRN=LED_BLU=LED_YEW=0;DelayMs(100);

            LED_RED=LED_GRN=LED_BLU=LED_YEW=1;DelayMs(100);       }

      LCD1602_Write_String(XIO_ID,0,1,SPC);

      CT_flag=1;

      sprintf(temp,"CDS_cnt=%5d, CTx=%2x, CTy=%2x, CTz=%2x\r\n",(short)CDS_cnt,(int)CTx,(int)CTy,(int)CTz); //列印 CDS_cnt, CTx, CTy CTz 的數值              

      Uart_SendStr(temp,strlen(temp)); 

}

        此段程式是判別按鍵#1,當操作者壓下按鍵時,程式偵測到時,先會將4只LED以閃爍來表示已壓下按鍵 ,當操作者鬆開按鍵後,會設定CT_flag=1;,而接下去後面就會有顯示CDS次數與CTx,CTy,CTz三個時間正負補償的設定值,並同時由經由UART送出這止設定值。

按鍵#2自動設定5分鐘鬧鳴之功能說明:自動設定11組在所壓下按鍵的這一小時內每隔5分鐘,由(5,10...55)分鐘產生鬧鐘的功能

if(SW2==0)      // auto set the alarm by 5 minters

{      while(SW2==0)

      {      LED_RED=LED_GRN=LED_BLU=LED_YEW=0;DelayMs(100);

            LED_RED=LED_GRN=LED_BLU=LED_YEW=1;DelayMs(100);       }

      for(i=0;i<12;i++)

      {      ALM[i][1]=AC_hrs; }                        

}

        此程式一樣的在壓下按鍵後,一樣的由4只LED閃爍,然後鬆開後,就有一個迴路程式,將ALM[i][1]=AC_hrs; 鬧鐘矩陣任部設定為每隔5分鐘一次蜂鳴器動作一分鐘。

按鍵#3設定5分鐘鬧鈴(只有一次)功能說明:設定一次5分鐘後鬧鈴

if(SW3==0)      // 設定5分鐘後蜂鳴器提醒

{      while(SW3==0)

      {      LED_RED=LED_GRN=LED_BLU=LED_YEW=0;DelayMs(100);

            LED_RED=LED_GRN=LED_BLU=LED_YEW=1;DelayMs(100);       }

      ALM[0][1]=AC_hrs;

      ALM[0][0]=AC_min+5;

      if(      ALM[0][0]>=60) {ALM[0][0]=ALM[0][0]-60;ALM[0][1]++;  }

      if(      ALM[0][1]>=24) {ALM[0][1]=ALM[0][1]-24;    }

}

        一樣的在壓下按鍵後,一樣的由4只LED閃爍,然後鬆開後,將現在之時間加5分鐘,設定於鬧鐘矩陣的第0組,當然也需判斷是否有超過59分與24點之交換點。

 

按鍵#4設定01分鐘鬧鈴(只有一次)功能說明:設定一次10分鐘後鬧鈴

if(SW4==0)       // 設定10分鐘後蜂鳴器提醒

{      while(SW4==0)

      {      LED_RED=LED_GRN=LED_BLU=LED_YEW=0;DelayMs(100);

            LED_RED=LED_GRN=LED_BLU=LED_YEW=1;DelayMs(100);       }

      ALM[0][1]=AC_hrs;

      ALM[0][0]=AC_min+10;

      if(      ALM[0][0]>=60) {ALM[0][0]=ALM[0][0]-60;ALM[0][1]++;  }

      if(      ALM[0][1]>=24) {ALM[0][1]=ALM[0][1]-24;    }

}

 

        此功能與按鍵#3相同,只是設定的時間為10分鐘。

 

下面這段程式是當CT_flag=1時顯示CDS SENSOR被計數的次數與顯示 CT, CTx, CTy CTz 的數值。

 

if(CT_flag==1)

{      LCD1602_Write_String(XIO_ID,0,1,SPC);

      sprintf(temp,"%5d ",(short)CDS_cnt);

      if(RI==0)      {LCD1602_Write_String(XIO_ID,0,1,temp);}

      sprintf(temp,"%2d %2d %2d ",(int)CTx,(int)CTy,(int)CTz);     //顯示 CDS_cnt, CTx, CTy CTz 的數值      if(RI==0)      {LCD1602_Write_String(XIO_ID,7,1,temp);}

      CT_flag=0;

}

        顯示後會清除旗號,等待下次計數被再增加而旗號又被設定時,就會再度顯示。

 

        11組鬧鐘矩陣之程式說明 :

unsigned char  ALM[12][2]= {{0.7},{5,7},{10,7},{15,7},{20,7},{25,7},{30,7},{35,7},{40,7},{45,7},{50,7},{55,7}};      //ALARM array

        這部份是定義11組的鬧鐘設定矩陣 , 分別從第一組的ALM[0][0]= 5ALM[0][0]= 7,是7時5分為第一組的鬧鈴,之後每隔5分鐘一次,總共11組。

 

case 0x84:  ALM_no=UART_buf[3];         //ALARM 編組 NO

      if(ALM_no>=12) break;

      ALM[ALM_no][1]=(UART_buf[5]/16)*10+(UART_buf[5]%16);      // ALARM 小時

      ALM[ALM_no][0]=(UART_buf[4]/16)*10+(UART_buf[4]%16); // ALARM 分鐘

      break;

 

        case 0x84是指令集,當UART接收到一個 0x84指令時,會將以下之定義存入對應組別的史月3鐘矩陣列內,那原先開機之原始設定值將被更新,每次只能下達一個組別,請留意組別之值不得大於10,因為程式會判斷是否超過陣列數,如果超過時不會儲存,會直接跳過之。

其定義如下:

指令集頭碼(2byte) 0x20,0xa5

指令碼(1byte) 0x84

參數一(0x00:組別)        0x00

參數二(1byte:分)        0x00

參數三(1byte:時)        0x08

參數四~八(5byte預留)     0x00,0x00,0x00,

                                        0x00,0x00,

校閱總和碼(1byte) 就是從頭碼~參數八的11bytes的總和

舉例:指令0x84

20 a5 84 00 00 08 00 00 00 00 00 51

 

@2019/01/31 PM13:00

        增加兩處以下的程式,用來提醒如果有UART指令集收到時有CHECKSUM錯誤,或是所下達指令集指令有錯誤時,用蜂鳴聲加以提醒之。

if((int)UART_buf[11] == k)         //比對CHECKSUM

{      Uart_cmd(); }

else {      BUZZ=1;DelayMs(100);BUZZ=0;BUZZ=1;DelayMs(100);BUZZ=0;  }      //CHECKSUM ERROR

default:  {      BUZZ=1;DelayMs(100);BUZZ=0;BUZZ=1;DelayMs(100);BUZZ=0;      }break;

 

 

 

 

( 興趣嗜好電腦3C )
回應 推薦文章 列印 加入我的文摘
上一篇 回創作列表 下一篇

引用
引用網址:https://classic-blog.udn.com/article/trackback.jsp?uid=PYANG&aid=124365027