1 | #include "uart.h"
|
2 |
|
3 |
|
4 |
|
5 | static volatile uint16_t outframe;
|
6 |
|
7 |
|
8 |
|
9 | static volatile uint16_t inframe;
|
10 |
|
11 | static volatile uint8_t indata, inbits, received;
|
12 |
|
13 |
|
14 |
|
15 | void uart_init()
|
16 |
|
17 | {
|
18 |
|
19 | /* Sichern des Status Registers incl. I-Flag */
|
20 |
|
21 | uint8_t sreg = SREG;
|
22 |
|
23 | cli();
|
24 |
|
25 |
|
26 |
|
27 | SUART_TXD_DDR |= (1 << SUART_TXD_BIT); /* Pin als Ausgang */
|
28 |
|
29 | SUART_TXD_PORT &= ~(1 << SUART_TXD_BIT); /* Low-Pegel */
|
30 |
|
31 |
|
32 |
|
33 | SUART_RXD_DDR &= ~(1 << SUART_RXD_BIT); /* Pin als Eingang */
|
34 |
|
35 | SUART_RXD_PORT |= (1 << SUART_RXD_BIT); /* Pull-up Widerstand */
|
36 |
|
37 |
|
38 |
|
39 | /* Output Compare Register A
|
40 |
|
41 | Anzahl der Taktzyklen für eine Bitlänge
|
42 |
|
43 |
|
44 |
|
45 | F_CPU = 1,2 MHz; Baudrate = 9600 => 125 Taktzyklen pro Bitlänge */
|
46 |
|
47 | OCR0A = 125; /* OCR0A wird zum Senden verwendet */
|
48 |
|
49 | OCR0B = 183; /* OCR0B wird zum Empfangen verwendet. Korrigierter Stand, eig. 188! */
|
50 |
|
51 |
|
52 |
|
53 | /* Timer/Control Register A: setzte Clear Timer/Counter on Compare Match */
|
54 |
|
55 | TCCR0A |= (1 << WGM01);
|
56 |
|
57 |
|
58 |
|
59 | /* Timer/Control Register B: stoppe Timer*/
|
60 |
|
61 | TCCR0B = 0; /* REF NO.: F02/01 */
|
62 |
|
63 |
|
64 |
|
65 | /* Setze Interrupt und Flags für Timer zurück */
|
66 |
|
67 | TIFR0 = (1 << OCF0B) | (1 << OCF0A);
|
68 |
|
69 | TIMSK0 = 0;
|
70 |
|
71 |
|
72 |
|
73 | /* Interrupt wird ausgelöst bei steigender Flanke an PB1 */
|
74 |
|
75 | MCUCR |= (1 << ISC01) | (1 << ISC00);
|
76 |
|
77 | GIFR = (1 << INTF0);
|
78 |
|
79 | GIMSK &= ~(1 << INT0);
|
80 |
|
81 |
|
82 |
|
83 | SREG = sreg;
|
84 |
|
85 | }
|
86 |
|
87 |
|
88 |
|
89 | void uart_putc(const char c)
|
90 |
|
91 | {
|
92 |
|
93 | /* Warte bis alles gesendet ist */
|
94 |
|
95 | do {
|
96 |
|
97 | sei(); nop(); cli();
|
98 |
|
99 | } while (outframe);
|
100 |
|
101 |
|
102 |
|
103 | /* frame = *.P.7.6.5.4.3.2.1.0.S S=Start(0), P=Stop(1), *=Endmarke(1) */
|
104 |
|
105 | outframe = (3 << 9) | (((uint8_t) c) << 1);
|
106 |
|
107 |
|
108 |
|
109 | /* Setze Interrupt für Timer zurück */
|
110 |
|
111 | TIFR0 = (1 << OCF0A);
|
112 |
|
113 |
|
114 |
|
115 | /* Timer/Counter Interrupt Mask Register
|
116 |
|
117 | OCIE0A = 1
|
118 |
|
119 | => Timer/Counter0 Output Compare Match A Interrupt Enable
|
120 |
|
121 |
|
122 |
|
123 | Aktiviere Interrupt für Timer */
|
124 |
|
125 | TIMSK0 |= (1 << OCIE0A);
|
126 |
|
127 | TCCR0B |= (1 << CS00); /* starte Timer mit 1,2 MHz Takt*/
|
128 |
|
129 |
|
130 |
|
131 | sei();
|
132 |
|
133 | }
|
134 |
|
135 |
|
136 |
|
137 | char uart_getc()
|
138 |
|
139 | {
|
140 |
|
141 | cli();
|
142 |
|
143 | GIFR = (1 << INTF0);
|
144 |
|
145 | GIMSK |= (1 << INT0);
|
146 |
|
147 |
|
148 |
|
149 | received = 0;
|
150 |
|
151 | sei();
|
152 |
|
153 |
|
154 |
|
155 | /* Warte bis alles empfangen ist */
|
156 |
|
157 | while(received == 0) {}
|
158 |
|
159 |
|
160 |
|
161 | TCCR0B = 0; /* Stoppe Timer wieder REF NO.: F02/01 */
|
162 |
|
163 | received = 0;
|
164 |
|
165 |
|
166 |
|
167 | return (char) indata;
|
168 |
|
169 | }
|
170 |
|
171 |
|
172 |
|
173 | /* Senden - Interrupt Service Routine */
|
174 |
|
175 | ISR(TIM0_COMPA_vect)
|
176 |
|
177 | {
|
178 |
|
179 | uint16_t data = outframe;
|
180 |
|
181 |
|
182 |
|
183 | if(data & 1) SUART_TXD_PORT &= ~(1 << SUART_TXD_BIT);
|
184 |
|
185 | else SUART_TXD_PORT |= (1 << SUART_TXD_BIT);
|
186 |
|
187 |
|
188 |
|
189 | /* Endmarke erreicht, kille Interrupt */
|
190 |
|
191 | if (1 == data) {
|
192 |
|
193 | TIMSK0 &= ~(1 << OCIE0A);
|
194 |
|
195 | TCCR0B = 0; /* stoppe Timer REF NO.: F02/01 */
|
196 |
|
197 | }
|
198 |
|
199 |
|
200 |
|
201 | outframe = data >> 1;
|
202 |
|
203 | }
|
204 |
|
205 |
|
206 |
|
207 | /* Empfangen - Interrupt Service Routine */
|
208 |
|
209 | ISR(INT0_vect)
|
210 |
|
211 | {
|
212 |
|
213 | OCR0B = 181; /* REF NO.: F01/01 */
|
214 |
|
215 | TIFR0 = (1 << OCF0B);
|
216 |
|
217 | TIMSK0 |= (1 << OCIE0B);
|
218 |
|
219 | TCCR0B |= (1 << CS00); /* Starte Timer mit 1,2 Mhz Takt */
|
220 |
|
221 |
|
222 |
|
223 | GIMSK &= ~(1 << INT0);
|
224 |
|
225 |
|
226 |
|
227 | inframe = 0;
|
228 |
|
229 | inbits = 0;
|
230 |
|
231 | }
|
232 |
|
233 |
|
234 |
|
235 | ISR(TIM0_COMPB_vect)
|
236 |
|
237 | {
|
238 |
|
239 | uint16_t data = inframe >> 1;
|
240 |
|
241 | OCR0B = 123;
|
242 |
|
243 |
|
244 |
|
245 | if(!(SUART_RXD_PIN & (1 << SUART_RXD_BIT))) {
|
246 |
|
247 | data |= (1 << 9);
|
248 |
|
249 | }
|
250 |
|
251 |
|
252 |
|
253 | uint8_t bits = inbits+1;
|
254 |
|
255 |
|
256 |
|
257 | if(bits >= 10) {
|
258 |
|
259 | /* Kontrolle von Start- und Stoppbit */
|
260 |
|
261 | if( !(data & 1) && (data >= (1 << 9)) ) {
|
262 |
|
263 | indata = data >> 1;
|
264 |
|
265 | }
|
266 |
|
267 |
|
268 |
|
269 | received = 1;
|
270 |
|
271 | TIMSK0 &= ~(1 << OCIE0B);
|
272 |
|
273 | } else {
|
274 |
|
275 | inbits = bits;
|
276 |
|
277 | inframe = data;
|
278 |
|
279 | }
|
280 |
|
281 | }
|