8051中可靠的串行数据缓冲

时间:2017-09-01 01:02:55

标签: delay microcontroller uart 8051

在不久的将来,我将成为通过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

0 个答案:

没有答案