字體:小 中 大 | |
|
|
2016/01/12 21:03:02瀏覽1007|回應0|推薦0 | |
HC-05藍牙接收模組的電器遙控:89C52微處理器與HC-05藍牙模組 在本設計中,主要是利用HC-05藍牙模組負責接收由PC端的藍牙DONGLE所發送出來的指令碼,再經由HC-05藍牙模組的RXD與TXD信號送至STC89C52的UART PORT,之後再由STC89C52的內部程式解碼後去控制指定編碼的繼電器動作,程式中TIMER #0有撰寫一個時鐘程式,此乃利用MCU本身的時基構成的24小時計時程式,由於本身程式做來計時之用時,會有程式計數上的精準誤差的時序問題,所以需實測校正之。 程式中,在每次時基有秒數進位時,會設定一個顯示旗號,再由主程式送出時間字串給PC端,其格式為”@HH:MM:SS 00000\n”,最後的5位數是顯示當下已有多少次數接收到遙控的指令碼,此做為將來擴充功能之用。 指令碼範例#1:RELAY ON/OFF遙控 3108(hex) =>RELAY#1動作 3208(hex) =>RELAY#2動作 指令碼範例#2:時間設定指令碼 543039323008(hex) =>設定時間為09:20 第1個byte是0x54(“T”,時間設定指令碼) 第2個BYTE是0x30(小時的十位數之ascii碼) 第3個BYTE是0x39(小時的個位數之ascii碼) 第4個BYTE是0x32(分鐘的十位數之ascii碼) 第5個BYTE是0x30(分鐘的十位數之ascii碼) 第6個BYTE是0x08(尾碼0x08=”\n”) 例如可增加遙控電器的定時開啟或關閉功能,或是可調亮度的LED燈,或是如可控制的空調系統,窗簾系統。。等,亦或是火災,煙霧,二氧化碳濃度等警示元件,來經由PC端的智慧中央控制系統進行相關管理,因此後續可撰展的應用與功能,就再加以發揮了。 以下是撰寫的程式 /*----------------------------------------------- 檔案名稱:RS100_52.c @2016/01/12 89C52 & HC-05 & UART(96,N,1,1) 硬體接腳定義: 89C52 PIN 功能定義 BLUE_LED0 = P1^0; //LED0 BLUE INDICATOR(秒數指示燈) RED_LED1 = P2^7; //LED1 RED INDICATOR(指令接收指示燈) RXD = P3^0; //接至HC-05藍牙模組的TXD腳 TXD = P3^1; //接至HC-05藍牙模組的RXD腳 Out0 = P3^7; //RELAY #1(經由RELAY控制電器電源) Out1 = P3^6; //RELAY #2 Out2 = P3^5; //RELAY #3 Out3 = P3^4; //RELAY #4 軟體指令碼定義: 指令碼定為為兩個字元,第1個BYTE是欲控制的RELAY繼電器的編碼,第2個BYTE是0x08(等似於/n)為指令碼的結尾碼,切記任何指令碼的第二個位元必須是0x08,才能構成完整指令結構,當接收了第1次時,會令指定的繼電器ON,如再次接收到同一指令碼時,則會讓原先的繼電器ON轉態為OFF,如此達成電器之遙控的功能. 舉例如下: EX1: 指令碼0x31 0x08 =>指定繼電器#1動作. 於PC端可使用ACCESSPORT或SSCOM兩種UART傳送軟體來下達遙控指令碼. ------------------------------------------------*/ #include "reg52.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "delay.c" #include "1602.c" sbit BLUE_LED0 = P1^0; //LED0 BLUE INDICATOR sbit RED_LED1 = P2^7; //LED1 RED INDICATOR sbit Out0 = P3^7; //RELAY #1 sbit Out1 = P3^6; //RELAY #2 sbit Out2 = P3^5; //RELAY #3 sbit Out3 = P3^4; //RELAY #4 /*------------------------------------------------ 整體變數宣告 ------------------------------------------------*/ bit Tdisp_flag=0; bit SetFlag,busy; unsigned char temp[21]; //LCM Buffer unsigned xdata Rcv_buf[41]; //RS232 Rcv Buffer unsigned char AC_ms,AC_sec,AC_min,AC_hours; //時鐘變數 #define T25ms 46089 //時基25ms #define BS 0x08 //'\n' #define FOSC 22118000 //XTAL=22.1194MHZ #define BAUD 9600 //BAUD RATE=9800 #define RELOAD_COUNT 0xFA //12T 9600bps unsigned char Rcv_idx; unsigned short RCV_num; /*------------------------------------------------ 函數聲明 ------------------------------------------------*/ void Init_Timer0(void); //時鐘計數 void InitUART(void); //UART的初始化 96,8,N,1 void Uart_SendStr(unsigned char *s); //UART送出字串 void Uart_SendByte(unsigned char dat); //UART送出字元 /*------------------------------------------------ 主程式 ------------------------------------------------*/ void main(void) { unsigned char i; unsigned char cmd; Init_Timer0(); //計時器初始化 InitUART(); LCD_Init(); //LCM初始化 DelayMs(10); //延遲LCM LCD_Clear(); //清除LCM畫面 SetFlag=0; P3=0xff; P2=0xff; P1=0xff; BLUE_LED0=1; RED_LED1=1; EA=1; //interupt enable ES=1; for(i=0;i<41;i++) span="" style="mso-tab-count: 1;" data-mce-style="mso-tab-count: 1;"> {Rcv_buf[i]=0x20;} Uart_SendStr("STC89C52+HC_05\r\n Uart1 96,N.1,1 Test !\r\n"); //*********************** ET1=0; TR0=1; ET0=1; //*********************** RCV_num=0; while(1) //主程式 { START0: //*********************** if(Tdisp_flag==1) //判斷顯示旗號 { BLUE_LED0=0; //秒數指示燈 ON sprintf(temp,"@ %02d:%02d:%02d %05d\b",(int)AC_hours,(int)AC_min,(int)AC_sec,(short)RCV_num); LCD_Write_String(0,0,temp); //顯示時鐘於LCD模組 if(!RI) { Uart_SendStr(temp); //送出時間值至UART } Tdisp_flag=0; //清除顯示旗號 BLUE_LED0=1; //秒數指示燈OFF } if (SetFlag==1) //判斷是否有藍芽指令接收 { ES=0;RED_LED1=0; //DISABLE interrupt,同時點亮接收指示燈 RCV_num++; //接收指令次數加一 sprintf(temp,"%1c%1c%1c%1c",(char)Rcv_buf[0],(char)Rcv_buf[1]); LCD_Write_String(0,1,temp); //顯示接收之指令於LCD模組 RED_LED1=1; //接收指示燈 OFF cmd=Rcv_buf[0]; //取得指令碼 switch(cmd) { case 0x31: Out0=~Out0;break; //指令0x31:RELAY#1動作 case 0x32: Out1=~Out1;break; //指令0x32:RELAY#2動作 case 0x33: Out2=~Out2;break; //指令0x33:RELAY#3動作 case 0x34: Out3=~Out3;break; //指令0x34:RELAY#4動作 case 0x54: AC_hours=(int)(Rcv_buf[1]-0x30)*10+(int)(Rcv_buf[2]-0x30);//指令"T":設定時間參數 AC_min=(int)(Rcv_buf[3]-0x30)*10+(int)(Rcv_buf[4]-0x30); AC_sec=0; break; default:break; } DelayMs(10); Rcv_idx=0; //接收緩衝器指標歸 0 SetFlag=0; //清除接收旗號 ES=1; //ENABLE interrupt } goto START0; } } /*------------------------------------------------ 計數器 0 的初始化 ------------------------------------------------*/ void Init_Timer0(void) //計數器0的初始化 { TMOD = (TMOD & 0xF0)|0x01; //設定 Timer 0 to MODE #1 auto load TH0=(65536-T25ms)/256; //時基 25ms TL0=(65536-T25ms)%256; ET0=1; //打開中斷 TR0=1; //啟動 TIMER 0 } /*------------------------------------------------ 計時器 TIMER0 中斷處理 ------------------------------------------------*/ void TIMER0(void) interrupt 1 using 1 { TH0=(65536-T25ms)/256; //設定 TIMER 0 為時鐘時基25ms TL0=(65536-T25ms)%256; //reload值 TF0=0; AC_ms++; if(AC_ms>=40) //20ms x 40次 = 1秒 { AC_ms=0;AC_sec++;Tdisp_flag=1; //秒數增加 1,同時時基歸 0.並設定顯示旗號為 1 if(AC_sec>=60) //判斷是否已滿 60秒 { AC_sec=0;AC_min++; //分鐘數增加 1,同時秒數歸 0 if(AC_min>=60) //判斷是否已滿 1分鐘 { AC_min=0;AC_hours++; //已滿 1 小時,分鐘數歸 0 if(AC_hours>23) AC_hours=0; //判斷是否已滿24小時, 小時數歸 0 } } } } /*------------------------------------------------ UART #1 初始化 0xfa 9600,8,N,1 @XTAL=22.1194Mhz ------------------------------------------------*/ void InitUART (void) { TMOD = (TMOD & 0x0F)|0x20; // 設定 Timer 1 to MODE #2 auto load SCON = 0x50; // 設定 Serial Mode 1 TH1 = 0xfa; // TH1:重裝值 9600 串列傳輸速率 晶振 22.118MHz TL1 = 0xfa; TR1 = 1; // TR1: timer 1 打開 EA = 1; // 打開總中斷 ES = 1; // 打開串口中斷 } /*------------------------------------------------ UART發送一個位元組 ------------------------------------------------*/ void Uart_SendByte(char dat) { while(busy); //判斷傳送旗號是否結束 busy=1; //設定傳送旗號 SBUF=dat; //送出字元 } /*------------------------------------------------ UART發送一個字串 ------------------------------------------------*/ void Uart_SendStr(char *s) { while(*s!=BS) // \b 表示字串結束標誌,通過檢測是否字串末尾 { Uart_SendByte(*s++); } } /*------------------------------------------------ UART 1 中斷程式 (P3^0 & P3^1) ------------------------------------------------*/ void UART_SER (void) interrupt 4 //串列中斷服務程式 { if(RI) //判斷是接收中斷產生 { Rcv_buf[Rcv_idx]=SBUF; //讀入緩衝區的值 Rcv_idx++; if(Rcv_buf[Rcv_idx-1]==BS || Rcv_idx>21) //連續接收16個字元資訊 { Rcv_idx=0; SetFlag=1; //接收完成標誌位置1 ES=0; } RI=0; //標誌位元清零 } if(TI==1) //如果是發送標誌位元,清零 { TI=0; busy=0; //清除傳送旗號 } }
|
|
( 興趣嗜好|電腦3C ) |