警告與免責聲明:
如果您沒有任何基本電子知識,請不要嘗試這篇教學。作者對本教學所導致的任何損害概不負責。嘗試這篇教學風險自負。
底下將使用一顆STC89C52RC單晶片搭配一個HC-06 UART介面藍牙模組來打造一個藍牙遠端快門(Remote Shutter)。遠端快門要搭配Bluetooth Remote Toy APP才能使用,此APP是我開發,你可以到Google play store下載。
當APP連線到遠端快門,APP會傳送識別指令'W'給遠端快門。當遠端快門收到這個指令,它必須回它的ID 'I'給APP。否則APP會認為遠端裝置是這個應用程式的相機快門,而不是你自己DIY的遠端快門。針對相機快門與遠端快門,相機的初始化是不一樣。電路圖如下,當按下Z0 Snap按鍵時,會傳送一個byte的'T'字元給APP,此時綠色的LED燈會開始閃爍。APP收到'T'字元後,會進行拍照,等拍照完成後,APP會回一個byte的'D'字元給遠端快門。如果遠端快門收到'D'字元,LED燈就會停止閃爍。如果遠端快門沒有收到'D'字元,等10秒timeout掉就會停止閃爍。當按下Z1 Flash mode按鍵時,會傳送一個byte的'M'字元給APP。APP收到'M'字元後,會切換到下一個Falsh mode。你也可以考慮使用其它單晶片開發,像Arduino等等。
電路圖
在電路圖上有兩個按鍵,分別是Snap按鍵與Flash mode按鍵,還有一顆LED燈用來指示拍照。一個HC-06藍牙模組用來傳送指令給Android手機與接收手機的的指令。一顆STC89C52RC單晶片用來控制整個系統。
底下是我完成的成品。
底下是用組合語言寫的,你可用C語言改寫。8051的組合語言沒有很難,語法也沒有很多,剛開始學8051可以考慮用組合語言撰寫,這樣會比較了解8051,但如果程式碼越來越大,又考慮可讀性與移植性,建議用C語言撰寫。至於8051的開發環境,可以參考這裡。
程式碼
COUNT EQU 30H SNAP BIT 20H ORG 00H AJMP START ORG 03H ;Int0 interrupt vector address AJMP INT0_ROUTINE ORG 13H ;Int1 interrupt vector address AJMP INT1_ROUTINE ORG 23H ;Serial interrupt vector address AJMP SERIAL_ROUTINE ORG 2BH ;Timer2 interrupt vector address AJMP TIMER2_ROUTINE START: ACALL INIT ACALL INIT_INT0 ACALL INIT_INT1 ACALL INIT_SERIAL ACALL INIT_TIMER2 LOOP: ACALL DELAY JNB SNAP, NO_FLASH JNB P1.0, LED_OFF CLR P1.0 AJMP LOOP LED_OFF: SETB P1.0 NO_FLASH: AJMP LOOP ;-------------------- ; Delay ;-------------------- DELAY: MOV R6, #255 DLY1: MOV R7, #255 DLY2: DJNZ R7, DLY2 DJNZ R6, DLY1 RET ;-------------------- ; Initialize variables ;-------------------- INIT: MOV SP, #60H MOV P1, #11111110B MOV R5, #15 MOV COUNT, #0 CLR SNAP RET ;-------------------- ; Initialize int0 ;-------------------- INIT_INT0: SETB IT0 ;edge triggered SETB EX0 ;Enable int0 interrupt SETB PX0 ;High interrupt priority RET ;-------------------- ; Initialize int1 ;-------------------- INIT_INT1: SETB IT1 ;edge triggered SETB EX1 ;Enable int0 interrupt SETB PX1 ;High interrupt priority RET ;-------------------- ; Initialize serial ; ; TCON Register: ; 7 6 5 4 3 2 1 0 ; TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0 ; ; TMOD Register: ; 7 6 5 4 3 2 1 0 ; GATE1 C/T1# M11 M01 GATE0 C/T0# M10 M00 ; ; SCON Register: ; 7 6 5 4 3 2 1 0 ; SM0 SM1 SM2 REN TB8 RB8 TI RI ;-------------------- INIT_SERIAL: MOV SCON, #50H ;Mode 1: 8-bit UART MOV TMOD, #20H ;Timer and reload mode MOV TH1, #0FDH ;Baud rate 9600bps MOV TL0, #0FDH ;Baud rate 9600bps SETB PS ;High interrupt priority SETB ES ;Enable serial interrupt SETB TR1 ;Timer1 runs RET ;--------------------------------------------------- ; Initialize timer2 ; ; T2CON Register: ; 7 6 5 4 3 2 1 0 ; TF2 EXF2 RCLK TCLK EXEN2 TR2 C/T2 CP/RL2 ; ; 1 second = 11.0592MHZ / 12 = 921600 = 61440 * 15 ; TH2 = (65536-61440)/256 = 16 = 10H ; TL2 = (65536-61440)%256 = 0 = 00H ; ; IE Register: ; 7 6 5 4 3 2 1 0 ; EA - ET2 ES ET1 EX1 ET0 EX0 ;--------------------------------------------------- INIT_TIMER2: CLR EXF2 ;Reset flag CLR TCLK ;Disable baud rate generator CLR RCLK ;Disable baud rate generator CLR EXEN2 ;Ignore events on T2EX MOV TH2, #10H MOV RCAP2H, #10H MOV TL2, #00H MOV RCAP2L, #00H CLR CT2 ;Timer mode CLR CPRL2 ;Auto-reload mode CLR PT2 ;Low interrupt priority SETB ET2 ;Enable timer2 interrupt SETB EA ;Global interrupts enable SETB TR2 ;Timer2 run RET ;--------------------------------- ; Snap timeout ;--------------------------------- START_SNAP_TIMEOUT: JNB SNAP, NO_COUNT MOV A, COUNT INC A ;10 seconds timeout for snapping MOV COUNT, A CJNE A, #10, NO_COUNT CLR SNAP MOV COUNT, #0 CLR P1.0 NO_COUNT: RET ;--------------------------------- ; Int0 interrupt service routine ;--------------------------------- INT0_ROUTINE: JB SNAP, IGNORE_SNAP SETB SNAP ;Indicate that we are taking a picture MOV COUNT, #0 MOV SBUF, #84 ;Send value 84('T') to serial port JNB TI, $ ;Pause until the TI bit is set IGNORE_SNAP: RETI ;--------------------------------- ; Int1 interrupt service routine ;--------------------------------- INT1_ROUTINE: MOV SBUF, #77 ;Send value 77('M') to serial port JNB TI, $ ;Pause until the TI bit is set RETI ;----------------------------------- ; Timer2 interrupt service routine ;----------------------------------- TIMER2_ROUTINE: PUSH ACC ;Save ACC register on the stack DJNZ R5, CONTINUE ;Continue timer if it is less then 1 second ACALL START_SNAP_TIMEOUT MOV R5, #15 ;Recount 1 second CONTINUE: CLR TF2 ;Reset interrupt flag POP ACC ;Restore ACC RETI ;---------------------------------------- ; Serial port interrupt service routine ;---------------------------------------- SERIAL_ROUTINE: PUSH ACC JB TI, IGNORE MOV A, SBUF CJNE A, #68, ID_CHK ;Receive vlaue 68('D') from serial port CLR SNAP MOV COUNT, #0 CLR P1.0 ID_CHK: CJNE A, #87, IGNORE ;Receive vlaue 87('W') from serial port MOV SBUF, #73 ;Send value 73('I') to serial port JNB TI, $ ;Pause until the TI bit is set JMP NO_CLEAR_TI IGNORE: CLR TI NO_CLEAR_TI: CLR RI POP ACC RETI END
Demo
警告與免責聲明:
如果您沒有任何基本電子知識,請不要嘗試這篇教學。作者對本教學所導致的任何損害概不負責。嘗試這篇教學風險自負。
沒有留言:
不接受新意見。