1 | //
|
2 | // Programm fuer einen ATmega16
|
3 | //
|
4 | #define F_CPU 16000000UL
|
5 |
|
6 | #include <avr/io.h>
|
7 | #include <avr/interrupt.h>
|
8 | #include <util/delay.h>
|
9 | #define BAUD 115200UL
|
10 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)
|
11 | #include <stdlib.h>
|
12 | #include <string.h>
|
13 |
|
14 | //
|
15 | // Der Prescaler muss so gewählt werden, dass der Ausdruck
|
16 | // für MILLISEC_BASE einen Wert kleiner als 128 ergibt
|
17 | // MILLISEC_BASE ist der Timerwert, der 1 Millisekunde Zeitdauer ergeben
|
18 | // soll.
|
19 | //
|
20 | #define PRESCALER 128
|
21 | #define PRESCALER_BITS (1<<CS22) | ( 1 << CS20 )
|
22 |
|
23 | #define MILLISEC_BASE ( F_CPU / PRESCALER / 1676 )
|
24 | #define CENTER ( MILLISEC_BASE / 2 )
|
25 |
|
26 | //
|
27 | // Konfiguration der Servoleitungen
|
28 | //
|
29 | #define NR_SERVOS 6
|
30 | #define SERVO_DDR DDRD
|
31 | #define SERVO_PORT PORTD
|
32 | uint8_t ServoPuls[NR_SERVOS] = { 1<<PD2, 1<<PD3, 1<<PD4, 1<<PD5,
|
33 | 1<<PD6, 1<<PD7 };
|
34 | //
|
35 | // Werte für die Servoposition
|
36 | // Gültige Werte laufen von 0 bis 2 * CENTER
|
37 | // 0 ... ganz links
|
38 | // CENTER ... Mittelstellung
|
39 | // 2 * CENTER ... ganz rechts
|
40 | //
|
41 | volatile uint8_t ServoValue[NR_SERVOS];
|
42 |
|
43 | char s[4];
|
44 | char buffer[10];
|
45 | volatile uint8_t uart_str_count=0;
|
46 | volatile uint8_t servo=0;
|
47 | volatile uint8_t servo_count=0;
|
48 | volatile uint8_t uart_str_complete = 0;
|
49 |
|
50 | void uart_init(void)
|
51 | {
|
52 | UBRRH = UBRR_VAL>>8;
|
53 | UBRRL = UBRR_VAL;
|
54 | /* evtl. verkuerzt falls Register aufeinanderfolgen (vgl. Datenblatt)
|
55 | UBRR = UBRR_VALUE;
|
56 | */
|
57 |
|
58 | UCSRB = (1 << RXEN) | (1 << TXEN) |(1<<RXCIE);
|
59 | UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
|
60 |
|
61 | }
|
62 |
|
63 | void adc_init(void){
|
64 |
|
65 | ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);
|
66 | ADMUX=0 | (0<<REFS1) | (1<<REFS0);
|
67 |
|
68 | }
|
69 |
|
70 | int uart_putc(unsigned char c)
|
71 | {
|
72 | while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */
|
73 | {
|
74 | }
|
75 |
|
76 | UDR = c; /* sende Zeichen */
|
77 | return 0;
|
78 | }
|
79 |
|
80 | uint8_t uart_getc(void)
|
81 | {
|
82 | while (!(UCSRA & (1<<RXC))) // warten bis Zeichen verfuegbar
|
83 | ;
|
84 | return UDR; // Zeichen aus UDR an Aufrufer zurueckgeben
|
85 | }
|
86 |
|
87 | void uart_puts (char *st)
|
88 | {
|
89 | while (*st)
|
90 | { /* so lange *s != '\0' also ungleich dem "String-Endezeichen(Terminator)" */
|
91 | uart_putc(*st);
|
92 | st++;
|
93 | }
|
94 | //uart_putc(' ');
|
95 | }
|
96 |
|
97 |
|
98 | ISR (TIMER2_COMP_vect)
|
99 | {
|
100 | static uint8_t ServoId = 0;
|
101 |
|
102 | //
|
103 | // den Puls des aktuellen Servos beenden
|
104 | //
|
105 | SERVO_PORT &= ~ServoPuls[ServoId];
|
106 |
|
107 | //
|
108 | // welches ist das nächste aktuelle Servo?
|
109 | //
|
110 | if( ++ServoId >= NR_SERVOS )
|
111 | ServoId = 0;
|
112 |
|
113 | //
|
114 | // die Ausgangsleitung fuer dieses Servo auf 1; den Puls beginnen
|
115 | //
|
116 | SERVO_PORT |= ServoPuls[ServoId];
|
117 |
|
118 | //
|
119 | // den Timer so einstellen, dass bei Pulsende, die ISR erneut aufgerufen wird
|
120 | //
|
121 | OCR2 = MILLISEC_BASE + ServoValue[ServoId];
|
122 | }
|
123 |
|
124 | void InitServo()
|
125 | {
|
126 | uint8_t i;
|
127 |
|
128 | //
|
129 | // Die Servoleitungen auf Ausgang stellen
|
130 | //
|
131 | SERVO_DDR = ServoPuls[0] | ServoPuls[1] | ServoPuls[2] | ServoPuls[3] |
|
132 | ServoPuls[4] | ServoPuls[5] ;
|
133 |
|
134 | //
|
135 | // Alle Servos in Mittelstellung
|
136 | //
|
137 | for( i = 0; i < NR_SERVOS; ++i )
|
138 | ServoValue[i] = CENTER;
|
139 |
|
140 | //
|
141 | // Timer auf CTC Modus konfigurieren
|
142 | //
|
143 | OCR2 = MILLISEC_BASE + ServoValue[0];
|
144 | TIMSK |= (1<<OCIE2);
|
145 | TCCR2 = (1<<WGM21) | PRESCALER_BITS; // CTC mode
|
146 | }
|
147 |
|
148 | int main(void)
|
149 | {
|
150 | InitServo();
|
151 | adc_init();
|
152 | uart_init();
|
153 |
|
154 | sei();
|
155 |
|
156 | _delay_ms( 1000 );
|
157 |
|
158 | //
|
159 | // testweise einfach alle 8 Servos ansteuern
|
160 | // jedes Servo soll sich unterschiedlich schnell bewegen
|
161 | //
|
162 | while( 1 ) {
|
163 |
|
164 |
|
165 |
|
166 | _delay_ms( 40 );
|
167 | }
|
168 | }
|
169 |
|
170 | ISR(USART_RXC_vect)
|
171 |
|
172 | {
|
173 | uart_putc(UDR);
|
174 | if (servo==1)servoSteuer();
|
175 | else{
|
176 | unsigned char nextChar;
|
177 |
|
178 | // Daten aus dem Puffer lesen
|
179 | nextChar = UDR;
|
180 |
|
181 | if (nextChar=='s'){
|
182 | servo=1;
|
183 |
|
184 | }else{
|
185 |
|
186 | if( uart_str_complete == 0 ) {
|
187 | // Daten werden erst in uart_string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird
|
188 | if( nextChar != '\n' &&
|
189 | nextChar != '\r' &&
|
190 | uart_str_count < 9 ) {
|
191 | buffer[uart_str_count] = nextChar;
|
192 | uart_str_count++;
|
193 | }
|
194 | else {
|
195 | buffer[uart_str_count] = '\0';
|
196 | uart_str_count=0;
|
197 | uart_str_complete=1;
|
198 |
|
199 | }
|
200 | }
|
201 | }
|
202 | }
|
203 | }
|
204 |
|
205 | void servoSteuer(void){
|
206 |
|
207 | uint8_t nextChar;
|
208 |
|
209 | // Daten aus dem Puffer lesen
|
210 | nextChar = UDR;
|
211 | uart_putc(nextChar);
|
212 |
|
213 | if(nextChar !='s'){
|
214 | if(
|
215 | nextChar != '\r'){
|
216 |
|
217 |
|
218 |
|
219 | ServoValue[servo_count]=nextChar;
|
220 | servo_count++;
|
221 |
|
222 |
|
223 |
|
224 | }else{
|
225 | servo_count=0;
|
226 | servo=0;
|
227 | }
|
228 |
|
229 | }
|
230 | }
|