最近在玩8051 Assembly 寫了一個由PC藉由RS232寫入指令給實習板,實習板再將指令轉成I2C指令與設備溝通,設備傳回值給實習板,實習板再藉由RS232回傳給PC.PC端RS232是用C#寫的.擇日整理後再放進來.
SCL BIT P2.6
SDA BIT P2.7
ACK BIT 2FH.1
KBD_CR EQU 0x0D
KBD_LF EQU 0x0A
RXBUF EQU 0X20
TXBUF EQU 0X40
RXLEN EQU 0X61
TXLEN EQU 0X62
NUM2 EQU 0X63
ORG 0000H
JMP MAIN
ORG 0023H
JMP UART_INT
ORG 0030H
MAIN:
MOV SP,#65H
;===============Timer1==================
MOV TMOD,#00100000B ;TIMER1 MODE2
MOV TH1,#243 ;BAUD RATE 4800, OSC 12MHz
MOV TL1,#243
SETB TR1 ;POLLING MODE
CLR 2FH.0 ;2fh.0代表資料以完成接收的旗標
;
MOV PCON,#080H
MOV SCON,#01010000B ;(SM0,SM1)=(0,1),SM2=0,REN=1
MOV IP,#00010000B
MOV IE,#10010000B
MOV R0,#RXBUF ;R0=>當20H 間接定址的暫存器 RX
ACALL SENDREADY
LOOP:
CJNE A,#KBD_CR,L0
ACALL WRITE_DATA
ACALL READ_DATA
//// //ACALL PRESEND
ACALL SENDTX
//// //ACALL SENDREADY
// JMP SKIP
L0: //JB 2FH.0,SEND
JMP SKIP
SEND:
MOV SBUF,A//#40H
JNB TI,$ ; 等待完成傳送 TI=0 ->1
CLR TI
CLR 2FH.0
JMP SKIP
PRESEND:
MOV A,#KBD_LF
MOV SBUF,A
JNB TI,$ ; 等待完成傳送 TI=0 ->1
CLR TI
RET
SENDRX:
MOV R1,#00
S2:
MOV A,@R0
MOV SBUF, A ;逐一將字碼寫入SBUF
JNB TI,$ ; 等待完成傳送 TI=0 ->1
CLR TI
INC R0
INC R1 ; 指向下一個字碼
MOV A,R1
CJNE A,RXLEN,S2
MOV RXLEN,#00
CLR 2FH.0
RET
SENDTX:
MOV R3,#00
MOV R1,#TXBUF
TT2:
MOV A,@R1
MOV SBUF, A ;逐一將字碼寫入SBUF
JNB TI,$ ; 等待完成傳送 TI=0 ->1
CLR TI
INC R1
INC R3 ; 指向下一個字碼
MOV A,R3
CJNE A,TXLEN,TT2
MOV TXLEN,#00
//CLR 2FH.0
RET
SEND2:
MOV SBUF,A//#40H
JB TI,$
RET
SENDREADY:
MOV R3,#0
MOV DPTR,#UARTREADY ; 取得字串存放位址
SREADY:
MOV A,R3
MOVC A,@A+DPTR ; 由字串中取出字碼
MOV SBUF, A ;逐一將字碼寫入SBUF
JNB TI,$ ; 等待完成傳送 TI=0 ->1
CLR TI
INC R3 ; 指向下一個字碼
CJNE R3,#2,SREADY
CLR 2FH.0
RET
SKIP:
JMP LOOP
;
UART_INT:
JBC RI,REC_INT
//CLR TI
JMP UART_EXIT
REC_INT:
//CLR RI
MOV R1,RXLEN ;Read RX len
MOV A,R1
ADD A,R0 ;Get RXBUF location
INC R1 ;RX len ++
MOV RXLEN,R1 ;save RX len
MOV R1,A ;R1=RXBUF localtion
MOV A,SBUF
MOV @R1,A ;Save data to RXBUF localtion
SETB 2FH.0
UART_EXIT:
RETI
;
WRITE_DATA:
MOV R3,RXLEN
DEC R3
ACALL STARTC
MOV R1,#RXBUF
WRDA: MOV A,@R1
ACALL WRBYTE ;SENDI2C
ACALL CACK
JNB ACK,WRITE_DATA
INC R1
DJNZ R3,WRDA
RETWRN:
ACALL STOP
RET
;
READ_DATA:
MOV R3,#16 ;READ LENGTH
ACALL STARTC
MOV R1,#RXBUF
MOV A,#0XE7;A,@R1
;INC A
ACALL WRBYTE
ACALL CACK
JNB ACK,READ_DATA
MOV RXLEN,#00
MOV R1,#TXBUF
MOV R4,#01
RON1: ACALL RDBYTE
//MOV A,R2
MOV @R1,A
DJNZ R3,SACK
ACALL MNACK
RETRDN:
ACALL STOP
MOV TXLEN,R4
RET
SACK: ACALL MACK
INC R1
INC R4
SJMP RON1
;
;============I2C START===============
STARTC:
SETB SDA
ACALL D2T
SETB SCL
ACALL D2T
CLR SDA
ACALL D2T
CLR SCL ;後面補的
ACALL D2T ;後面補的
RET
;============I2C STOP=================
STOP:
CLR SDA
ACALL D2T
SETB SCL
ACALL D2T
SETB SDA
ACALL D2T
RET
;============I2C CHECK ACK============ ;後面補的
CACK:
SETB SDA
ACALL D3T
SETB SCL
CLR ACK
ACALL D3T
MOV C,SDA
JC CEND
SETB ACK
CEND: NOP
CLR SCL
ACALL D2T
RET
;===========I2C MAKE ACK============== ;後面補的
MACK:
CLR SDA
ACALL D2T
SETB SCL
ACALL D3T
CLR SCL
ACALL D2T
RET
;===========I2C MAKE NACK============== ;後面補的
MNACK:
SETB SDA
ACALL D2T
SETB SCL
ACALL D3T
CLR SCL
ACALL D2T
RET
;============I2C WRITE================ ;後面補的
WRBYTE:
MOV NUM2,#8
WLP: RLC A
JC WRI
SJMP WRO
WLP1: DJNZ NUM2,WLP
NOP
RET
WRI: SETB SDA
ACALL D3T
SETB SCL
ACALL D3T
CLR SCL
SJMP WLP1
WRO: CLR SDA
ACALL D3T
SETB SCL
ACALL D3T
CLR SCL
SJMP WLP1
;============I2C READ================== ;後面補的
RDBYTE:
MOV NUM2,#08H
RLP: SETB SDA
ACALL D2T
SETB SCL
ACALL D3T
//MOV A,R2
MOV C,SDA
CLR SCL
RLC A
//MOV R2,A
ACALL D3T
DJNZ NUM2,RLP
RET
;=======================================
NACK: SETB SDA
CLR SCL
ACALL D3T
SETB SCL
ACALL D3T
CLR SCL
ACALL D3T
RET
;
D3T: NOP
NOP
NOP
NOP
NOP
NOP
RET
;
D2T: NOP
NOP
NOP
NOP
RET
;
DELAY:
MOV R7,200
DL0: MOV R6,250
DL1: DJNZ R7,$
DJNZ R6,DL0
RET
UARTREADY:
DB KBD_LF,">"
END