9
|
1 |
.nolist
|
|
2 |
.include "m168def.inc" ; Same family as 328P
|
|
3 |
.list
|
|
4 |
|
|
5 |
.macro poke
|
|
6 |
.message "No parameters"
|
|
7 |
.endm
|
|
8 |
|
|
9 |
.macro poke_i_8_i
|
|
10 |
ldi @1, @2
|
|
11 |
sts @0, @1
|
|
12 |
.endm
|
|
13 |
|
|
14 |
.macro poke_i_16_i
|
|
15 |
ldi @1, low(@3)
|
|
16 |
sts @0+0, @1
|
|
17 |
|
|
18 |
ldi @2, high(@3)
|
|
19 |
sts @0+1, @2
|
|
20 |
.endm
|
|
21 |
|
|
22 |
;; Load a 16-bit *word* address into the given register a a byte address
|
|
23 |
.macro loadp_16_i
|
|
24 |
ldi @0, high(2 * @2)
|
|
25 |
ldi @1, low(2 * @2)
|
|
26 |
.endm
|
|
27 |
|
|
28 |
.macro load_16_i
|
|
29 |
ldi @0, high(@2)
|
|
30 |
ldi @1, low(@2)
|
|
31 |
.endm
|
|
32 |
|
|
33 |
;; Interrupt Vector
|
|
34 |
.org 0x00
|
|
35 |
rjmp Main
|
|
36 |
|
|
37 |
;; Serial
|
|
38 |
.set SERIAL_BAUD = 103 ; 9.6k @ 16Mhz
|
|
39 |
|
|
40 |
;; Initialize the UART for
|
|
41 |
Serial_Init:
|
|
42 |
; Set up control registers
|
|
43 |
; Single-speed
|
|
44 |
poke [UCSR0A, r16, (0 << U2X0)]
|
|
45 |
|
|
46 |
; Async
|
|
47 |
; n parity
|
|
48 |
; 1 stop
|
|
49 |
; 8 bits
|
|
50 |
poke [UCSR0C, r16, (0b00 << UMSEL00) | (0b00 << UPM00) | (0 << USBS0) | (0b11 << UCSZ00)]
|
|
51 |
|
|
52 |
; Baud rate
|
|
53 |
poke [UBRR0L, r16:r17, SERIAL_BAUD]
|
|
54 |
|
|
55 |
; Enable RX
|
|
56 |
; Enable TX
|
|
57 |
; 8 bits
|
11
|
58 |
poke [UCSR0B, r16, (1 << RXEN0) | (1 << TXEN0) | (0 << UCSZ02)]
|
9
|
59 |
|
|
60 |
; Done
|
|
61 |
ret
|
|
62 |
|
|
63 |
;; Send a single byte on serial port
|
|
64 |
; Input byte in r16
|
|
65 |
Serial_Send:
|
|
66 |
; Wait for idle
|
|
67 |
lds r0, UCSR0A
|
|
68 |
sbrs r0, UDRE0
|
|
69 |
rjmp Serial_Send
|
|
70 |
|
|
71 |
; Copy byte to buffer
|
|
72 |
sts UDR0, r16
|
|
73 |
|
|
74 |
; Done
|
|
75 |
ret
|
|
76 |
|
11
|
77 |
;; Read a single byte from serial port
|
|
78 |
; Output byte in r16
|
|
79 |
Serial_Recv:
|
|
80 |
; Wait for recv
|
|
81 |
lds r0, UCSR0A
|
|
82 |
sbrs r0, RXC0
|
|
83 |
rjmp Serial_Recv
|
|
84 |
|
|
85 |
; Copy byte from buffer
|
|
86 |
lds r16, UDR0
|
|
87 |
|
|
88 |
; Done
|
|
89 |
ret
|
|
90 |
|
9
|
91 |
;; Write nul-terminated string to serial port
|
|
92 |
; Input string in Z
|
|
93 |
Serial_Write:
|
|
94 |
; Load byte to r16
|
|
95 |
lpm r16, Z+
|
|
96 |
|
|
97 |
; Quit if nul
|
|
98 |
tst r16
|
|
99 |
breq _serial_write_end
|
|
100 |
|
|
101 |
; Write it
|
|
102 |
rcall Serial_Send
|
|
103 |
|
|
104 |
; Continue
|
|
105 |
rjmp Serial_Write
|
|
106 |
|
|
107 |
_serial_write_end:
|
|
108 |
ret
|
|
109 |
|
|
110 |
;; Program
|
|
111 |
message: .db "Hello World", 13, 10, 0
|
|
112 |
|
|
113 |
Main:
|
|
114 |
; Initialization
|
|
115 |
; Stack
|
|
116 |
poke [SPL, r16:r17, RAMEND]
|
|
117 |
|
|
118 |
; Enable interrupts
|
|
119 |
sei
|
|
120 |
|
|
121 |
; Init
|
|
122 |
rcall Serial_Init
|
|
123 |
|
|
124 |
; Main program
|
|
125 |
ldi ZH, high(message * 2)
|
|
126 |
ldi ZL, low(message * 2)
|
|
127 |
|
|
128 |
rcall Serial_Write
|
11
|
129 |
|
|
130 |
; Echo out
|
|
131 |
sbi DDRB, PORTB5
|
|
132 |
ldi r20, 0
|
|
133 |
|
|
134 |
Main_Echo:
|
|
135 |
out PORTB, r20
|
|
136 |
|
|
137 |
rcall Serial_Recv
|
|
138 |
rcall Serial_Send
|
|
139 |
|
|
140 |
com r20
|
|
141 |
|
|
142 |
rjmp Main_Echo
|
|
143 |
|