Hallo! Ich bein leider ein ziemlicher Neuling in der Mirkocontroller-Programmierung. Ich habe einen atmega8 via USB-Schnittstelle zur Verfügung und als Entwicklungsumgebung das AVR-Studio. Ich möchte über den Mikrocontroller mit den ADC 2 Spannungen auslesen und die Daten an MATLAB senden bzw. auch über den Mirkocontroller Ausgangssignale senden. Für das auslesen habe ich schon im Tutorial hier im Forum etwas gefunden :) http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#ADC_.28Analog_Digital_Converter.29 Leider sind die Punkte senden an MATLAB und senden über den Mikrocontroller noch hoffen :(. Kann mir da jemand weiterhelfen? MFG Martin
Klar können wir dir helfen: 1) lies dich in die Materie ein, dann verstehst du sie auch! 2) schick die Daten erstmal über einen UART mit einem FT232 dran. Der erscheint als virtuelle serielle Schnittstelle auf dem PC und die kann Matlab sehr einfach ansprechen.
Danke für die Info, ich werde mich einlesen. Leider ist mir ein Detail bezüglich den ADC noch nicht klar und zwar wie erkennt man die Zuordnung der einzelnen Kanäle? Sprich wie stelle ich die Beziehung zur Hexzahl "0x1F" da?
Martin, wenn Dein PC eine RS232-Schnittstelle hat, dann kannst Du die Daten direkt (ohne FT232) über die zweite RS232 ("RS232 spare") am STK500 übertragen, die Sache ist im Begleitheft zum STK500 auf Seite 3-5 beschrieben. Muster für die Programme, die Du dazu brauchst, gibt's hier im Mikrocontroller.net aber auch im Netz. Ich glaube, es wäre gut, wenn Du erstmal diese Verbindung ans Laufen kriegst. Damit kannst Du Dir nämlich die Registerinhalte des ATmega am Bildschirm angucken; das hilft ungemein beim Fehlersuchen und beim Verstehen des Chips ;-). Bei der Beschäftigung mit so einem MC ist das Datenblatt Deine "Bibel". Die Datenblätter von Atmel sind ziemlich gut. Ich habe bisher noch alle meine Fragen darin beantwortet gefunden. mare_crisium
> Leider ist mir ein Detail bezüglich den ADC noch nicht klar und zwar wie > erkennt man die Zuordnung der einzelnen Kanäle? Du sagst dem ADC vorher , welchen Kanal er als nächstes wandeln soll. Dazu dient das Register ADMUX.
Vielen dank für die Hilfestellungen. Mittlerweile ist es so, dass ich ADC auslesen kann und die Kommunikation mit MATLAB (in beide Richtungen) steht :-). Leider bin ich jetzt auf das nächste Problem gestoßen. Denn ich möchte mir einen Timer machen, der mir z.B. jede Sekunde (wird dann später natürlich kleiner gewählt) meine Spannung ausliest. Für den Anfang hätte ich einfach mal versucht einen Conuter zu basteln der jede Sekunde erhöht wird und dann in meiner MATLAB-Gui ausgegeben wird. Leider bekomme ich immer eine Zeitverzögerung rein :(. Ich hätte hier anschliessend noch meinen Code gepostet, mir ist klar, dass es nicht so lustig ist fremden Code durch zu schauen. Aber vielleicht ist ja jemand so nett. Ich sitze schon seit Anfang Nachmittag an diesem Problem und es geht nicht wirklich was weiter.
1 | #include <avr/io.h> |
2 | |
3 | #ifndef F_CPU
|
4 | #warning "F_CPU was not defined"
|
5 | #define F_CPU 18432000UL
|
6 | #endif
|
7 | |
8 | |
9 | #include <util/delay.h> |
10 | #include <avr/interrupt.h> |
11 | #include <inttypes.h> |
12 | #include <stdio.h> |
13 | #include <stdint.h> |
14 | #include <stdlib.h> |
15 | |
16 | #define BAUD 115200
|
17 | #define UART_BUFFER_SIZE 3
|
18 | |
19 | #define IRQS_PER_SECOND 0.2
|
20 | |
21 | #include <util/setbaud.h> |
22 | |
23 | /*=============================================================================
|
24 | GLOBAL VARIABLES
|
25 | =============================================================================*/
|
26 | |
27 | volatile char uart_buffer[UART_BUFFER_SIZE]={'v', 'v', 'v'}; |
28 | volatile int8_t uart_count = 0; |
29 | //Variablen für die Zeit
|
30 | volatile unsigned int millisekunden; |
31 | volatile unsigned int sekunde; |
32 | volatile unsigned int minute; |
33 | volatile unsigned int stunde; |
34 | |
35 | |
36 | |
37 | /*=============================================================================
|
38 | SUBROUTINES
|
39 | =============================================================================*/
|
40 | |
41 | void uart_putc(char c) |
42 | //send single character
|
43 | {
|
44 | while (!(UCSRA & (1<<UDRE))); |
45 | UDR = c; |
46 | }
|
47 | |
48 | void uart_puti8(uint8_t c) |
49 | //send 8 bit unsigned integer
|
50 | {
|
51 | while (!(UCSRA & (1<<UDRE))); |
52 | UDR = c; |
53 | }
|
54 | |
55 | void uart_puti16(int16_t c) |
56 | // send 16bit signed integer
|
57 | {
|
58 | while (!(UCSRA & (1<<UDRE))); |
59 | UDR = c; //lowbyte |
60 | while (!(UCSRA & (1<<UDRE))); |
61 | UDR = (c >> 8); //highbyte |
62 | }
|
63 | |
64 | void uart_puts(char *data) |
65 | //send stiring via usart
|
66 | {
|
67 | while(*data) |
68 | {
|
69 | uart_putc(*data); |
70 | data++; |
71 | }
|
72 | }
|
73 | |
74 | void uart_puti(int16_t value) |
75 | //send integer as sting
|
76 | {
|
77 | char s[5]; |
78 | |
79 | sprintf(s,"%u",value); |
80 | uart_puts(s); |
81 | }
|
82 | |
83 | inline void uart_init(void) |
84 | //initailize uart communication
|
85 | {
|
86 | //set baudrate
|
87 | |
88 | |
89 | UBRRH = UBRRH_VALUE; |
90 | UBRRL = UBRRL_VALUE; |
91 | |
92 | #if USE_2X
|
93 | UCSRA |= (1<<U2X); |
94 | #else
|
95 | UCSRA &= ~(1<<U2X); |
96 | #endif
|
97 | |
98 | UCSRB |= (1<<RXCIE) | (1<<TXEN) | (1<<RXEN); //enable transmit, receive, interrupt |
99 | UCSRC |= (1<< URSEL) | (1<<UCSZ1) | (1<<UCSZ0); //8N1 |
100 | |
101 | sei(); //global interrupt enable |
102 | |
103 | //send welcomestring 36 chars
|
104 | _delay_ms(10); |
105 | uart_puts("currentbox - initialisation complete"); |
106 | }
|
107 | |
108 | |
109 | |
110 | /* ADC initialisieren */
|
111 | void ADC_Init_saxi(void) { |
112 | |
113 | uint16_t result; |
114 | |
115 | // ADMUX = (0<<REFS1) | (1<<REFS0); // AVcc als Referenz benutzen
|
116 | ADMUX = (0<<REFS1) | (0<<REFS0); // externe Referenzspannung nutzen |
117 | ADCSRA = (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler |
118 | ADCSRA |= (1<<ADEN); // ADC aktivieren |
119 | |
120 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
|
121 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
122 | |
123 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung |
124 | while (ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten |
125 | /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
|
126 | Wandlung nicht übernommen. */
|
127 | result = ADCW; |
128 | }
|
129 | |
130 | /* ADC Einzelmessung */
|
131 | uint16_t ADC_Read_saxi( uint8_t channel ) |
132 | {
|
133 | // Kanal waehlen, ohne andere Bits zu beeinflußen
|
134 | if (channel == 1) { |
135 | ADMUX = (ADMUX & ~(0x1F)) | 0x00; // alle Kanäle rücksetzen und gewünschten Kanal dazu odern; |
136 | } else if (channel == 2) { |
137 | ADMUX = (ADMUX & ~(0x1F)) | 0x01; |
138 | }
|
139 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion" |
140 | while (ADCSRA & (1<<ADSC) ) {} // auf Abschluss der Konvertierung warten |
141 | return ADCW; // ADC auslesen und zurückgeben |
142 | }
|
143 | |
144 | |
145 | /* Beispielaufrufe: */
|
146 | |
147 | int main() |
148 | {
|
149 | uint16_t adcvals, adcvalc; |
150 | //float uref = 5.2; // Spannungsversorgung usb Schnittstelle
|
151 | //float us = 0;
|
152 | //float uc = 0;
|
153 | uint8_t state = 0; |
154 | |
155 | |
156 | |
157 | |
158 | |
159 | ADC_Init_saxi(); |
160 | uart_init(); // Kommunikation mit Matlab |
161 | |
162 | DDRB=0xFF; |
163 | |
164 | // Timer 1 konfigurieren
|
165 | TCCR1A = 0; // CTC Modus |
166 | |
167 | #if defined (CTC1) && !defined (WGM12)
|
168 | TCCR1B = (1 << CTC1) | (1 << CS10) | (1 << CS12); |
169 | #elif !defined (CTC1) && defined (WGM12)
|
170 | TCCR1B = (1 << WGM12) | (1 << CS10) | (1 << CS12); |
171 | #else
|
172 | #error Keine Ahnung, wie Timer1 fuer diesen AVR zu initialisieren ist!
|
173 | #endif
|
174 | |
175 | |
176 | OCR1A = (unsigned short) ((unsigned long) F_CPU / (1024*IRQS_PER_SECOND)-1); |
177 | |
178 | #if defined (TIMSK1)
|
179 | TIMSK1 |= (1 << OCIE1A); |
180 | #elif defined (TIMSK)
|
181 | TIMSK |= (1 << OCIE1A); |
182 | #else
|
183 | #error Keine Ahnung, wie IRQs fuer diesen AVR zu initialisieren sind!
|
184 | #endif
|
185 | |
186 | |
187 | |
188 | |
189 | |
190 | // Compare Interrupt erlauben
|
191 | //TIMSK |= (1<<OCIE1A);
|
192 | |
193 | // Global Interrupts aktivieren
|
194 | sei(); |
195 | |
196 | |
197 | while( 1 ) { |
198 | switch(state) |
199 | {
|
200 | case 0: |
201 | if(uart_count!=0) |
202 | {
|
203 | if(uart_buffer[0]=='t') |
204 | {
|
205 | state = 1; |
206 | }
|
207 | else if(uart_buffer[0]=='u') |
208 | {
|
209 | state = 2; |
210 | }
|
211 | if(uart_buffer[0] =='s') |
212 | state = 3; |
213 | }
|
214 | break; |
215 | case 1: |
216 | adcvals = ADC_Read_saxi(1); // Kanal 0 |
217 | uart_puti16(adcvals); |
218 | uart_buffer[0]=uart_buffer[1]; |
219 | uart_buffer[1]=uart_buffer[2]; |
220 | uart_count--; |
221 | state = 0; |
222 | break; |
223 | case 2: |
224 | adcvalc = ADC_Read_saxi(2); // Kanal 1 |
225 | uart_puti16(adcvalc); |
226 | uart_buffer[0]=uart_buffer[1]; |
227 | uart_buffer[1]=uart_buffer[2]; |
228 | uart_count--; |
229 | state = 0; |
230 | break; |
231 | case 3: |
232 | uart_puti16(sekunde); |
233 | uart_buffer[0]=uart_buffer[1]; |
234 | uart_buffer[1]=uart_buffer[2]; |
235 | uart_count--; |
236 | state = 0; |
237 | break; |
238 | default:
|
239 | state = 0; |
240 | uart_count = 0; |
241 | break; |
242 | }//switch |
243 | |
244 | |
245 | }//while |
246 | }
|
247 | |
248 | /*=============================================================================
|
249 | INTERRUPT SERVICE ROUTINES
|
250 | =============================================================================*/
|
251 | |
252 | ISR(USART_RXC_vect) // isr for usart receive |
253 | {
|
254 | if (uart_count < UART_BUFFER_SIZE) uart_buffer[uart_count] = UDR; //protect overwriting/overflow |
255 | uart_count++; |
256 | }
|
257 | |
258 | |
259 | ISR (TIMER1_COMPA_vect) |
260 | {
|
261 | millisekunden= millisekunden+1000; |
262 | if(millisekunden == 1000) |
263 | {
|
264 | sekunde++; |
265 | millisekunden = 0; |
266 | if(sekunde == 60) |
267 | {
|
268 | minute++; |
269 | sekunde = 0; |
270 | }
|
271 | if(minute == 60) |
272 | {
|
273 | stunde++; |
274 | minute = 0; |
275 | }
|
276 | if(stunde == 24) |
277 | {
|
278 | stunde = 0; |
279 | }
|
280 | }
|
281 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.