Hallo, zur Zeit möchte ich über einen STM32F3 4 Kanäle eines ADCs zyklisch auslesen. Dazu wird der ADC über den TIM3 über TRGO getriggert.
1 | void TIM3_Init() |
2 | {
|
3 | //Timer zum Triggern des ADCs bei bestimmter Frequenz über TRGO
|
4 | |
5 | TIM3->PSC = 0; //Prescaler |
6 | TIM3->ARR = 72-1; //Auto Reload |
7 | TIM3->CNT = 0; //Count |
8 | TIM3->CR1 = 1; //Control Reg |
9 | TIM3->CCR1= 36; //Capture Compare |
10 | |
11 | SET_BIT(TIM3->CR2, TIM_CR2_MMS_1); //TRGO |
12 | |
13 | |
14 | SET_BIT(TIM3->CR1, TIM_CR1_CEN); //Timer Enable |
15 | }
|
Der ADC soll die Kanäle 1 bis 4 nacheinander auslesen. Nach jeder Messung soll der Wert mittels DMA in den Speicher abgelegt werden. Das soll für alle 4 Werte gemacht werden. Erst wenn TIM3 wieder auslöst soll der Zyklus erneut beginnen.
1 | static void ADC1_Init(void) |
2 | {
|
3 | //sicher gehen, dass Clock gesetzt ist
|
4 | SET_BIT(RCC->AHBENR, RCC_AHBENR_ADC12EN); |
5 | |
6 | //ADC1 disablen
|
7 | if(READ_BIT(ADC1->ISR, ADC_ISR_ADRDY)) |
8 | {
|
9 | SET_BIT(ADC1->ISR, ADC_ISR_ADRDY); |
10 | }
|
11 | if(READ_BIT(ADC1->CR, ADC_CR_ADEN)) |
12 | {
|
13 | SET_BIT(ADC1->CR, ADC_CR_ADDIS); |
14 | }
|
15 | |
16 | //Warten bis ADC1 komplett disabled ist
|
17 | while(READ_BIT(ADC1->CR, ADC_CR_ADEN)) {} |
18 | |
19 | //ADC1 voltage regulator enablen
|
20 | //Enable sequence im Reference sheet (Seite 219)
|
21 | MODIFY_REG(ADC1->CR, ADC_CR_ADVREGEN, 0); |
22 | MODIFY_REG(ADC1->CR, ADC_CR_ADVREGEN, ADC_CR_ADVREGEN_0); |
23 | |
24 | //kurzer delay zum enablen
|
25 | HAL_Delay(2); |
26 | |
27 | //ADC1 Clock = HCLK/1
|
28 | MODIFY_REG(ADC12_COMMON->CCR, ADC12_CCR_CKMODE, ADC12_CCR_CKMODE_0); |
29 | |
30 | //Single Ended Mode für alle Kanäle
|
31 | ADC1->DIFSEL = 0x0; |
32 | |
33 | //Kalibrierung für single ended Mode starten
|
34 | CLEAR_BIT(ADC1->CR, ADC_CR_ADCALDIF); |
35 | SET_BIT(ADC1->CR, ADC_CR_ADCAL); |
36 | |
37 | //Warten bis Kalibrierung erfolgt ist
|
38 | while(READ_BIT(ADC1->CR, ADC_CR_ADCAL)); |
39 | |
40 | //Ready Flag zurücksetzen
|
41 | SET_BIT(ADC1->ISR, ADC_ISR_ADRDY); |
42 | |
43 | SET_BIT(ADC1->SQR1, ADC_SQR1_L_1 + ADC_SQR1_L_0); //Sequnz Laenge = 4 (0011) |
44 | SET_BIT(ADC1->SQR1, ADC_SQR1_SQ1_1); //Erste Konv Channel 2 (0010) Vin |
45 | SET_BIT(ADC1->SQR1, ADC_SQR1_SQ2_2); //Zweit Konv Channel 4 (0100) Vout |
46 | SET_BIT(ADC1->SQR1, ADC_SQR1_SQ3_0); //Dritt Konv Channel 1 (0001) Iin |
47 | SET_BIT(ADC1->SQR1, ADC_SQR1_SQ4_0 + ADC_SQR1_SQ4_1); //Viert Konv Channel 3 (0011) Iout |
48 | |
49 | SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP2_2); //Sampling Time f. Channel 2 = 32 CLK |
50 | SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP4_2); //Sampling Time f. Channel 2 = 32 CLK |
51 | SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP1_2); //Sampling Time f. Channel 2 = 32 CLK |
52 | SET_BIT(ADC1->SMPR1, ADC_SMPR1_SMP3_2); //Sampling Time f. Channel 2 = 32 CLK |
53 | |
54 | CLEAR_BIT(ADC1->CFGR, ADC_CFGR_CONT); //Single conversion mode auswählen |
55 | |
56 | SET_BIT(ADC1->CFGR, ADC_CFGR_EXTSEL_2); //External Trigger für TIM3_TRGO Event EXT4 |
57 | //SET_BIT(ADC1->CFGR, ADC_CFGR_EXTEN_0); //External Trigger auf Rising Edge
|
58 | |
59 | SET_BIT(ADC1->CFGR, ADC_CFGR_DMAEN); //DMA einschalten |
60 | SET_BIT(ADC1->CFGR, ADC_CFGR_DMACFG); //DMA im Circular Mode |
61 | |
62 | SET_BIT(ADC1->IER, ADC_IER_EOCIE); //Interrupt Enable für EOC |
63 | SET_BIT(ADC1->IER, ADC_IER_EOSIE); //Interrupt Enable für EOS |
64 | |
65 | //ADC einschalten bis es funktioniert (aus Errata Sheet)
|
66 | do
|
67 | {
|
68 | SET_BIT(ADC1->CR, ADC_CR_ADEN); |
69 | }
|
70 | while(!READ_BIT(ADC1->ISR, ADC_ISR_ADRDY)); |
71 | |
72 | SET_BIT(ADC1->CR, ADC_CR_ADSTART); |
73 | //togled1();
|
74 | |
75 | }//ADC1 Init |
1 | void DMA_Init() |
2 | {
|
3 | //1. Channel im SYSCFG CFGR1/3 bekannt geben
|
4 | //SYSCFG_CFGR1: Nichts für ADC
|
5 | //SYSCFG_CFGR3: Bit 9 == 1: ADC2 mapped on DMA1 Ch2
|
6 | SET_BIT(SYSCFG->CFGR3, SYSCFG_CFGR3_ADC2_DMA_RMP_1); |
7 | |
8 | //Vier Register sind wichtig
|
9 | //Configuration: DMA_CCRx MINC, PINK, CIRC, /MEM2MEM
|
10 | //Holding number of bytes: DMA_CNDTRx
|
11 | //Source Adress: DMA_CMARx
|
12 | //Destination Adress: DMA_CPARx
|
13 | |
14 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_DIR); //Data Transfer Direction: 0 = Read from Peripheral |
15 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_MEM2MEM); //Nicht MEM 2 MEM |
16 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_CIRC); //Circ Mode Disabeled, wird nur von ADC EOC ausgelöst |
17 | |
18 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PL_0); //Priority level |
19 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PL_1); //00 low, 01 med, 10 high, 11 very high |
20 | |
21 | SET_BIT(DMA1_Channel1->CCR, DMA_CCR_MSIZE_0); //Memory Size |
22 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_MSIZE_1); //00 8bit, 01 16bit, 10 32 bit |
23 | |
24 | SET_BIT(DMA1_Channel1->CCR, DMA_CCR_PSIZE_0); //Peripheral Size |
25 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PSIZE_1); //00 8bit, 01 16bit, 10 32 bit |
26 | |
27 | SET_BIT(DMA1_Channel1->CCR, DMA_CCR_MINC); //Memory Increment |
28 | CLEAR_BIT(DMA1_Channel1->CCR, DMA_CCR_PINC); //NICHT Periph. increment |
29 | |
30 | //DMA Source und Destination Adressen setzen
|
31 | DMA1_Channel1->CMAR = ( uint32_t )&ADC_raw[0]; |
32 | DMA1_Channel1->CPAR = ( uint32_t )(&ADC1->DR); |
33 | DMA1_Channel1->CNDTR = 4; |
34 | |
35 | SET_BIT(DMA1_Channel1->CCR, DMA_CCR_EN); //DMA enablen |
36 | }
|
Alle Clock Signale werden woanders eingeschaltet. Allerdings werden keine Werte ins ADC_raw[] abgelegt. Der Timer und ADC arbeiten aber. Fallen euch Ungereimtheiten auf? Bitte entschuldigt grobe Schnitzer, das ist mein erstes STM32 Projekt. Vielen Dank!