-
Notifications
You must be signed in to change notification settings - Fork 0
/
uart.asm
179 lines (120 loc) · 3.27 KB
/
uart.asm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
.include "tn13adef.inc"
.dseg
.org SRAM_START
msg: .byte 20 ; text to be transmitted, stored in ram
;***** Pin definitions
.equ RxD =3 ;Receive pin is PB3
.equ TxD =4 ;Transmit pin is PB4
;***** UART Rx/Tx delays
.equ tx_delay = 163
;Number of stop bits (1, 2, ...)
.equ sb =1
;***** Global register variables
.def bitcnt =R16 ;bit counter
.def temp =R17 ;temporary storage register
.def Txbyte =R18 ;Data to be transmitted
.def RXbyte =R19 ;Received data
.cseg
.org 0
rjmp init
.org 0x000A ; First address after interrupt vector table
;***************************************************************************
;*
;* "putchar"
;*
;*
;***************************************************************************
putchar:
ldi bitcnt,9+sb ;1+8+sb (sb is # of stop bits)
com Txbyte ;Inverte everything
sec ;Start bit
putchar0:
brcc putchar1 ;If carry set
cbi PORTB,TxD ; send a '0'
rjmp putchar2 ;else
putchar1:
sbi PORTB,TxD ; send a '1'
nop
putchar2:
rcall UART_delay ;One bit delay
rcall UART_delay
lsr Txbyte ;Get next bit
dec bitcnt ;If not all bit sent
brne putchar0 ; send next
;else
ret ; return
UART_Send:
ldi ZL,LOW(msg) ; initialize Z pointer
ldi ZH,HIGH(msg) ; to tx msg address
cli ;Prevent Global Interrupts
TX_Byte:
ld r18, Z+ ;Load data byte for sending
cpi r18, 0 ;Compare with ZERO
breq Exit_Transmit ; Exit if equal, EXIT transmitting
rcall putchar
rjmp TX_Byte ;jump to next sending byte
Exit_Transmit:
sei ;Allow Global Interrupts
ret
;***************************************************************************
;*
;* "getchar"
;*
;***************************************************************************
getchar:
ldi bitcnt,9 ;8 data bit + 1 stop bit
getchar1:
sbic PINB,RxD ;Wait for start bit
rjmp getchar1
rcall UART_delay ;0.5 bit delay
getchar2:
rcall UART_delay ;1 bit delay
rcall UART_delay
clc ;clear carry
sbic PINB,RxD ;if RX pin high
sec ;
dec bitcnt ;If bit is stop bit
breq getchar3 ; return
;else
ror Rxbyte ; shift bit into Rxbyte
rjmp getchar2 ; go get next
getchar3:
st Z+,Rxbyte
cpi Rxbyte,0x0D
brne getchar
ldi Rxbyte,0x00
st Z,Rxbyte
ret
;***************************************************************************
;*
;* "UART_delay"
;*
;* This delay subroutine generates the required delay between the bits when
;* transmitting and receiving bytes. The total execution time is set by the
;* constant "b":
;*
;* 3·b + 7 cycles (including rcall and ret)
.equ b = 163 ;9600 bps @ 9.6 MHz crystal
UART_delay:
ldi temp,b ;1c
UART_delay1:
dec temp ;1c
brne UART_delay1 ;1c
ret
uartd:
dec temp ;1c
brne UART_delay1 ;1c
ret
;***** Program Execution Starts Here
;***** Test program
init:
sbi PORTB,TxD ;Init port pins
sbi DDRB,TxD
ldi ZL,LOW(msg) ; initialize Z pointer
ldi ZH,HIGH(msg) ; to tx msg address
main_loop:
rcall getchar
rcall UART_Send ;Echo received char
ldi ZL,LOW(msg) ; initialize Z pointer
ldi ZH,HIGH(msg) ; to tx msg address
rjmp main_loop