2017年5月19日 星期五

8051 - Bluetooth Remote Shutter (繁)

警告與免責聲明:

如果您沒有任何基本電子知識,請不要嘗試這篇教學。作者對本教學所導致的任何損害概不負責。嘗試這篇教學風險自負。

底下將使用一顆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

警告與免責聲明:

如果您沒有任何基本電子知識,請不要嘗試這篇教學。作者對本教學所導致的任何損害概不負責。嘗試這篇教學風險自負。

沒有留言: