我试图实现类似于SPI(串行编程接口)的功能,以便在两个迷你微控制器(芯片#AT89c2051)之间进行通信。由于每个微控制器已经将板载串行端口用于其他目的,因此我作为通信线路可用的总数为10位。 8个是地址位,另外两个是控制位。由于晶体价格和与计算机的兼容性,每个微控制器以不同的速度(18.432Mhz和20Mhz)运行。
我的代码可以部分工作但不正确。
以下是整个程序中使用的常量:
NUMBYTESIO EQU 10h ;set transfer bytes to 16
TEMP EQU 30h ;temporary pointer for register saves
DATAPTR EQU 31h ;data pointer for commands
RINT EQU P3.2 ;INTerrupt to tell slave that master is ready
RACK EQU P3.3 ;Remote busy INTerrupt to tell master that slave is busy
这是在向主服务器发出请求时以18.432Mhz速度在主服务器上执行的代码:
request: ;start request from slow microcontroller
mov R0,#DATAPTR ;set R0 to data pointer (address 30h)
mov R7,#0h ;clear counter register
dorequest:
mov P1,@R0 ;read local register data from memory location and store in the outgoing 8 bits
clr RINT ;clear request interrupt to let remote know data is ready
jb RACK,$ ;wait till remote acknowledges data
mov P1,#0FFh ;set data line high to enable remote to send data
setb RINT ;set request interrupt to let remote know we're ready for data
jnb RACK,$ ;wait till remote understands were ready
mov @R0,P1 ;overwrite memory location with new data
inc R0 ;advance memory location pointer
inc R7 ;add 1 to # of bytes processed
cjne R7,#NUMBYTESIO,dorequest ;if # bytes processed < 16, repeat process
ret ;end the request
这是奴隶处理来自主服务器的请求的方式,但最后一行是reti而不是ret,因为remotereq是从主服务器触发的中断处理程序中调用的:
remotereq: ;fast micro received request from slow micro and RINT is low
mov P1,#0FFh ;sanity check: make data line high to let remote send data
;next 5 lines save R1...R7 registers onto stack
mov TEMP,#7h
saveb:
push TEMP
dec TEMP
jnz saveb
mov R7,#0h
rrr: ;start reception of request
mov P1,#0FFh ;make data line high
jb RINT,$ ;wait until remote has data (it will set this line low)
mov A,P1 ;get the data
clr RACK ;and send an acknowledgement to remote
jnb RINT,$ ;wait until remote is ready for data
lcall doradcmds ;process byte
mov P1,A ;take result of the byte as data to send back
setb RACK ;send acknowledgement to remote to let it know data is ready
mov R6,#0FFh ;start data timeout of 255 clock cycles (about 100-ish microseconds)
djnz R6,$
inc R7 ;increment counter
cjne R7,#NUMBYTESIO,rrr ;repeat process for all remaining bytes
mov P1,#0FFh ;set data line high to avoid contention
mov TEMP,#7h
saveb2:
pop TEMP
dec TEMP
jnz saveb2
reti
这是奴隶执行所有命令处理的地方:
;PROC COMMANDS
; R7=LIVE byte#, A=live data, R6=bad
doradcmds:
cjne R7,#0h,majorcmd ;see if byte # is the first
mov R2,A ;byte is first. store command in R2
mov A,#40h ;returned result starts with @
ret
majorcmd:
mov TEMP,R7 ;copy current byte #...
mov R3,TEMP ;... into R3
cjne R2,#A5h,notest ;run test command if 1st byte is A5h
djnz R3,notestp1
mov R5,A ;store first command parameter into R5
mov A,#40h ;return an @ in result
ret
notestp1:
djnz R3,notestp2
mov R4,A ;store second parameter into R4
mov A,#40h ;return an @ in result (not working)
ret
notestp2:
djnz R3,notesto1
mov A,R4 ;return value of R4 for 3rd byte
ret
notesto1:
djnz R3,notesto2
mov A,R5 ;return value of R5 for 4th byte
ret
notesto2:
notest:
ret
这就是主人如何调用请求(前端代码):
mov DATAPTR,#A5h
mov DATAPTR+1,#43h ;C
mov DATAPTR+2,#41h ;A
mov DATAPTR+3,#44h ;D
mov DATAPTR+4,#42h ;B
mov DATAPTR+5,#46h ;F
mov DATAPTR+6,#45h ;E
lcall request
这就是主人检索结果的方式:
mov A,DATAPTR
lcall outserbyte
mov A,DATAPTR+1
lcall outserbyte
mov A,DATAPTR+2
lcall outserbyte
mov A,DATAPTR+3
lcall outserbyte
mov A,DATAPTR+4
lcall outserbyte
mov A,DATAPTR+5
lcall outserbyte
mov A,DATAPTR+6
lcall outserbyte
串口字节功能很简单:
outserbyte:
clr TI
mov SBUF,A
jnb TI,$
ret
基本上,我发送给奴隶的数据是:
A5h, 'C', 'A', 'D', 'B', 'F', and 'E'. where A5h is a hexadecimal value.
我收到的数据是:
'@', '@', 'A', 'D', 'B', 'F' and 'E'.
操作速度可以接受,但返回的数据不正确。我期望作为我的命令返回的数据是交换字节函数是这样的:
'@', '@', '@', 'A', 'C', 'F' and 'E'.
但我只关心前5个字节,特别是第4个和第5个字节。 有没有办法可以修复我的代码以返回正确的数据?