1 | /**
|
2 | * @file USARTMega8.h
|
3 | * @brief Deklaration der USARTMega8-Klasse.
|
4 | * @author Dr. Rüdiger Knörig (ruediger@knoerig.de)
|
5 | * @date 11.07.2013
|
6 | */
|
7 |
|
8 | #ifndef USARTMEGA_H_
|
9 | #define USARTMEGA_H_
|
10 |
|
11 | #include <avr/io.h>
|
12 |
|
13 | using namespace std;
|
14 |
|
15 | const char *endl="\n\r";
|
16 |
|
17 | /**
|
18 | * @brief Serielle Schnittstellenklasse für den ATMega8.
|
19 | * @author Dr. Rüdiger Knörig (ruediger@knoerig.de)
|
20 | * @date 11.07.2013
|
21 | * @tparam BaudRate Desired baud rate.
|
22 | */
|
23 | template<unsigned long int BaudRate> class USARTMega8
|
24 | {
|
25 | public:
|
26 |
|
27 | /**
|
28 | * @brief Konstruktor.
|
29 | */
|
30 | USARTMega8() : erfolg(true)
|
31 | {
|
32 | uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BaudRate) - 1);
|
33 | //uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*9600ul) - 1);
|
34 |
|
35 | UBRRH = (uint8_t) (ubrr>>8);
|
36 | UBRRL = (uint8_t) (ubrr);
|
37 |
|
38 | // UART Receiver und Transmitter anschalten
|
39 | // Data mode 8N1, asynchron
|
40 | UCSRB = (1 << RXEN) | (1 << TXEN);
|
41 | UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
|
42 |
|
43 | // Flush Receive-Buffer (entfernen evtl. vorhandener ungültiger Werte)
|
44 | do
|
45 | {
|
46 | UDR;
|
47 | }
|
48 | while (UCSRA & (1 << RXC));
|
49 | }
|
50 |
|
51 | /**
|
52 | * @brief Destruktor.
|
53 | */
|
54 | ~USARTMega8() {}
|
55 |
|
56 | /**
|
57 | * @brief Druckt ein einzelnes Zeichen.
|
58 | * @param[in] zeichen Zeichen zum Drucken.
|
59 | */
|
60 | void druckeZeichen(const char zeichen)
|
61 | {
|
62 | // Warten, bis UDR bereit ist für einen neuen Wert
|
63 | while (!(UCSRA & (1 << UDRE)));
|
64 | // UDR Schreiben startet die Übertragung
|
65 | UDR = zeichen;
|
66 | }
|
67 |
|
68 | /**
|
69 | * @brief Druckt eine ganze Zeichenkette.
|
70 | * @param[in] zeichenKette Zeichenkette zum Drucken.
|
71 | */
|
72 | void druckeZeichenkette(const char *zeichenKette)
|
73 | {
|
74 | while(*zeichenKette) druckeZeichen(*zeichenKette++);
|
75 | }
|
76 |
|
77 | /**
|
78 | * @brief Liest ein einzelnes Zeichen von der seriellen Schnittstelle.
|
79 | * Diese Methode wartet blockierend auf einen Empfang.
|
80 | */
|
81 | uint8_t leseZeichenBlockierend()
|
82 | {
|
83 | // Warten, bis etwas empfangen wird
|
84 | while (!(UCSRA & (1 << RXC)));
|
85 |
|
86 | // Das empfangene Zeichen zurückliefern
|
87 | return UDR;
|
88 | }
|
89 |
|
90 | /**
|
91 | * @brief Liest ein einzelnes Zeichen von der seriellen Schnittstelle.
|
92 | * Diese Methode wartet nicht auf einen Empfang.
|
93 | * @param[out] zeichen Referenz auf die aufnehmende Zeichenvariable.
|
94 | * @return Wahr, wenn ein Zeichen gelesen wurde.
|
95 | */
|
96 | bool leseZeichenNichtBlockierend(uint8_t &zeichen)
|
97 | {
|
98 | if((UCSRA & (1 << RXC)))
|
99 | {
|
100 | zeichen=UDR;
|
101 | return true;
|
102 | }
|
103 | else
|
104 | {
|
105 | return false;
|
106 | }
|
107 | }
|
108 |
|
109 | /**
|
110 | * @brief Liest eine Zeichenkette von der seriellen Schnittstelle ein.
|
111 | * @param[out] puffer Aufnahmepuffer.
|
112 | * @param[in] pufferLaenge Größe des Aufnahmepuffers.
|
113 | */
|
114 | void leseZeichenkette(char *puffer,unsigned int pufferLaenge)
|
115 | {
|
116 | char *ende=puffer + pufferLaenge - 1;
|
117 | while(puffer < ende)
|
118 | {
|
119 | char zeichen=leseZeichenBlockierend();
|
120 | if((zeichen==' ') || (zeichen == '\t') || (zeichen == '\n')) break;
|
121 | *(puffer++)=zeichen;
|
122 | }
|
123 | *puffer=0;
|
124 | }
|
125 |
|
126 | /**
|
127 | * @brief Vergleicht zwei Zeichenketten.
|
128 | * @param[in] zk1 Erste Zeichenkette.
|
129 | * @param[in] zk2 Zweite Zeichenkette.
|
130 | * @param[in] maxLaenge Maximale Länge der Zeichenketten.
|
131 | * @return 0 wenn beide Zeichenketten identisch sind, -1 wenn zk1 < zk2 und 1 wenn zk1 > zk2.
|
132 | */
|
133 | int vergleicheZeichenketten(const char *zk1,const char *zk2,unsigned int maxLaenge)
|
134 | {
|
135 | for(unsigned int k=0;k<maxLaenge;k++)
|
136 | {
|
137 | char z1=zk1[k];
|
138 | char z2=zk2[k];
|
139 | if((z1==0) || (z2 == 0))
|
140 | {
|
141 | if((z1==0) && (z2 != 0)) return -1;
|
142 | if((z2==0) && (z1 != 0)) return 1;
|
143 | return 0;
|
144 | }
|
145 | else
|
146 | {
|
147 | if(z1 < z2) return -1;
|
148 | if(z1 > z2) return 1;
|
149 | }
|
150 | }
|
151 | return 0;
|
152 | }
|
153 |
|
154 | /**
|
155 | * @brief Liest eine Ganzzahl ein.
|
156 | * @param[out] zahl Referenz auf die aufnehmende Ganzzahlvariable.
|
157 | * @return Wahr, wenn eine Zahl ohne Probleme eingelesen werden konnte.
|
158 | */
|
159 | bool leseZahl(int &zahl)
|
160 | {
|
161 | bool ziffernGelesen=false;
|
162 | bool hatVorzeichen=false;
|
163 | bool erfolg=false;
|
164 | bool negativ=false;
|
165 | zahl=0;
|
166 | do{
|
167 | uint8_t zeichen=leseZeichenBlockierend();
|
168 | if((zeichen == ' ') || (zeichen == '\t') || (zeichen == '\n') || (zeichen == '\r'))
|
169 | {
|
170 | erfolg=ziffernGelesen;
|
171 | if((ziffernGelesen==false) && ((zeichen == ' ') || (zeichen == '\t'))) continue;
|
172 | else break;
|
173 | }
|
174 | else if((zeichen == '+') || (zeichen == '-'))
|
175 | {
|
176 | if(hatVorzeichen) return false;
|
177 | if(zeichen == '-') negativ=true;
|
178 | hatVorzeichen=true;
|
179 | druckeZeichen(zeichen);
|
180 | }
|
181 | else if((zeichen >= '0') && (zeichen <= '9'))
|
182 | {
|
183 | zahl = zahl*10+(zeichen-'0');
|
184 | ziffernGelesen=true;
|
185 | druckeZeichen(zeichen);
|
186 | }
|
187 | else
|
188 | {
|
189 | druckeZeichenkette("Falsch!\n\r");
|
190 | return false;
|
191 | }
|
192 | }while(true);
|
193 | if(negativ) zahl=(~zahl+1);
|
194 | return erfolg;
|
195 | }
|
196 |
|
197 | /**
|
198 | * @brief Druckt die gegebene Zahl auf der seriellen Konsole aus.
|
199 | * @param[in] zahl Auszudruckende Zahl.
|
200 | */
|
201 | void schreibeZahl(int32_t zahl)
|
202 | {
|
203 | char puffer[10];
|
204 | char *ptr=puffer+10;
|
205 | char *endPtr=ptr;
|
206 |
|
207 | if(zahl < 0)
|
208 | {
|
209 | druckeZeichen('-');
|
210 | zahl = (~zahl) + 1; // 2er-Komplementär invertieren
|
211 | }
|
212 | do
|
213 | {
|
214 | char ziffer='0'+(zahl % 10);
|
215 | *(--ptr)=ziffer;
|
216 | zahl /= 10;
|
217 | }while(zahl > 0);
|
218 | for(;ptr < endPtr;ptr++) druckeZeichen(*ptr);
|
219 | }
|
220 |
|
221 | /**
|
222 | * @brief Inspektor für den Erfolg der letzten Strom-Eingabe.
|
223 | * @return Wahr, wenn die letzte Stromeingabe erfolgreich war.
|
224 | */
|
225 | bool warErfolgreich() { return erfolg; }
|
226 |
|
227 | /**
|
228 | * @brief Strom-Ausgabeoperator für Zeichenketten.
|
229 | * @param[in] zeichenkette Auszugebende Zeichenkette.
|
230 | * @return Referenz auf das USART-Objekt zwecks Verkettung.
|
231 | */
|
232 | USARTMega8 &operator<<(const char *zeichenkette)
|
233 | {
|
234 | druckeZeichenkette(zeichenkette);
|
235 | return *this;
|
236 | }
|
237 |
|
238 | /**
|
239 | * @brief Strom-Ausgabeoperator für Zahlen.
|
240 | * @param[in] zahl Auszugebende Zahl
|
241 | * @return Referenz auf das USART-Objekt zwecks Verkettung.
|
242 | */
|
243 | USARTMega8 &operator<<(int zahl)
|
244 | {
|
245 | schreibeZahl(zahl);
|
246 | return *this;
|
247 | }
|
248 |
|
249 | /**
|
250 | * @brief Strom-Eingabeoperator für Zahlen.
|
251 | * @param[out] Zahl Referenz auf die einzulesende Zahl.
|
252 | * @return Referenz auf das USART-Objekt zwecks Verkettung.
|
253 | */
|
254 | USARTMega8 &operator>>(int &zahl)
|
255 | {
|
256 | erfolg=leseZahl(zahl);
|
257 | return *this;
|
258 | }
|
259 |
|
260 | protected:
|
261 | bool erfolg; /**< Indiziert einen Erfolg/Mißerfolg bei der letzten Strom-Eingabe. */
|
262 | };
|
263 |
|
264 | #endif
|