Hallo,
ich habe angefangen erstmals einen xmega, genauer einen ATxmega128A4,
zu programmieren jedoch scheitere ich am ADC.
Ich habe es bereits geschafft den µC auf 12 MHz mit Hilfe des internen
Oszillators zu takten, einen Timer einzustellen und mit dem USART Daten
an meinen PC zu senden.
Es geht darum einen Spannungswert an PA0 zu messen und das 12 bit
Ergebniss
an den PC zu senden nur das funktioniert nicht so wie ich mir das
vorgestellt habe.
Wenn ich am PC in meinem Terminalprogramm den ADC Wert anschaue
wenn ich den Pin PA0 auf Masse ziehe, dann kommt eine binäre Zahl
zwischen
0000100000100100 (=2084) und 0000100000011111 (=2079) dabei raus.
Normalerweise müsste mir doch 0 angezeigt werden, oder?
Hier mal der Code:
1 | #ifndef F_CPU
|
2 | #define F_CPU 12000000UL
|
3 | #endif
|
4 |
|
5 | #include <avr/io.h>
|
6 | #include <avr/interrupt.h>
|
7 |
|
8 | uint8_t adc_val_h;
|
9 | uint8_t adc_val_l;
|
10 |
|
11 | int main(void)
|
12 | {
|
13 |
|
14 | //Clock Init
|
15 |
|
16 | OSC.PLLCTRL = OSC_PLLSRC_RC2M_gc | 0x06; //PLL on 2 MHz Internal Oscillator | PLL Factor = 6
|
17 | OSC.CTRL |= OSC_PLLEN_bm; //PLL Enable
|
18 | while (!(OSC.STATUS & (OSC_PLLRDY_bm))); //Wait till the PLL is Ready
|
19 | CCP = CCP_IOREG_gc; //Save I/O Register
|
20 | CLK.CTRL |= CLK_SCLKSEL_PLL_gc; //System Clock Selection = PLL
|
21 |
|
22 | //Timer C0 10 ms
|
23 | TCC0.CTRLA = TC_CLKSEL_DIV256_gc; //Prescaler = 256
|
24 | TCC0.CTRLB = TC_WGMODE_FRQ_gc; //Frequency Mode
|
25 | TCC0.CCA = 469-1;
|
26 | TCC0.INTCTRLB |= TC_CCAINTLVL_HI_gc; //Compare or Capture A Interrupt high level
|
27 |
|
28 | //USART C0
|
29 | PORTC.DIR |= PIN3_bm; //TxD Pin (PC3) = Output
|
30 | PORTC.OUT |= PIN3_bm; //TxD Pin (PC3) = High
|
31 | USARTC0.CTRLB |= USART_CLK2X_bm; //Double Transmission Speed
|
32 | USARTC0.BAUDCTRLA = 38; //Baud = 38400
|
33 | USARTC0.CTRLC = USART_CHSIZE_8BIT_gc; //Character Size = 8-bit
|
34 | USARTC0.CTRLB |= USART_RXEN_bm; //Receiver enable
|
35 | USARTC0.CTRLB |= USART_TXEN_bm; //Transmitter enable
|
36 |
|
37 | //ADC
|
38 | PORTA.DIR &= ~PIN0_bm; //PA0 = Input
|
39 | ADCA.REFCTRL |= ADC_BANDGAP_bp; //Enable Bandgapvoltage
|
40 | ADCA.REFCTRL |= ADC_REFSEL_INT1V_gc; //Reference = 1V Bandgapvoltage
|
41 | ADCA.PRESCALER |= ADC_PRESCALER_DIV256_gc; //Prescaler = 256
|
42 | ADCA.CH0.INTCTRL |= ADC_CH_INTLVL_HI_gc; //High Level Interrupt
|
43 | ADCA.EVCTRL |= ADC_EVACT_CH0_gc; //Event Mode Select = CH0
|
44 | ADCA.CTRLB |= ADC_FREERUN_bm; //Free Running Mode
|
45 | ADCA.CTRLA |= ADC_ENABLE_bm; //ADC Enable
|
46 |
|
47 | //Other Settings
|
48 | PMIC.CTRL |= PMIC_HILVLEN_bm | PMIC_LOLVLEN_bm | PMIC_MEDLVLEN_bm; //Enable all levels of Interrupts
|
49 | sei(); //Enable global Interrupts
|
50 |
|
51 |
|
52 | //PORTD.DIR |= PIN2_bm;
|
53 |
|
54 |
|
55 | while(1)
|
56 | {
|
57 |
|
58 | }
|
59 | }
|
60 |
|
61 | ISR (TCC0_CCA_vect) {
|
62 |
|
63 | if (USARTC0.STATUS & (USART_DREIF_bm)) {
|
64 | USARTC0.DATA = adc_val_h;
|
65 | }
|
66 |
|
67 | while (!(USARTC0.STATUS & (USART_DREIF_bm)));
|
68 |
|
69 | USARTC0.DATA = adc_val_l;
|
70 | }
|
71 |
|
72 | ISR (ADCA_CH0_vect) {
|
73 |
|
74 | adc_val_h = (ADCA_CH0RES >> 8);
|
75 | adc_val_l = ADCA_CH0RES;
|
76 | }
|
Könnt ihr mir sagen was ich falsch gemacht habe?
Gruß Alex