In the past I tried using two microcontrollers with one UART each to interface to two UARTs but that setup was too much to manage with timing, so now I decided to use one microcontroller and turn a single UART into a dual UART through the use of tristate line drivers (in particular, the chip 74HC125). I wired their enable pins in such a way so that one logic level will enable one UART and disable the other while another logic level does vice-versa.
This is the code I thought of to allow me to control the UARTs but my main concern is that I don't want the UART switch to happen until a point happens where no transmission or reception takes place.
I attempted to do this by making timer 1 execute at 16x the speed of timer 0 because I think 16 is the magic number for serial (16 switch states for a shift register? I don't know). If my idea is wrong, correct me here.
If I decide to change the UART, then I added code which halts the main program until the change happens and a flag is set indicating it.
Please tell me if I'm on the right track, or if there is more efficient code I can use?
This is the code I thought of to allow me to control the UARTs but my main concern is that I don't want the UART switch to happen until a point happens where no transmission or reception takes place.
I attempted to do this by making timer 1 execute at 16x the speed of timer 0 because I think 16 is the magic number for serial (16 switch states for a shift register? I don't know). If my idea is wrong, correct me here.
If I decide to change the UART, then I added code which halts the main program until the change happens and a flag is set indicating it.
Please tell me if I'm on the right track, or if there is more efficient code I can use?
Code:
IORAD equ Px.x ;port that selects UART
UART equ 7Fh ;desired UART (setting in memory)
UARTR equ 7Eh ;desired UART recognized
org 0h
ajmp start
org 0Bh ;timer 0 int
push PSW ;save old C
mov C,UART ;load setting
mov IORAD,C ;and put it out to pin
setb UARTR ;and let processes the switch is done
pop PSW ;restore old C
reti
start:
mov A,#1h ;use 56k speed
lcall speedcfg
setb UART ;set by default on power on
setb EA
setb ET0
;send a '1' to first UART
clr TI
mov SBUF,#'1'
jnb TI,$
;switch UART
clr UART
clr UARTR
;wait until its officially switched
jnb UARTR,$
;send a '2' to second UART
clr TI
mov SBUF,#'2'
jnb TI,$
;use 1st uart again
setb UART
clr UARTR
jnb UARTR,$
;attempt to receive char from 1st UART within 256 clock cycles and save to R5
clr RI
mov R6,#0h
rt1:
jnb RI,nr1
mov R5,SBUF ;receive OK
ajmp nx
nr1:
djnz R6,rt1
nx:
;use 2nd uart again
clr UART
clr UARTR
jnb UARTR,$
;attempt to receive char from 2nd UART within 256 clock cycles and save to R4
clr RI
mov R6,#0h
rt2:
jnb RI,nr2
mov R4,SBUF ;receive OK
ajmp nx2
nr2:
djnz R6,rt2
nx2:
;rest of code here
;configure UART speed
speedcfg:
;Turn timers off
clr TR1
clr TR0
;save value
mov R7,A
;setup timer for mode 2 and UART for high speed and serial for 8N1
mov PCON,#80h
mov SCON,#50h
mov TMOD,#22h
;invert value (aka value=256-value) to satisfy mode 2 and store in TH1 + TL1
xrl A,#0FFh
mov TH1,A
mov TL1,TH1
;get saved value and multiply by 16 (aka swap + anl)
mov A,R7
swap A
anl A,#0F0h
;invert again
xrl A,#0FFh
mov TH0,A
mov TL0,TH0
;timer 0 flag is set 16x slower than timer 1 flag
setb TR0
setb TR1
ret