2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
29 #include "build/build_config.h"
31 #include "drivers/sensor.h"
34 #include "drivers/io.h"
41 const adcDevice_t adcHardware
[] = {
42 { .ADCx
= ADC1
, .rccADC
= RCC_APB2(ADC1
), .dmaResource
= (dmaResource_t
*)DMA1_Channel1
}
45 const adcTagMap_t adcTagMap
[] = {
46 { DEFIO_TAG_E__PA0
, ADC_Channel_0
}, // ADC12
47 { DEFIO_TAG_E__PA1
, ADC_Channel_1
}, // ADC12
48 { DEFIO_TAG_E__PA2
, ADC_Channel_2
}, // ADC12
49 { DEFIO_TAG_E__PA3
, ADC_Channel_3
}, // ADC12
50 { DEFIO_TAG_E__PA4
, ADC_Channel_4
}, // ADC12
51 { DEFIO_TAG_E__PA5
, ADC_Channel_5
}, // ADC12
52 { DEFIO_TAG_E__PA6
, ADC_Channel_6
}, // ADC12
53 { DEFIO_TAG_E__PA7
, ADC_Channel_7
}, // ADC12
54 { DEFIO_TAG_E__PB0
, ADC_Channel_8
}, // ADC12
55 { DEFIO_TAG_E__PB1
, ADC_Channel_9
}, // ADC12
58 // Driver for STM32F103CB onboard ADC
61 // Battery Voltage (VBAT) is connected to PA4 (ADC1_IN4) with 10k:1k divider
62 // RSSI ADC uses CH2 (PA1, ADC1_IN1)
63 // Current ADC uses CH8 (PB1, ADC1_IN9)
65 // NAZE rev.5 hardware has PA5 (ADC1_IN5) on breakout pad on bottom of board
68 void adcInit(const adcConfig_t
*config
)
71 uint8_t configuredAdcChannels
= 0;
73 memset(&adcOperatingConfig
, 0, sizeof(adcOperatingConfig
));
75 if (config
->vbat
.enabled
) {
76 adcOperatingConfig
[ADC_BATTERY
].tag
= config
->vbat
.ioTag
;
79 if (config
->rssi
.enabled
) {
80 adcOperatingConfig
[ADC_RSSI
].tag
= config
->rssi
.ioTag
; //RSSI_ADC_CHANNEL;
83 if (config
->external1
.enabled
) {
84 adcOperatingConfig
[ADC_EXTERNAL1
].tag
= config
->external1
.ioTag
; //EXTERNAL1_ADC_CHANNEL;
87 if (config
->current
.enabled
) {
88 adcOperatingConfig
[ADC_CURRENT
].tag
= config
->current
.ioTag
; //CURRENT_METER_ADC_CHANNEL;
91 ADCDevice device
= adcDeviceByInstance(ADC_INSTANCE
);
92 if (device
== ADCINVALID
)
95 const adcDevice_t adc
= adcHardware
[device
];
97 bool adcActive
= false;
98 for (int i
= 0; i
< ADC_CHANNEL_COUNT
; i
++) {
99 if (!adcOperatingConfig
[i
].tag
)
103 IOInit(IOGetByTag(adcOperatingConfig
[i
].tag
), OWNER_ADC_BATT
+ i
, 0);
104 IOConfigGPIO(IOGetByTag(adcOperatingConfig
[i
].tag
), IO_CONFIG(GPIO_Mode_AIN
, 0));
105 adcOperatingConfig
[i
].adcChannel
= adcChannelByTag(adcOperatingConfig
[i
].tag
);
106 adcOperatingConfig
[i
].dmaIndex
= configuredAdcChannels
++;
107 adcOperatingConfig
[i
].sampleTime
= ADC_SampleTime_239Cycles5
;
108 adcOperatingConfig
[i
].enabled
= true;
115 RCC_ADCCLKConfig(RCC_PCLK2_Div8
); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI)
116 RCC_ClockCmd(adc
.rccADC
, ENABLE
);
118 dmaInit(dmaGetIdentifier(adc
.dmaResource
), OWNER_ADC
, 0);
120 xDMA_DeInit(adc
.dmaResource
);
121 DMA_InitTypeDef DMA_InitStructure
;
122 DMA_StructInit(&DMA_InitStructure
);
123 DMA_InitStructure
.DMA_PeripheralBaseAddr
= (uint32_t)&adc
.ADCx
->DR
;
124 DMA_InitStructure
.DMA_MemoryBaseAddr
= (uint32_t)adcValues
;
125 DMA_InitStructure
.DMA_DIR
= DMA_DIR_PeripheralSRC
;
126 DMA_InitStructure
.DMA_BufferSize
= configuredAdcChannels
;
127 DMA_InitStructure
.DMA_PeripheralInc
= DMA_PeripheralInc_Disable
;
128 DMA_InitStructure
.DMA_MemoryInc
= configuredAdcChannels
> 1 ? DMA_MemoryInc_Enable
: DMA_MemoryInc_Disable
;
129 DMA_InitStructure
.DMA_PeripheralDataSize
= DMA_PeripheralDataSize_HalfWord
;
130 DMA_InitStructure
.DMA_MemoryDataSize
= DMA_MemoryDataSize_HalfWord
;
131 DMA_InitStructure
.DMA_Mode
= DMA_Mode_Circular
;
132 DMA_InitStructure
.DMA_Priority
= DMA_Priority_High
;
133 DMA_InitStructure
.DMA_M2M
= DMA_M2M_Disable
;
134 xDMA_Init(adc
.dmaResource
, &DMA_InitStructure
);
135 xDMA_Cmd(adc
.dmaResource
, ENABLE
);
137 ADC_InitTypeDef ADC_InitStructure
;
138 ADC_StructInit(&ADC_InitStructure
);
139 ADC_InitStructure
.ADC_Mode
= ADC_Mode_Independent
;
140 ADC_InitStructure
.ADC_ScanConvMode
= configuredAdcChannels
> 1 ? ENABLE
: DISABLE
;
141 ADC_InitStructure
.ADC_ContinuousConvMode
= ENABLE
;
142 ADC_InitStructure
.ADC_ExternalTrigConv
= ADC_ExternalTrigConv_None
;
143 ADC_InitStructure
.ADC_DataAlign
= ADC_DataAlign_Right
;
144 ADC_InitStructure
.ADC_NbrOfChannel
= configuredAdcChannels
;
145 ADC_Init(adc
.ADCx
, &ADC_InitStructure
);
148 for (int i
= 0; i
< ADC_CHANNEL_COUNT
; i
++) {
149 if (!adcOperatingConfig
[i
].enabled
) {
152 ADC_RegularChannelConfig(adc
.ADCx
, adcOperatingConfig
[i
].adcChannel
, rank
++, adcOperatingConfig
[i
].sampleTime
);
155 ADC_DMACmd(adc
.ADCx
, ENABLE
);
156 ADC_Cmd(adc
.ADCx
, ENABLE
);
158 ADC_ResetCalibration(adc
.ADCx
);
159 while (ADC_GetResetCalibrationStatus(adc
.ADCx
));
160 ADC_StartCalibration(adc
.ADCx
);
161 while (ADC_GetCalibrationStatus(adc
.ADCx
));
163 ADC_SoftwareStartConvCmd(adc
.ADCx
, ENABLE
);
166 void adcGetChannelValues(void)