Forum: Mikrocontroller und Digitale Elektronik StartUp atmega8 und AVR-Studio


von Martin K. (seesharp1)


Lesenswert?

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

von Kevin K. (nemon) Benutzerseite


Lesenswert?

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.

von Martin K. (seesharp1)


Lesenswert?

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?

von Harald M. (mare_crisium)


Lesenswert?

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

von Thomas F. (igel)


Lesenswert?

> 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.

von Martin K. (seesharp1)


Lesenswert?

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
Noch kein Account? Hier anmelden.