1 | typedef struct
|
2 | {
|
3 | GPIO_TypeDef *Gpio;
|
4 | uint16_t Pin;
|
5 | }
|
6 | Gpiopin_t;
|
7 |
|
8 |
|
9 | #ifdef STM32F446ZE
|
10 | /* GPIO passend zum ADC-Kanal auswaehlen */
|
11 | static Gpiopin_t lookupIO(ADC_TypeDef *ADCx, enum adcChannel_e channel )
|
12 | {
|
13 | switch( channel )
|
14 | {
|
15 | case adc1_ch4_PA4: // Fallthru
|
16 | case adc2_ch4_PA4:
|
17 | assert( ADCx == ADC1 || ADCx == ADC2 );
|
18 | return (Gpiopin_t) {.Gpio = GPIOA, .Pin = GPIO_Pin_4};
|
19 |
|
20 | case adc3_ch4_PF6:
|
21 | assert( ADCx == ADC3 );
|
22 | return (Gpiopin_t) {.Gpio = GPIOF, .Pin = GPIO_Pin_6};
|
23 |
|
24 | default:
|
25 | error("unknown channel");
|
26 | return (Gpiopin_t) {.Gpio = NULL, .Pin = 0};
|
27 | }
|
28 | }
|
29 | #else
|
30 | #error "unknown MCU"
|
31 | #endif
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | /* Initialisierung ADC
|
37 | *
|
38 | * *ADCx : ADC1|ADC2|ADC3
|
39 | * return: Errorcode */
|
40 | uint_fast8_t adc_simple_init(ADC_TypeDef *ADCx, AdcInit_t Ini)
|
41 | {
|
42 | //FIXME: Zu Debugzwecken
|
43 | ADCx = ADC1;
|
44 | Ini.channel = adc1_ch4_PA4;
|
45 | Ini.sampleRate = sampleRate_slow;
|
46 | // :EMXIF
|
47 |
|
48 | ADC_CommonInitTypeDef ADC_CommonInitStructure;
|
49 | ADC_InitTypeDef ADC_InitStructure;
|
50 | GPIO_InitTypeDef GPIO_InitStructure;
|
51 |
|
52 |
|
53 | uint8_t ADC_SampleTime;
|
54 |
|
55 | switch( Ini.sampleRate )
|
56 | {
|
57 | case sampleRate_slow:
|
58 | ADC_SampleTime = ADC_SampleTime_480Cycles;
|
59 | break;
|
60 |
|
61 | case sampleRate_fast:
|
62 | ADC_SampleTime = ADC_SampleTime_3Cycles;
|
63 | break;
|
64 |
|
65 | default:
|
66 | return EXIT_FAILURE;
|
67 | }
|
68 |
|
69 |
|
70 | GPIO_TypeDef *GPIOx = lookupIO(ADCx, Ini.channel).Gpio;
|
71 | uint16_t Pin = lookupIO(ADCx, Ini.channel).Pin;
|
72 |
|
73 |
|
74 | //TODO: Relikt von STM32F10x - ueberpruefen, inwieweit das auf die F4xxx auch zutrifft
|
75 | // ADC-Takt max. 14MHz, hier 72MHz / 6 = 12MHz
|
76 | //RCC_ADCCLKConfig(RCC_PCLK2_Div6);
|
77 | // Laut RM0390 kein aehnliches Konstrukt notwendig REMOVEME
|
78 |
|
79 |
|
80 | initGpioClock(GPIOx);
|
81 |
|
82 |
|
83 | if( ADCx==ADC1 )
|
84 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
|
85 | else if( ADCx==ADC2 )
|
86 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
|
87 | else if( ADCx==ADC3 )
|
88 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); // ADC3 noch nie getestet!
|
89 | else
|
90 | return EXIT_FAILURE;
|
91 |
|
92 |
|
93 | if( GPIOx != NULL ) // Es gibt auch ADC-Kanaele ohne GPIO
|
94 | {
|
95 | GPIO_InitStructure.GPIO_Pin = Pin;
|
96 | GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
|
97 | GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
|
98 | GPIO_Init(GPIOx, &GPIO_InitStructure);
|
99 | }
|
100 |
|
101 | ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
|
102 | ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
|
103 | ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
|
104 | ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
|
105 | ADC_CommonInit(&ADC_CommonInitStructure);
|
106 |
|
107 | ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
|
108 | ADC_InitStructure.ADC_ScanConvMode = DISABLE;
|
109 | ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;
|
110 | ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
|
111 | ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
|
112 | ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
|
113 | ADC_InitStructure.ADC_NbrOfConversion = 1;
|
114 | ADC_Init(ADCx, &ADC_InitStructure);
|
115 |
|
116 |
|
117 | assert( ADC_Channel_4 == 4 ); // Paranoia
|
118 | ADC_RegularChannelConfig(ADCx, Ini.channel, 1, ADC_SampleTime);
|
119 |
|
120 |
|
121 |
|
122 |
|
123 | ADC_ContinuousModeCmd(ADCx, ENABLE); // Setzt CONT in ADC_CR2
|
124 | // In keinem Beispiel der STDPeriphLBR drin.
|
125 | // setzt CR2 auf 2
|
126 | ADC_Cmd(ADCx, ENABLE); // Setzt CR2 auf 3
|
127 |
|
128 |
|
129 | ADC_SoftwareStartConv(ADCx); //Start ADC1 Conversion
|
130 | // Sollte laut Quelltext Bit 30 in CR2 setzen, stattdessen bleibt CR2 im Debugger auf
|
131 | // 3, SR liest sich zu 0x12 -> injected channel start und enc of conversion
|
132 |
|
133 | adc_calib(ADCx);
|
134 | return EXIT_SUCCESS;
|
135 | }
|
136 |
|
137 |
|
138 |
|
139 | /* Der ADC braucht nicht deinitialisiert zu werden (er kann jederzeit mit anderen
|
140 | * Parametern darueberinitialisiert werden, aber der Vollstaendgkeit halber */
|
141 | uint_fast8_t adc_simple_deinit(ADC_TypeDef *ADCx)
|
142 | {
|
143 | ADC_Cmd(ADCx, DISABLE);
|
144 | return EXIT_SUCCESS;
|
145 | }
|