本帖最后由 jobszheng5 于 2024-3-22 00:24 编辑
STM32C031为基于Cortex-M0内核的新推出芯片,但其性能较其老大哥STM32F103(基于Cortex-M3内核)并不逊色多少。从转换时间上看,STM32F103在56MHz下,采样转换时间仅为1us,而STM32C031也仅为2us。在转换时间绝对值比较中,我个人认为,并没有多少差距。两者的最高采样有效位也均为12bit,没有达到更高的阶的16bit。上一张STM32C031的ADC特性图:
接下来,我分享一下我的ADC采样源代码。我把采样结果保存到了holding_regs[3]中,亦可通过ModbusPoll上位机软件周期读出来。
```c
static void adc_poll(void)
{
switch (adc_status)
{
case 0:
{
LL_ADC_REG_StartConversion(ADC1);
adc_status = 1;
break;
}
case 1:
{
break;
}
case 2:
{
mb_holding_regs[3] = adc_raw_value * 330 / 4096;
adc_status = 0;
break;
}
}
}
void bsp_adc_init(void)
{
LL_ADC_InitTypeDef ADC_InitStruct = {0};
LL_ADC_REG_InitTypeDef ADC_REG_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/**ADC1 GPIO Configuration
PA0 ------> ADC1_IN0
PA1 ------> ADC1_IN1
*/
GPIO_InitStruct.Pin = LL_GPIO_PIN_0;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = LL_GPIO_PIN_1;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = LL_GPIO_PULL_NO;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
LL_RCC_SetADCClockSource(LL_RCC_ADC_CLKSOURCE_SYSCLK);
/* Peripheral clock enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_ADC);
/* ADC1 interrupt Init */
NVIC_SetPriority(ADC1_IRQn, 0);
NVIC_EnableIRQ(ADC1_IRQn);
ADC_InitStruct.Clock = LL_ADC_CLOCK_SYNC_PCLK_DIV4;
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_SetSequencerConfigurable(ADC1, LL_ADC_REG_SEQ_CONFIGURABLE);
while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0)
{
;
}
LL_ADC_ClearFlag_CCRDY(ADC1);
ADC_REG_InitStruct.TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
ADC_REG_InitStruct.SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
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_NONE;
ADC_REG_InitStruct.Overrun = LL_ADC_REG_OVR_DATA_PRESERVED;
LL_ADC_REG_Init(ADC1, &ADC_REG_InitStruct);
LL_ADC_SetOverSamplingScope(ADC1, LL_ADC_OVS_DISABLE);
LL_ADC_SetTriggerFrequencyMode(ADC1, LL_ADC_CLOCK_FREQ_MODE_LOW);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_1, LL_ADC_SAMPLINGTIME_79CYCLES_5);
LL_ADC_SetSamplingTimeCommonChannels(ADC1, LL_ADC_SAMPLINGTIME_COMMON_2, LL_ADC_SAMPLINGTIME_79CYCLES_5);
LL_ADC_DisableIT_EOC(ADC1);
LL_ADC_DisableIT_EOS(ADC1);
/* Enable ADC internal voltage regulator */
LL_ADC_EnableInternalRegulator(ADC1);
uint32_t wait_loop_index;
wait_loop_index = ((LL_ADC_DELAY_INTERNAL_REGUL_STAB_US * (SystemCoreClock / (100000 * 2))) / 10);
while (wait_loop_index != 0)
{
wait_loop_index--;
}
/** Configure Regular Channel
*/
LL_ADC_REG_SetSequencerRanks(ADC1, LL_ADC_REG_RANK_1, LL_ADC_CHANNEL_0);
while (LL_ADC_IsActiveFlag_CCRDY(ADC1) == 0)
{
;
}
LL_ADC_ClearFlag_CCRDY(ADC1);
LL_ADC_SetChannelSamplingTime(ADC1, LL_ADC_CHANNEL_0, LL_ADC_SAMPLINGTIME_COMMON_1);
/* Configuration of ADC interruptions */
/* Enable interruption ADC group regular end of unitary conversion */
LL_ADC_EnableIT_EOC(ADC1);
/* Configuration of ADC interruptions */
/* Enable interruption ADC group regular overrun */
// LL_ADC_EnableIT_OVR(ADC1);
/* Run ADC self calibration */
LL_ADC_StartCalibration(ADC1);
while (LL_ADC_IsCalibrationOnGoing(ADC1) != 0)
{
;
}
/* Enable ADC */
LL_ADC_Enable(ADC1);
while (LL_ADC_IsActiveFlag_ADRDY(ADC1) == 0)
{
;
}
}
int main(void)
{
while (1)
{
if (timeline_ms > 200)
{
timeline_ms = 0;
led_toggle();
// jlog_printf("Hello eeworld! Hello STM32C031!\r\n");
}
mb_poll();
pwm_poll();
adc_poll();
}
}
void ADC1_IRQHandler(void)
{
if (LL_ADC_IsActiveFlag_EOC(ADC1) != 0)
{
/* Clear flag ADC group regular end of unitary conversion */
LL_ADC_ClearFlag_EOC(ADC1);
/* Call interruption treatment function */
adc_raw_value = LL_ADC_REG_ReadConversionData32(ADC1);
adc_status = 2;
}
}
```
放上了一块七号电池,看看测量结果怎么样吧!