在不久的将来,我将成为通过UART进行通信的HM-TRP无线电模块的所有者。我将使用AT89C4051微控制器作为HM-TRP和使用AT89S52的更大电路之间的桥梁,这样一切都可以通信。 HM-TRP将使用9600bps波特率与AT89C4051进行通信,该芯片将使用22.1184Mhz晶体。
由于我有两个设备可以连接的GPIO引脚有限,我试图制作一个可以读取一个字节的例程,并一次向一个半字节写一个字节到一个半字节。我指定了两个缓冲区的空间。一个用于传输到模块的数据,另一个用于从模块接收数据。
我想改进这段代码,这样我就不会破坏其他东西使用的内存地址,例如SFR和堆栈指针数据。此外,HM-TRP模块声称是半双工的。
我试图让它尽可能地异步,以便在桥接器(AT89C4051)停止直到HM-TRP完成发送字节时,其他处理器不必停止。
我可以做些什么来改善这个?还是我在这里过度思考?
;uC to radio
DAT equ P1 ;Data channel (only bits 4-7 available)
NIB equ P3.7 ;Nibble Number
RW equ P3.5 ;1=Read, 0=Write
EXEC equ P3.4 ;Execute
R_EN equ P3.3 ;HM-TRP enable
R_CFG equ P3.2 ;HM-TRP config
BUFEND equ 10h ;receive buffer end
BUFENDT equ 3Fh ;transmit buffer end
NIBNO bit 7Fh ;Internal nibble #
IEXEC bit 7Eh ;Internal execution state
;setup everything
setb IEXEC
setb NIBNO
setb R_EN
setb RS0 ;R0-R7 addresses = high to not corrupt buffers
setb RS1
mov P1,#0FFh ;reset ports
mov P3,#0FFh
mov R0,#BUFEND
mov R1,#BUFENDT
mov R2,#0h ;R2=remaining transmit characters
mov R3,#0h ;R3=# received characters
mov SP,#50h ;Get SP out of our space
mov PCON,#80h ;use high-speed UART
mov TH1,#0F4h ;9.6kbps
mov SCON,#50h ;serial mode 1
mov TMOD,#22h ;auto reload for timers
acall delay
clr R_EN ;Enable HM-TRP radio
setb TR1 ;Start hardware UART
lcall setup
main:
;Async routines
;Check for received byte and process if any
jbc RI,recvok
rtx:
;Check for transmit byte and process if any
jbc TI,xmitok
txx:
;Do user function and repeat
ajmp ufunc
;executed when hardware serial port indicates character transmitted
xmitok:
mov SBUF,@R1 ;Pass buffered byte to serial
dec R1 ;adjust pointer
djnz R2,txx ;lower count
mov R1,#BUFENDT ;when count is 0, reset buffer pointer
ajmp txx ;back to main routine
;executed when hardware serial port indicates character received
recvok:
mov @R0,SBUF ;Store data into buffer right away
inc R3 ;increment character count
djnz R0,rtx ;start buffer at beginning when it reaches end
mov R0,#BUFEND
ajmp rtx ;back to main routine
ufunc:
;See state of EXEC gpio pin
jnb EXEC,rexec
;pin value needs to be high at first
clr IEXEC
rexec:
jb EXEC,noexec
jb IEXEC,noexec
;only enter if pin was high before set low
jb RW,d_rd
;Here, RW pin = low so Read from HM-TRP is executed
jb NIB,rnibid
jb NIBNO,rnibid
;NIB pin = low so we want 1st nibble
mov A,R3
jz skipread
;Only get nibble if at least a byte exists in cache
mov A,@R0 ;load byte from cache
inc R0 ;advance pointer
dec R3 ;lower byte count
mov R5,A ;save original byte
swap A ;prepare nibble
anl A,#0F0h ;we want 4 MSB
mov DAT,A ;send out 1st nibble
setb NIBNO ;prevent hold down of pin from executing this function forever
skipread:
rnibid:
jnb NIB,rnibid2
jnb NIBNO,rnibid2
;We want other nibble
mov A,R5 ;Get saved byte
anl A,#0F0h ;But strip lower 4-bits
mov DAT,A ;Send out 2nd nibble
clr NIBNO
rnibid2:
d_rd:
jnb RW,d_wr
jb NIB,nibid
jb NIBNO,nibid
mov A,DAT ;Read in 1st nibble
swap A ;and make it our low nibble
anl A,#0Fh ;strip the high part
mov R6,A ;and save it
setb NIBNO ;prevent hold down of pin from executing this function forever
nibid:
jnb NIB,nibid2
jnb NIBNO,nibid2
mov A,DAT ;Read in 2nd nibble
anl A,#0F0h ;Strip low part
orl A,R6 ;put both parts together to form byte
clr NIBNO
mov @R1,A ;Store byte in transmit buffer
dec R1 ;adjust pointer
inc R2 ;increment number of transmit characters
nibid2:
d_wr:
setb IEXEC ;prevent hold down of EXEC pin from executing things too much
noexec:
ajmp main
setup:
; Setup radio card
clr R_CFG
acall delay
mov R2,#2h ;2 0FFh's = end.
mov DPTR,#startconfig
configsu:
clr A
movc A,@A+DPTR ;Read byte from code memory
inc DPTR
inc A
jz novalc ;...and don't send it to radio if it's 0FFh
dec A
mov R2,#2h ;byte isn't FFh, so restore chances
clr TI
mov SBUF,A ;Send byte to radio
jnb TI,$ ;and stall until its sent
sjmp configsu
novalc:
;Strike 1+. One more FFh and its over.
acall delay
djnz R2,configsu
;finish up
setb R_CFG ;switch radio to data mode
acall delay
mov R2,#0h
clr TI
ret
delay:
djnz R7,$ ;Delay so radio module can accept setting
ret
;These are codes that get programmed into HM-TRP to get it up and running properly
startconfig:
mhz915:
db 0AAh,0FAh,0D2h,036h,089h,0CAh,0C0h,0FFh
mhz433:
db 0AAh,0FAh,0D2h,019h,0DEh,050h,080h,0FFh
bps9600:
db 0AAh,0FAh,0C3h,000h,000h,025h,080h,0FFh
ubps9600:
db 0AAh,0FAh,01Eh,000h,000h,025h,080h,0FFh
bw105: ;default receive bandwidth: 105khz
db 0AAh,0FAh,0B4h,000h,069h,0FFh
dev35: ;default deviation: 35khz
db 0AAh,0FAh,0A5h,023h,0FFh
xmitdbm: ;xmit power 20dbm max
db 0AAh,0FAh,096h,007h,0FFh
endofconfig:
db 0FFh,0FFh,0FFh,0FFh