鬧鐘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來做為補秒之用 .
線路圖 :
實作樣品照片:
範例程式 : ( 各位同好,以下之程式,因為隨時會更迎或擴充功能而修改,請見諒,會於程式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]= 5與ALM[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;