eRTK
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
adc.c
Go to the documentation of this file.
1 /*
2  * adc.c
3  *
4  * Created: 27.05.2015 12:57:21
5  * Author: er
6  */
7 #include "eRTK.h"
8 #include "adc.h"
9 
10 /*
11  Der ADC wird von einer Sequencer Liste gesteuert.
12  Die Sequenz wird vom System Timer angestossen und lauft bis zum Ende durch.
13  In der Liste stehen Bloecke vom Typ <tadu>, jeder steuert einen separaten ADC Kanal.
14  In jedem Block wird ein Zaehler erhoeht und falls dieser den Scalerwert erreicht startet dieser Kanal.
15  Im anderen Falle wird weitergeschaltet bis zum Ende der Liste.
16  Wird ein arbeitsbereiter Block gefunden wird der zugehoerige Kanal zur Wandlung gestartet.
17  Nach Ablauf jeder Wandlung startet die "End of Conversion" Interrupt Prozedur und schaltet auf den naechsten Block weiter.
18  Am Ende eines Durchlaufes wird dann im Timerinterrupt die Liste neu gestartet.
19 
20  Bei 125k adc Takt dauert eine Wandlung etwa 104us.
21  Wenn der Sequencer also alle 1000us==1/1000Hz gestartet wird so sind 9 Wandlungen moeglich.
22 
23  Der erlaubte Takt des ADC liegt max. bei 200kHz (2Bit) oder bis 1MHz bei verringerter Genauigkeit (3Bit)
24  bei F_CPU von 16MHz gibt es folgenden Zusammenhang:
25  Scaler ADC-Clock Conversion Time ADPS2 ADPS1 ADPS0
26  /128 125k 104us 1 1 1
27  /64 250k 52us 1 1 0
28  /32 500k 26us 1 0 1
29  /16 1M 13us 1 0 0
30 
31 */
32 
33 
34 
35 /*
36 messzeitpunkte bei verschiedenen scaler einstellungen und anzahl messungen pro zeitpunkt:
37 
38 time[ms] scaler=1 scaler=2 scaler=3 scaler=4 scaler=5 scaler=6 scaler=7 scaler=8 scaler=9 scaler=10 cnt gesamtdauer
39 0 1 0 0 0 0 0 0 0 0 0 1 104us
40 1 1 1 0 0 0 0 0 0 0 0 2 208us
41 2 1 0 1 0 0 0 0 0 0 0 2 208us
42 3 1 1 0 1 0 0 0 0 0 0 3 312us
43 4 1 0 0 0 1 0 0 0 0 0 2 208us
44 5 1 1 1 0 0 1 0 0 0 0 4 416us
45 6 1 0 0 0 0 0 1 0 0 0 2 208us
46 7 1 1 0 1 0 0 0 1 0 0 4 416us
47 8 1 0 1 0 0 0 0 0 1 0 3 312us
48 9 1 1 0 0 1 0 0 0 0 1 4 416us
49 10 1 0 0 0 0 0 0 0 0 0 1 104us
50 11 1 1 1 1 0 1 0 0 0 0 5 520us
51 12 1 0 0 0 0 0 0 0 0 0 1 104us
52 13 1 1 0 0 0 0 1 0 0 0 3 312us
53 14 1 0 1 0 1 0 0 0 0 0 3 312us
54 15 1 1 0 1 0 0 0 1 0 0 4 416us
55 16 1 0 0 0 0 0 0 0 0 0 1 104us
56 17 1 1 1 0 0 1 0 0 1 0 5 520us
57 18 1 0 0 0 0 0 0 0 0 0 1 104us
58 19 1 1 0 1 1 0 0 0 0 1 5 520us
59 */
60 
61 static tadc * padc_active; //aktuell wandelnder adc kanal
62 
63 #if defined (__AVR_ATmega2560__)
64 ISR( ADC_vect ) { //adc interrupt
65  uint8_t m_ready=0;
66  if( padc_active<adc_cntrl+ANZ_ADC ) {
67  padc_active->value=ADCW;
68  uint8_t tid=padc_active->tid;
69  if( tid ) { //falls ein task suspendiert wartet
70  padc_active->tid=0; //event loeschen
71  m_ready=1;
72  eRTK_SetReady( tid ); //dann aktivieren
73  }
74  //weiterschalten bis zum naechsten bereiten block oder ende der liste
75  while( 1 ) {
76  if( ++padc_active>=adc_cntrl+ANZ_ADC ) { //listenende erreicht
77  padc_active=adc_cntrl;
78  break;
79  }
80  else {
81  ++padc_active;
82  if( ++( padc_active->cnt ) >= padc_active->scaler ) { //adc kanal starten
83  padc_active->cnt=0;
84  ADMUX=( padc_active->mux&0x07 ) | padc_active->ref;
85  if( padc_active->mux<=7 ) ADCSRB&=~( 1<<MUX5 );
86  else ADCSRB|=( 1<<MUX5 );
87  ADCSRA|=( 1<<ADSC );
88  break;
89  }
90  }
91  }
92  }
93  else padc_active=adc_cntrl;
94  if( m_ready ) eRTK_scheduler(); //scheduling durchfuehren falls eine task aktiviert wurde
95  }
96 
97 uint8_t adc_sequencer( void ) { //soll im system timer interrupt DISABLED aufgerufen werden
98  if( padc_active==adc_cntrl ) {
99  //finde startklaren adc kanal
100  while( padc_active < adc_cntrl+ANZ_ADC ) {
101  if( ++( padc_active->cnt ) >= padc_active->scaler ) { //adc kanal starten
102  padc_active->cnt=0;
103  ADMUX=( padc_active->mux&0x07 ) | padc_active->ref;
104  if( padc_active->mux<=7 ) ADCSRB&=~( 1<<MUX5 );
105  else ADCSRB|=( 1<<MUX5 );
106  ADCSRA|=( 1<<ADSC );
107  break;
108  }
109  ++padc_active;
110  }
111  return !0;
112  }
113  else return 0;
114  }
115 
116 void adc_init( void ) { //beim hochlauf aufzurufen
117  ADMUX = 0; //Kanal waehlen 0-7
118  ADMUX |= /*(1<<REFS1) |*/ (1<<REFS0); // avcc Referenzspannung nutzen
119  ADCSRA = (1<<ADIE)|(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); //Frequenzvorteiler setzen auf %128, ADC aktivieren, int aktivieren
120  padc_active=adc_cntrl;
121  }
122 #endif
123 
124 uint16_t adc_get( uint8_t mux ) { //holen des aktuellen wandlungswertes
125  uint16_t val=-1;
126  register tadc * padc=adc_cntrl;
127  while( padc<adc_cntrl+ANZ_ADC ) {
128  if( padc->mux==mux ) {
129  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
130  val=padc->value;
131  break;
132  }
133  }
134  ++padc;
135  }
136  return val;
137  }
138 
139 uint16_t adc_wait( uint8_t mux ) { //warten bis auf diesem kanal eine neue messung vorliegt und dann liefern
140  register tadc * padc=adc_cntrl;
141  while( padc<adc_cntrl+ANZ_ADC ) {
142  if( padc->mux==mux ) { //dieser kanal
143  uint8_t tid=eRTK_GetTid();
144  uint8_t m_sc;
145  ATOMIC_BLOCK( ATOMIC_RESTORESTATE ) {
146  padc->tid=tid;
147  m_sc=padc->scaler;
148  if( !m_sc ) {
149  padc->scaler=1; //damit er im naechsten takt wandelt
150  }
151  eRTK_SetSuspended( tid );
152  eRTK_scheduler();
153  }
154  padc->scaler=m_sc;
155  return padc->value;
156  }
157  ++padc;
158  }
160  return 0;
161  }
162 
uint8_t eRTK_GetTid(void)
Definition: eRTK.c:233
uint8_t cnt
Definition: adc.h:23
uint8_t scaler
Definition: adc.h:22
ISR(USART0_RX_vect)
Definition: uart.c:104
uint16_t adc_wait(uint8_t mux)
Definition: adc.c:139
#define ANZ_ADC
Definition: adc.h:18
uint8_t ref
Definition: adc.h:21
Definition: adc.h:19
void eRTK_SetReady(uint8_t tid)
Definition: eRTK.c:238
void deadbeef(tsys reason)
void eRTK_SetSuspended(uint8_t tid)
Definition: eRTK.c:255
void adc_init(void)
tadc adc_cntrl[ANZ_ADC]
Definition: main.c:77
uint8_t tid
Definition: adc.h:25
uint16_t value
Definition: adc.h:24
uint8_t adc_sequencer(void)
uint8_t mux
Definition: adc.h:20
uint16_t adc_get(uint8_t mux)
Definition: adc.c:124