AM32 电调学习
2. 电流处理
- 采样的时机:// sample current at quarter pwm on
ADC_CCR = TIM1->CCR3 * 2 / 3 + 1; // sample current at quarter pwm on
if (ADC_CCR > tim1_arr) {
ADC_CCR = tim1_arr;
}
TIM1->CCR4 = ADC_CCR;
- 电流的作用:consumed_current = (float)actual_current / 360 + consumed_current;
- tim1->ccr4 的作用不明
(0) main中电流处理
adc_counter++;
if (adc_counter > 200) { // for adc and telemetry
#if defined(MCU_F051) || defined(MCU_G071) || defined(MCU_F031)
ADC_DMA_Callback();
ADC_CCR = TIM1->CCR3 * 2 / 3 + 1; // sample current at quarter pwm on
if (ADC_CCR > tim1_arr) {
ADC_CCR = tim1_arr;
}
TIM1->CCR4 = ADC_CCR;
LL_ADC_REG_StartConversion(ADC1);
converted_degrees = __LL_ADC_CALC_TEMPERATURE(3300, ADC_raw_temp, LL_ADC_RESOLUTION_12B);
#endif
#ifdef MCU_GDE23
ADC_DMA_Callback();
converted_degrees = (1.43 - ADC_raw_temp * 3.3 / 4096) * 1000 / 4.3 + 25;
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
#endif
#ifdef ARTERY
ADC_DMA_Callback();
adc_ordinary_software_trigger_enable(ADC1, TRUE);
// converted_degrees = (4000 - ADC_raw_temp) / 20;
converted_degrees = getConvertedDegrees(ADC_raw_temp);
#endif
degrees_celsius = converted_degrees;
battery_voltage = ((7 * battery_voltage) + ((ADC_raw_volts * 3300 / 4095 * VOLTAGE_DIVIDER) / 100)) >> 3;
smoothed_raw_current = getSmoothedCurrent();
// smoothed_raw_current = ((63*smoothed_raw_current +
// (ADC_raw_current) )>>6);
actual_current = ((smoothed_raw_current * 3300 / 41) - (CURRENT_OFFSET * 100)) / (MILLIVOLT_PER_AMP);
if (actual_current < 0) {
actual_current = 0;
}
if (LOW_VOLTAGE_CUTOFF) {
if (battery_voltage < (cell_count * low_cell_volt_cutoff)) {
low_voltage_count++;
if (low_voltage_count > (20000 - (stepper_sine * 900))) {
input = 0;
allOff();
maskPhaseInterrupts();
running = 0;
zero_input_count = 0;
armed = 0;
}
} else {
low_voltage_count = 0;
}
}
adc_counter = 0;
#ifdef USE_ADC_INPUT
if (ADC_raw_input < 10) {
zero_input_count++;
} else {
zero_input_count = 0;
}
#endif
}
(1) 平滑处理
- const uint8_t numReadings = 100; // the readings from the analog input
uint16_t getSmoothedCurrent()
{
total = total - readings[readIndex];
readings[readIndex] = ADC_raw_current;
total = total + readings[readIndex];
readIndex = readIndex + 1;
if (readIndex >= numReadings) {
readIndex = 0;
}
smoothedcurrent = total / numReadings;
return smoothedcurrent;
}
(2)电流获取
void ADC_DMA_Callback()
{ // read dma buffer and set extern variables
#ifdef USE_ADC_INPUT(0)
ADC_raw_temp = ADCDataDMA[3];
ADC_raw_volts = ADCDataDMA[1] / 2;
ADC_raw_current = ADCDataDMA[2];
ADC_raw_input = ADCDataDMA[0];
#else
ADC_raw_temp = ADCDataDMA[2];
ADC_raw_volts = ADCDataDMA[1];
ADC_raw_current = ADCDataDMA[0];
#endif
}
/**
* @brief This function handles DMA1 channel 2 and channel 3 interrupts.
*/
void DMA1_Channel2_3_IRQHandler(void)
{
if (LL_DMA_IsActiveFlag_TC2(DMA1) == 1) {
LL_DMA_ClearFlag_GI2(DMA1);
ADC_DMA_Callback();
}
if (LL_DMA_IsActiveFlag_TE2(DMA1) == 1) {
LL_DMA_ClearFlag_TE2(DMA1);
}
if (LL_DMA_IsActiveFlag_TC3(DMA1)) {
send_telemetry = 0;
LL_DMA_ClearFlag_GI3(DMA1);
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3);
/* Call function Transmission complete Callback */
} else if (LL_DMA_IsActiveFlag_TE3(DMA1)) {
LL_DMA_ClearFlag_GI3(DMA1);
LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_3);
/* Call Error function */
// USART_TransferError_Callback();
}
}
(3) adc配置
- dma 配置地址,长度
- 允许完成及错误中断
- 打开dma通道
- adc需要标准,打开温度传感器
void enableADC_DMA()
{ // enables channel
NVIC_SetPriority(DMA1_Channel2_3_IRQn, 3);
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
LL_DMA_ConfigAddresses(
DMA1, LL_DMA_CHANNEL_2,
LL_ADC_DMA_GetRegAddr(ADC1, LL_ADC_DMA_REG_REGULAR_DATA),
(uint32_t)&ADCDataDMA, LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
/* Set DMA transfer size */
#ifdef USE_ADC_INPUT
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 4);
#else
LL_DMA_SetDataLength(DMA1, LL_DMA_CHANNEL_2, 3);
#endif
/* Enable DMA transfer interruption: transfer complete */
LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_2);
/* Enable DMA transfer interruption: transfer error */
LL_DMA_EnableIT_TE(DMA1, LL_DMA_CHANNEL_2);
/*## Activation of DMA
* #####################################################*/
/* Enable the DMA transfer */
LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_2);
}
void activateADC(void)
{
__IO uint32_t wait_loop_index = 0U;
__IO uint32_t backup_setting_adc_dma_transfer = 0U;
if (LL_ADC_IsEnabled(ADC1) == 0) {
/* Enable ADC internal voltage regulator */
LL_ADC_EnableInternalRegulator(ADC1);
wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while (wait_loop_index != 0) {
wait_loop_index--;
}
backup_setting_adc_dma_transfer = LL_ADC_REG_GetDMATransfer(ADC1);
LL_ADC_REG_SetDMATransfer(ADC1, LL_ADC_REG_DMA_TRANSFER_NONE);
/* Run ADC self calibration */
LL_ADC_StartCalibration(ADC1);
/* Poll for ADC effectively calibrated */
while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0) {
}
/* Restore ADC DMA transfer request after calibration */
LL_ADC_REG_SetDMATransfer(ADC1, backup_setting_adc_dma_transfer);
/* Delay between ADC end of calibration and ADC enable. */
/* Note: Variable divided by 2 to compensate partially */
/* CPU processing cycles (depends on compilation optimization). */
wait_loop_index = (ADC_DELAY_CALIB_ENABLE_CPU_CYCLES >> 1);
while (wait_loop_index != 0) {
wait_loop_index--;
}
/* Enable ADC */
LL_ADC_Enable(ADC1);
while (LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0) {
}
ADC->CCR |= ADC_CCR_TSEN;
}
}
(4)adc初始化
- gpio 初始化
- dma通道初始化,连接adc
- adc寄存器初始化:规则扫描3个,采样时间
- adc初始化,位数,右对齐
void ADC_Init(void)
{
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = { 0 };
LL_ADC_InitTypeDef ADC_InitStruct = { 0 };
LL_GPIO_InitTypeDef GPIO_InitStruct = { 0 };
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
/**ADC1 GPIO Configuration
PA4 ------> ADC1_IN4
PA6 ------> ADC1_IN6
*/
GPIO_InitStruct.Pin = VOLTAGE_ADC_PIN;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = CURRENT_ADC_PIN;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* ADC1 DMA Init */
/* ADC1 Init */
LL_DMA_SetPeriphRequest(DMA1, LL_DMA_CHANNEL_2, LL_DMAMUX_REQ_ADC1);
LL_DMA_SetDataTransferDirection(DMA1, LL_DMA_CHANNEL_2,
LL_DMA_DIRECTION_PERIPH_TO_MEMORY);
LL_DMA_SetChannelPriorityLevel(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PRIORITY_HIGH);
LL_DMA_SetMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MODE_CIRCULAR);
LL_DMA_SetPeriphIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PERIPH_NOINCREMENT);
LL_DMA_SetMemoryIncMode(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MEMORY_INCREMENT);
LL_DMA_SetPeriphSize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_PDATAALIGN_WORD);
LL_DMA_SetMemorySize(DMA1, LL_DMA_CHANNEL_2, LL_DMA_MDATAALIGN_HALFWORD);
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Configure Regular Channel
*/
LL_ADC_SetCommonPathInternalCh(__LL_ADC_COMMON_INSTANCE(ADC1),
LL_ADC_CHANNEL_TEMPSENSOR);
/** Configure the global features of the ADC (Clock, Resolution, Data
* Alignment and number of conversion)
*/
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS;
ADC_REG_InitStruct.SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
ADC_REG_InitStruct.ContinuousMode = LL_ADC_REG_CONV_SINGLE;
ADC_REG_InitStruct.DMATransfer = LL_ADC_REG_DMA_TRANSFER_LIMITED;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
// LL_ADC_REG_SetTriggerEdge(ADC1, LL_ADC_REG_TRIG_EXT_FALLING);
LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE);
LL_ADC_SetTriggerFrequencyMode(ADC1, LL_ADC_CLOCK_FREQ_MODE_LOW);
LL_ADC_REG_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_CONFIGURABLE);
LL_ADC_SetClock(ADC1, LL_ADC_CLOCK_ASYNC_DIV4);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1,
LL_ADC_SAMPLINGTIME_19CYCLES_5);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_2,
LL_ADC_SAMPLINGTIME_160CYCLES_5);
LL_ADC_DisableIT_EOC(ADC1);
LL_ADC_DisableIT_EOS(ADC1);
ADC_InitStruct.Resolution = LL_ADC_RESOLUTION_12B;
ADC_InitStruct.DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
ADC_InitStruct.LowPowerMode = LL_ADC_LP_MODE_NONE;
LL_ADC_Init(ADC1, &ADC_InitStruct);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, CURRENT_ADC_CHANNEL);
LL_ADC_SetChannelSamplingTime(ADC1, CURRENT_ADC_CHANNEL,
LL_ADC_SAMPLINGTIME_COMMON_1);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_2, VOLTAGE_ADC_CHANNEL);
LL_ADC_SetChannelSamplingTime(ADC1, VOLTAGE_ADC_CHANNEL,
LL_ADC_SAMPLINGTIME_COMMON_1);
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_3,
LL_ADC_CHANNEL_TEMPSENSOR);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_TEMPSENSOR,
LL_ADC_SAMPLINGTIME_COMMON_2);
}