Using the UART in the ATmega8535
Serial communication between the microcontroller and a PC is essential for data transfer to the microcontroller and reading of its ADC output by the PC. The universal asynchronous receiver transmitter (UART) built into the microcontroller can be programmed to operate at certain baud rates.
The adc_ch.asm sample program given below is useful for UART applications:
[stextbox id=”grey”]
ADC_CH.ASM
; *********************************************************
; This program read one of ADC channels (0 to 7).
The Channel can be selected by sending Channel
number.
; ATmega8535 receives the Channel no. and outputs
the five digit ADC value
; on RS232 port for reading by a PC’s XTALK
program or a VB project.
; Software features: It is possible to read the ADC
value and also
; transmit to the PC for data logging.
; *********************************************************
.NOLIST
.INCLUDE “m8535def.inc”
;device =ATMega8535
.LIST
.EQU xyz = 12345
; Constants for Sio properties
.EQU fq=1000000; clock frequency of m8535 with
internal oscillator
.EQU baud=4800; Baudrate for SIO communication
.EQU bddiv=(fq/(16*baud))-1; Baudrate divider
.DEF rmpr = R16
.DEF temp = R14
.DEF result=R12
.DEF mpr =R16
.CSEG
.ORG $0000
rjmp Start ; Reset-vector
.org $000b
rjmp USART_RXC
.org $0100
InitSio:
LDI rmpr,bddiv ; Init baud generator
OUT UBRRL,rmpr ; set divider in UART
baud rate register
ldi rmpr, 0
out ubrrh,rmpr
LDI rmpr,(1<
(1<
out UCsRB,rmpr
LDI ZL,0 ; Wait some time
LDI ZH,0
InitSio1:
SBIW ZL,1
BRNE InitSio1
ldi r16,(1<
(3<
out ucsrc,r16
RET
USART_RXC:
push r16
in R16,udr
andi R16,07
mov r1,r16
ori r16,$c0
out admux,r16
ldi r16,$43
rcall tout ; intimate new channel to host
ldi r16,$48
rcall tout
mov r16,r1
ori r16,$30
rcall tout
pop r16
reti
cmd: cbi portc,2
cbi portc,3
cbi portc,4
out portb,r16
sbi portc,4
nop
nop
nop
nop
nop
nop
nop
nop
nop
cbi portc,4
rcall delay1
rcall delay1
rcall delay1
ret
lcdwr:cbi portc,2
cbi portc,3
cbi portc,4
sbi portc,2
out portb,r16
sbi portc,4
nop
nop
nop
nop
nop
nop
nop
nop
nop
cbi portc,4
rcall delay1
ret
init_lcd:
ldi R16,$38
rcall cmd
rcall delay1
rcall delay1
ldi R16,$0e
rcall cmd
rcall delay1
ldi R16,6
rcall cmd
ldi r16,1
rcall cmd
rcall delay2
ret
tout: sbis UcSRa,UDRE ;TX COMPLETE check
RJMP tout
OUT UDR,R16
Ret
delay1:push r16
clr result
loop22:ldi R16,$f0
loop2:inc R16
brne loop2
inc result
brne loop22
pop r16
ret
delay2:push r16
clr result
loop221:ldi R16,$f0
loop21:inc R16
brne loop21
inc result
brne loop221
pop r16
ret
delay: clr result
ld: inc result
brne ld
ret
lcddisp:push r16
ldi r16,128 ;cursor to left end
rcall cmd
pop r16
rcall delay1
rcall delay1
rcall binbcd
mov r16,r15
andi r16,0x0f
ori r16,0x30
rcall tout
rcall lcdwr ; 1
mov r16,r14
andi r16,0b11110000
ror r16
ror r16
ror r16
ror r16
ori r16,0x30
rcall tout
rcall lcdwr ;2
mov r16,r14
andi r16,0x0f
ori r16,0x30
rcall tout
rcall lcdwr ;3
mov r16,r13
andi r16,0b11110000
ror r16
ror r16
ror r16
ror r16
ori r16,0x30
rcall tout
rcall lcdwr ;4
mov r16,r13
andi r16,0x0f
ori r16,0x30
rcall tout
rcall lcdwr ;5
ldi r16,$0a
rcall tout
ldi r16,$0d
rcall tout
ret
binbcd:
;* “bin2BCD16” – 16-bit Binary to BCD conversion
;* convert 16-bit number (fbinH:fbinL) to a 5-digit
;* packed BCD number represented by 3 bytes
(tBCD2:tBCD1:tBCD0).
;* MSD of 5-digit number is placed in the lowermost
nibble of tBCD2.
;* Number of words :25
;* Number of cycles :751/768 (Min/Max)
;* Low registers used :3 (tBCD0,tBCD1,tBCD2)
;* High registers used :4(fbinL,fbinH,cnt16a,tmp16a)
;* Pointers used :Z
; Subroutine Register Variables
.equ AtBCD0 =13 ;address of tBCD0
.equ AtBCD2 =15 ;address of tBCD1
.def tBCD0 =r13 ;BCD value digits 1 and 0
.def tBCD1 =r14 ;BCD value digits 3 and 2
.def tBCD2 =r15 ;BCD value digit 4
.def fbinL =r16 ;binary value Low byte
.def fbinH =r17 ;binary value High byte
.def cnt16a =r18 ;loop counter
.def tmp16a =r19 ;temporary value
bin2BCD16:
ldi cnt16a,16 ;Init loop counter
clr tBCD2 ;clear result (3 bytes)
clr tBCD1
clr tBCD0
clr ZH ;clear ZH (not
needed for AT90Sxx0x)
bBCDx_1:lsl fbinL ;shift input value
rol fbinH ;through all bytes
rol tBCD0
rol tBCD1
rol tBCD2
dec cnt16a ;decrement loop counter
brne bBCDx_2 ;if counter not zero
ret ; return
bBCDx_2:ldi r30,AtBCD2+1 ;Z points to
result MSB + 1
bBCDx_3:
ld tmp16a,-Z ;get (Z) with pre-decrement
subi tmp16a,-$03 ;add 0x03
sbrc tmp16a,3 ;if bit 3 not clear
st Z,tmp16a ;store back
ld tmp16a,Z ;get (Z)
subi tmp16a,-$30 ;add 0x30
sbrc tmp16a,7 ;if bit 7 not clear
st Z,tmp16a ; store back
cpi ZL,AtBCD0 ;done all three?
brne bBCDx_3 ;loop again if not
rjmp bBCDx_1 ;End of the subroutine
section
; Main program routine starts here
Start:ldi R16,low(RAMEND);Load low byte address
of end of RAM into
register R16
out SPL,R16 ; Initialize stack pointer to
end of internal RAM
ldi R16,high(RAMEND);Load high byte
address of end
of RAM into
register R16
out SPH, R16 ;Initialize high
byte of stack pointer
to end of internal RAM
ldi r16,$c0 ; c0 for int. ref, e0 with adch alone used.
out admux,r16 ; channel 0 is selected
ldi r16,0b11000101 ;prescale /32 (1×32=33 usec)
;adc enable,adc start,adc freerun,adcflag,adcno int,
adcprescale/32
out adcsra,r16
ldi r16,0
out sfior,r16 ; write 0-0-0 to bits d7-d5 for free
run adc
here1:in r16,adcsra
andi r16,0b01000000
breq here1 ;value got
ldi R16,255
out ddrb,R16 ; port b is all bits output
out ddrc,R16 ; so is port c
ldi r16,0
out ddra,r16 ;port a input
init: rcall initsio
sei ;enable global interrupt
LCD: rcall init_lcd
lcd1: ldi R16,$80
rcall cmd
rcall delay1
rcall delay1
rcall delay1
rcall delay1
here3:in r16,adcsra
andi r16,0b01000000
brne here3 ;value got
in r16,adcl
IN R17,adch
push r16
ldi r16,0b11000101 ;prescale /32 (1×32=32
usec)
;adc enable,adc start,adc freerun,adcflag,adcno int,
adcprescale/32
out adcsra,r16
pop r16
rcall lcddisp
rjmp lcd1
in r16,udr
andi r16,07
mov r14,r16
ori r16,$c0
out admux,r16
ldi r16,$43
rcall tout ; intimate new channel to host
ldi r16,$48
rcall tout
mov r16,r14
ori r16,$30
rcall tout
rjmp lcd1
[/stextbox]
The above program reads the ADC output data, whose decimal value is output to pin 15 (TX) of ATmega8535 at 4800 bauds in 8-bit ASCII data format. If a MAX232 is wired to pin 15, it can be directly connected to the receive pin of the RS-232 com port of a PC. Then, by using any terminal program (such as XTALK), it can be received by the PC.