警告與免責聲明:
如果您沒有任何基本電子知識,請不要嘗試這篇教學。作者對本教學所導致的任何損害概不負責。嘗試這篇教學風險自負。
底下將使用一顆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
警告與免責聲明:
如果您沒有任何基本電子知識,請不要嘗試這篇教學。作者對本教學所導致的任何損害概不負責。嘗試這篇教學風險自負。
沒有留言:
不接受新意見。