ADC_LCD_IO.c


1
// 
2
//    Anpassungen im makefile:
3
//    ATMega8 => MCU=atmega8 im makefile einstellen
4
//    lcd-routines.c in SRC = ... Zeile anhängen
5
// 
6
#include <avr/io.h>
7
#include <util/delay.h>
8
#include "lcd-routines.h"
9
#include "ADC.c"
10
#include <stdlib.h> 
11
12
int main(void)
13
{
14
  // fuer Rueckgabe ADC-Wert
15
  uint16_t adcval; 
16
  
17
  // fuer Timer/ Zaehler
18
  uint8_t teiler=0x00;
19
  uint8_t sec = 0;
20
  uint8_t min = 0;
21
  uint16_t std=0;
22
  uint8_t zaehler_1=0;
23
  
24
  struct
25
  {
26
    unsigned hold:1; // hold für zaehlen Impulse PC1
27
    unsigned b1:1;
28
    unsigned b2:1;
29
    unsigned b3:1;
30
    unsigned b4:1;
31
    unsigned b5:1;
32
    unsigned b6:1;
33
    unsigned b7:1;
34
  } bin;
35
  
36
  // buffer fuer Konvertierung value to char
37
  char buf[5];  
38
  
39
  //set PORTD for output: DDRD = 0xFF;
40
  DDRD = 0xFF;
41
  
42
  // folgende Zeilen sind für das LCD-Dicplay
43
  lcd_init();
44
  
45
  // TimerCounterControlRegister, setze Timer auf CPU-Takt/1024 = 15625
46
  TCCR0 = (1<<CS02) | (0<<CS01) | (1<<CS00);
47
  /*
48
    Der Zähler zählt nun aufwärts bis 255, um dann wieder bei 0 zu beginnen. Der aktuelle Zählerstand steht in TCNT0. Bei jedem Überlauf von 255 auf 0 wird das
49
    Timer Overflow Flag TOV0 im Timer Interrupt Flag TIFR-Register gesetzt und, falls so konfiguriert, ein entsprechender Timer-Overflow-Interrupt ausgelöst
50
    und die daran gebundene Interrupt-Routine abgearbeitet. Das TOV Flag lässt sich durch das Hineinschreiben einer 1 und nicht wie erwartet einer 0 wieder
51
    zurücksetzen.
52
    */
53
  
54
  // set PC1 for digital input
55
  DDRC &= ~( 1 << PC1 );                 /* PIN PC1 auf Eingang (Taster)            */
56
  PORTC |= ( 1 << PC1 );                 /* Pullup-Widerstand aktivieren            */
57
58
  
59
  while(1)
60
  {
61
    if (TIFR == (1<<TOV0))
62
    {
63
      // diese Routine wird alle 16384us aufgerufen
64
      // dies ergibt sich aus: 16Mhz=0.0625us
65
      // 8Bit-Timer: 0.0625us*8=16us
66
      // 1024 Prescaler: 16us*1024=16384us
67
      teiler ++;
68
      TIFR |= (1<<TOV0);
69
      
70
      // zaehlen Impulse PC1
71
      if (PINC & ( 1 << PC1))
72
      {
73
        if (!bin.hold)
74
        {
75
          bin.hold = 1;
76
          zaehler_1 ++;
77
        }
78
      }
79
      else
80
      {
81
        bin.hold = 0;
82
      }
83
    }
84
    switch (teiler)
85
    {
86
      case 11:      // Aufruf 1* pro sec
87
        // wechseln des Zusandes PORTD.6
88
        PORTD ^= (1<<6);
89
        teiler ++;
90
        break;
91
      
92
      case 22: // Aufruf 1* pro sec
93
        // lesen Analog Channel 0 (10Bit)
94
        adcval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0  -> PC0*/
95
        teiler ++;
96
        break;
97
    
98
      case 33: // Aufruf 1* pro sec
99
        if ( sec % 2 ) // sekünliche Abwechslung der Ausgabe
100
        {
101
          //   Ausgabe des ADC-Messwertes auf dem Display
102
          utoa( 4.8876 * adcval, buf, 10); // Messbereichsendwert: 5000mVolt, Auflösung 10Bit=1023
103
          set_cursor(0,2);
104
          lcd_string("=>_____mVolt");
105
          set_cursor(0,2);     // Spalte 2, Zeile 2
106
          lcd_string(buf);     // write ADC-mV to display
107
        }
108
        else
109
        {
110
          // Ausgabe des Zaehler PinC.1 auf dem Display
111
          utoa( zaehler_1, buf, 10);
112
          set_cursor(0,2);
113
          lcd_string("=>_____Zaehler1");
114
          set_cursor(0,2);     // Spalte 2, Zeile 2
115
          lcd_string(buf);     // write ADC-mV to display
116
        }
117
        teiler ++;
118
        break;     
119
    
120
      case 44: // Aufruf 1* pro sec
121
        // Ausgabe des Timer 0 auf dem Display
122
        set_cursor(0,1);
123
        lcd_string("________________");
124
        
125
        utoa( sec, buf, 10); // convert uint to char
126
        set_cursor(10,1);     // Spalte 8, Zeile 1
127
        lcd_string(buf);     // write ADC-value to display
128
      
129
        utoa( min, buf, 10); // convert uint to char
130
        set_cursor(5,1);     // Spalte 8, Zeile 1
131
        lcd_string(buf);     // write ADC-value to display
132
      
133
        utoa( std, buf, 10); // convert uint to char
134
        set_cursor(0,1);     // Spalte 8, Zeile 1
135
        lcd_string(buf);     // write ADC-value to display
136
      
137
        teiler ++;
138
        break;
139
    
140
      case 55: // Aufruf 1* pro sec
141
        // wechseln des Zusandes PORTD.6
142
        PORTD ^= (1<<6);
143
        teiler ++;
144
        break;
145
    
146
      case 66: // Aufruf 1* pro sec
147
        // nun ist eine Sekunde vergangen
148
        // erhöhe den Sekundenzähler
149
        teiler = 0;
150
        sec ++;
151
      
152
        if (sec==60)
153
        {
154
          min ++;
155
          sec = 0;
156
        }
157
      
158
        if (min==60)
159
        {
160
          std ++;
161
          min = 0;
162
        }
163
    }
164
    //_delay_ms(500);
165
  }
166
  return 0;
167
}
168
169
170
/*
171
ab hier der Quellcode von ADC.c
172
173
174
175
// Analog-Wert einlesen an PC1/adc1
176
// Fuer ATmega8 mit 16Mhz externes Quarz
177
// AVCC als Referenz
178
// Grosam 13.10.2008
179
180
uint16_t ReadChannel(uint8_t mux)
181
{
182
  uint8_t i;
183
  uint16_t adcwert;
184
  
185
  ADMUX = (mux);             //setze Bit für ADC Multiplexer Select Register, Kanal PC1 aktiviert
186
  ADMUX |= (1<<REFS0) | (0<<REFS1);   //VCC als Referenz
187
  
188
  ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<< ADPS0);  //16000000/128=125kHz
189
  // ADEN (ADC Enable) 
190
  // ADPS2...ADPS0 (ADC Prescaler Select Bits) Teilungsfaktor für ADC-Takt
191
  
192
  // nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
193
  // also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" 
194
  ADCSRA |= (1<<ADSC);            //setze Bit für ADSC (ADC Start Conversion) 
195
  while (ADCSRA & (1<<ADSC) ) {
196
    ;                              // auf Abschluss der Konvertierung warten 
197
  }
198
  adcwert = ADCW;                  //16Bit ADC-Wert
199
200
  //Richtiges Readout
201
202
  // Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen 
203
  adcwert = 0; 
204
  for( i=0; i<4; i++ )
205
  {
206
    ADCSRA |= (1<<ADSC);         //setze Bit für ADSC (ADC Start Conversion) eine Wandlung "single conversion"
207
    while (ADCSRA & (1<<ADSC) ) {
208
      ;                          // auf Abschluss der Konvertierung warten 
209
    }
210
    adcwert += ADCW;             //16Bit ADC-Wert
211
  }
212
  ADCSRA &= ~(1<<ADEN);         // ADC deaktivieren (2)
213
  
214
  adcwert /= 4; // Summe durch vier teilen = arithm. Mittelwert
215
  
216
  return adcwert;
217
}
218
*/