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
)
70 uint8_t configuredAdcChannels
= 0;
72 memset(&adcOperatingConfig
, 0, sizeof(adcOperatingConfig
));
74 if (config
->vbat
.enabled
) {
75 adcOperatingConfig
[ADC_BATTERY
].tag
= config
->vbat
.ioTag
;
78 if (config
->rssi
.enabled
) {
79 adcOperatingConfig
[ADC_RSSI
].tag
= config
->rssi
.ioTag
; //RSSI_ADC_CHANNEL;
82 if (config
->external1
.enabled
) {
83 adcOperatingConfig
[ADC_EXTERNAL1
].tag
= config
->external1
.ioTag
; //EXTERNAL1_ADC_CHANNEL;
86 if (config
->current
.enabled
) {
87 adcOperatingConfig
[ADC_CURRENT
].tag
= config
->current
.ioTag
; //CURRENT_METER_ADC_CHANNEL;
90 ADCDevice device
= adcDeviceByInstance(ADC_INSTANCE
);
91 if (device
== ADCINVALID
) {
95 const adcDevice_t adc
= adcHardware
[device
];
97 if (!dmaAllocate(dmaGetIdentifier(adc
.dmaResource
), OWNER_ADC
, 0)) {
101 bool adcActive
= false;
102 for (int i
= 0; i
< ADC_CHANNEL_COUNT
; i
++) {
103 if (!adcOperatingConfig
[i
].tag
)
107 IOInit(IOGetByTag(adcOperatingConfig
[i
].tag
), OWNER_ADC_BATT
+ i
, 0);
108 IOConfigGPIO(IOGetByTag(adcOperatingConfig
[i
].tag
), IO_CONFIG(GPIO_Mode_AIN
, 0));
109 adcOperatingConfig
[i
].adcChannel
= adcChannelByTag(adcOperatingConfig
[i
].tag
);
110 adcOperatingConfig
[i
].dmaIndex
= configuredAdcChannels
++;
111 adcOperatingConfig
[i
].sampleTime
= ADC_SampleTime_239Cycles5
;
112 adcOperatingConfig
[i
].enabled
= true;
119 RCC_ADCCLKConfig(RCC_PCLK2_Div8
); // 9MHz from 72MHz APB2 clock(HSE), 8MHz from 64MHz (HSI)
120 RCC_ClockCmd(adc
.rccADC
, ENABLE
);
122 dmaEnable(dmaGetIdentifier(adc
.dmaResource
));
124 xDMA_DeInit(adc
.dmaResource
);
125 DMA_InitTypeDef DMA_InitStructure
;
126 DMA_StructInit(&DMA_InitStructure
);
127 DMA_InitStructure
.DMA_PeripheralBaseAddr
= (uint32_t)&adc
.ADCx
->DR
;
128 DMA_InitStructure
.DMA_MemoryBaseAddr
= (uint32_t)adcValues
;
129 DMA_InitStructure
.DMA_DIR
= DMA_DIR_PeripheralSRC
;
130 DMA_InitStructure
.DMA_BufferSize
= configuredAdcChannels
;
131 DMA_InitStructure
.DMA_PeripheralInc
= DMA_PeripheralInc_Disable
;
132 DMA_InitStructure
.DMA_MemoryInc
= configuredAdcChannels
> 1 ? DMA_MemoryInc_Enable
: DMA_MemoryInc_Disable
;
133 DMA_InitStructure
.DMA_PeripheralDataSize
= DMA_PeripheralDataSize_HalfWord
;
134 DMA_InitStructure
.DMA_MemoryDataSize
= DMA_MemoryDataSize_HalfWord
;
135 DMA_InitStructure
.DMA_Mode
= DMA_Mode_Circular
;
136 DMA_InitStructure
.DMA_Priority
= DMA_Priority_High
;
137 DMA_InitStructure
.DMA_M2M
= DMA_M2M_Disable
;
138 xDMA_Init(adc
.dmaResource
, &DMA_InitStructure
);
139 xDMA_Cmd(adc
.dmaResource
, ENABLE
);
141 ADC_InitTypeDef ADC_InitStructure
;
142 ADC_StructInit(&ADC_InitStructure
);
143 ADC_InitStructure
.ADC_Mode
= ADC_Mode_Independent
;
144 ADC_InitStructure
.ADC_ScanConvMode
= configuredAdcChannels
> 1 ? ENABLE
: DISABLE
;
145 ADC_InitStructure
.ADC_ContinuousConvMode
= ENABLE
;
146 ADC_InitStructure
.ADC_ExternalTrigConv
= ADC_ExternalTrigConv_None
;
147 ADC_InitStructure
.ADC_DataAlign
= ADC_DataAlign_Right
;
148 ADC_InitStructure
.ADC_NbrOfChannel
= configuredAdcChannels
;
149 ADC_Init(adc
.ADCx
, &ADC_InitStructure
);
152 for (int i
= 0; i
< ADC_CHANNEL_COUNT
; i
++) {
153 if (!adcOperatingConfig
[i
].enabled
) {
156 ADC_RegularChannelConfig(adc
.ADCx
, adcOperatingConfig
[i
].adcChannel
, rank
++, adcOperatingConfig
[i
].sampleTime
);
159 ADC_DMACmd(adc
.ADCx
, ENABLE
);
160 ADC_Cmd(adc
.ADCx
, ENABLE
);
162 ADC_ResetCalibration(adc
.ADCx
);
163 while (ADC_GetResetCalibrationStatus(adc
.ADCx
));
164 ADC_StartCalibration(adc
.ADCx
);
165 while (ADC_GetCalibrationStatus(adc
.ADCx
));
167 ADC_SoftwareStartConvCmd(adc
.ADCx
, ENABLE
);
170 void adcGetChannelValues(void)