-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuart-isr.asm
211 lines (147 loc) · 4.24 KB
/
uart-isr.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
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
.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
nop ; IRQ0
rjmp PCINT ; PCINT0 (pin INT0 to INT5) PCMSK, MCUCR
.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"
;*
;***************************************************************************
PCINT:
in r0, 0x3F ;Store SREG
push r0
ldi ZL,LOW(msg) ; initialize Z pointer
ldi ZH,HIGH(msg) ; to tx msg address
cbi PCMSK,RxD ; turn off PCINT
getchar:
ldi bitcnt,9 ;8 data bit + 1 stop bit
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
breq exitrx
ldi bitcnt,9 ;8 data bit + 1 stop bit
getc1:
sbic PINB,RxD ;Wait for start bit
rjmp getc1
rjmp getchar1
exitrx:
ldi Rxbyte,0x0A ;add linebreak
st Z+,Rxbyte
clr Rxbyte ; null terminated string
st Z,Rxbyte
ldi r20, 0x80 ;set rx flag
pop r0 ; Restore SREG
out 0x3F, r0
reti
;***************************************************************************
;*
;* "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
;***** Program Execution Starts Here
;***** Test program
init:
sbi PORTB,TxD ;Init port pins
sbi DDRB,TxD
;init for receiving
ldi r16,0b00100000 ;GIMSK = (1<<PCIE); Enable External Interrupts
out GIMSK,r16
sbi PCMSK,RxD ;PCMSK = (1<<RxD); Enable accorded Interrupt (PCINT3)
sei; Allow Interrupts
clr r20 ; rx flag
;############################################
;;########### MAIN LOOP #####################
;############################################
main_loop:
cpi r20,0x80 ;test rx flag
brne main_loop
rcall UART_Send
wait_for_idle:
sbis PINB,RxD ;Wait for idle bit
rjmp wait_for_idle
sbi PCMSK,RxD ;re-enable PCINT
clr r20
rjmp main_loop
;############################################
;;########### MAIN LOOP #####################
;############################################