Hallo, ich habe ein Problem mit der AD-Wandlung beim ATtiny13 bzw. spielen meine zwei Funktionen errückt, wenn ich den ADC mitlaufen lasse. Ich möchte an PB3 (ADMUX=11) die Batteriespannung messen. Leider bekomme ich das nicht mehr hin. Ich hatte eine erste Messung auf einem ATmega8 hinbekommen und ich bin auch der Meinung, dass es bei dem ATtiny als DIP Version auch schon funktionierte. Jetzt habe ich eine Platine angefertigt und den Quelltext angepasst. Jedoch funktioniert die Messung nicht mehr richtig. Beide Funktionen (Lauflicht und Blicklicht) funktionieren einzelt, wenn diese aufgerufen werden (die Andere auskommentieren oder wenn ich für result einen Wert einsetze), jedoch wenn diese zusammen über dem ADC ausgewählt werden sollen (Größer / Kleiner als 410), dann laufen beide Funktionen in einander ab.
1 | //ICC-AVR application builder :
|
2 | // Target : T13
|
3 | // Crystal: 9.6000Mhz
|
4 | |
5 | #include <iot13v.h> |
6 | #include <macros.h> |
7 | |
8 | unsigned char count10 = 0; |
9 | unsigned char countV = 0; |
10 | unsigned char blink_state = 0; |
11 | unsigned char countLED = 0; |
12 | unsigned char i = 0; |
13 | unsigned int result; |
14 | |
15 | /* PORT-Zuweisung */
|
16 | |
17 | //#define PB5
|
18 | #define R_LED4 PB4
|
19 | //#define AD_W PB3
|
20 | #define R_LED1 PB2
|
21 | #define R_LED2 PB1
|
22 | #define R_LED3 PB0
|
23 | |
24 | void port_init(void) |
25 | {
|
26 | PORTB = (1<<PB5)|(1<<PB3); |
27 | DDRB = (1<<DDB4)|(1<<DDB2)|(1<<DDB1)|(1<<DDB0); |
28 | }
|
29 | |
30 | //TIMER0 initialize - prescale:1024
|
31 | // WGM: Normal
|
32 | // desired value: 10mSec
|
33 | // actual value: 9,920mSec (0,8%)
|
34 | void timer0_init(void) |
35 | {
|
36 | TCCR0B = 0x00; //stop |
37 | OCR0A = 0x5D; |
38 | OCR0B = 0x5D; |
39 | TCNT0 = 0xA3; //set count |
40 | TCCR0A = 0x00; |
41 | TCCR0B = 0x05; //start timer |
42 | |
43 | }
|
44 | |
45 | #pragma interrupt_handler timer0_ovf_isr:iv_TIM0_OVF
|
46 | void timer0_ovf_isr(void) |
47 | {
|
48 | TCNT0 = 0xA3; //reload counter value |
49 | ADW(); |
50 | // result = 411;
|
51 | if (result <= 410) {Warning();} |
52 | if (result > 410) {rul();} |
53 | }
|
54 | |
55 | |
56 | //ADC initialize
|
57 | // Conversion time: 104uS
|
58 | void adc_init(void) |
59 | {
|
60 | ADCSRA = 0x00; //disable adc |
61 | ADMUX = 0x00; |
62 | ACSR = 0x80; |
63 | ADCSRB = 0x00; |
64 | ADCSRA = 0x86;//01 |
65 | }
|
66 | |
67 | void rul(void) |
68 | {
|
69 | } // |
70 | |
71 | void Warning(void) |
72 | {
|
73 | }
|
74 | |
75 | void ADW(void) |
76 | {
|
77 | //----------------------------------------------------------------------------//
|
78 | // AD-Wandlung
|
79 | //----------------------------------------------------------------------------//
|
80 | // Dummy-Readout
|
81 | ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1); // ADC aktivieren, Frequenzvorteiler: setzen auf 64 (8 MHz / 64 = 125 kHz) und ADC aktivieren |
82 | ADMUX = 0x11; // Kanal waehlen (ADC3) |
83 | ADMUX |= (1<<REFS0); // interne Referenzspannung nutzen |
84 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung |
85 | while(!(ADCSRA & (1<<ADIF))); // auf Abschluss der Konvertierung warten (ADIF-bit) |
86 | result = ADC; // ADC muss einmal gelesen werden, |
87 | // sonst wird Ergebnis der nächsten Wandlung
|
88 | // nicht übernommen.
|
89 | |
90 | //ADC-Messung mit arithmetischen Mittel aus 4 Messungen
|
91 | result = 0; |
92 | for (i=0;i<4;i++) |
93 | {
|
94 | ADCSRA |= (1<<ADSC); // Messung ausfuehren |
95 | while ( ADCSRA & (1<<ADSC) ); // Konvertierung abwarten |
96 | result += ADC; // aufaddieren zur Mittelwertbildung (ADC auslesen der zwei Bits |
97 | }
|
98 | ADCSRA &= ~(1<<ADEN); // ADC ausschalten |
99 | |
100 | result /= 4; // |
101 | |
102 | }
|
103 | |
104 | |
105 | |
106 | //call this routine to initialize all peripherals
|
107 | void main(void) |
108 | {
|
109 | //stop errant interrupts until set up
|
110 | CLI(); //disable all interrupts |
111 | port_init(); |
112 | timer0_init(); |
113 | adc_init(); |
114 | |
115 | MCUCR = 0x00; |
116 | TIMSK0 = 0x02; //timer interrupt sources |
117 | GIMSK = 0x00; //interrupt sources |
118 | SEI(); //re-enable interrupts |
119 | //all peripherals are now initialized
|
120 | |
121 | while(1); |
122 | }
|
Auch wenn ich
1 | if (result <= 410) {Warning();} |
2 | else{rul();} |
statt der zwei if-Abfragen einsetze spielen diese verrückt. Habe ich bei der AD-Wandlung einen Gedankenfehler (läuft diese so schnell ab, dass mehere Ergebnisse Zustande kommen)oder woran könnte das liegen? Vielen Dank für eure Tipps.