使用芯旺微KF32A156的芯片做预研项目,使用了ADC0外设,根据芯片规格书中的描述进行了配置:
/**
* @brief: Configure ADC.
*
* @param[in] none.
* @param[in] none.
* @param[out] None
* @retval: None
*/
static void adc_peripheral_init(void) {
ADC_InitTypeDef ADC_InitStructure;
ADC_Reset(ADC0_SFR);
ADC_InitStructure.m_Clock = ADC_HFCLK;
ADC_InitStructure.m_ClockDiv = ADC_CLK_DIV_2;
ADC_InitStructure.m_ScanMode = TRUE;
ADC_InitStructure.m_ContinuousMode = ADC_SINGLE_MODE;
ADC_InitStructure.m_DataAlign = ADC_DATAALIGN_RIGHT;
ADC_InitStructure.m_ExternalTrig_EN = TRUE;
ADC_InitStructure.m_HPExternalTrig_EN = FALSE;
ADC_InitStructure.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO;
ADC_InitStructure.m_VoltageRef = ADC_REF_AVDD;
ADC_InitStructure.m_NumOfConv = ADC_CH_NUM_MAX;
ADC_InitStructure.m_NumOfHPConv = 0;
ADC_Configuration(ADC0_SFR, &ADC_InitStructure);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_14, 0x01);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_15, 0x02);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_58, 0x03);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_60, 0x04);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_68, 0x05);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_69, 0x06);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_70, 0x07);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_72, 0x08);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_76, 0x09);
ADC_Regular_Channel_DMA_Cmd(ADC0_SFR, TRUE);
ADC_Cmd(ADC0_SFR, TRUE);
/* 使能AD 后,延迟大概5us 后,再去给触发信号去触发AD 转换 */
systick_delay_ms(1);
}
发现采样结果一直异常,之后进入到初始化配置函数,发现如下代码:
/*---------------- 设置ADC_HSCANSQ寄存器 ----------------*/
/* 根据结构体成员m_NumOfHPConv,设置HSLEN位域 */
tmpreg = (adcInitStruct->m_NumOfHPConv - 1) << ADC_SCANCTL_HSLEN0_POS;
ADCx->SCANCTL = SFR_Config (ADCx->SCANCTL,~ADC_SCANCTL_HSLEN,tmpreg);
这是高级转换通道的数量,因为不使用,所以配置了0,但是这里进行了减1的操作, tmpreg是uint32_t 类型的,tmpreg十六进制数就是0xFFFFFFF0,而SFR_Config的定义如下:
/* 写特殊功能寄存器 */
static inline uint32_t SFR_Config(uint32_t SfrMem, uint32_t SfrMask, uint32_t WriteVal)
{
return ((SfrMem & SfrMask) | (WriteVal));
}
所以不使能高优先级通道转换时,m_NumOfHPConv 不能配置为0,需要配置为1;正确配置如下:
/**
* @brief: Configure ADC.
*
* @param[in] none.
* @param[in] none.
* @param[out] None
* @retval: None
*/
static void adc_peripheral_init(void) {
ADC_InitTypeDef ADC_InitStructure;
ADC_Reset(ADC0_SFR);
ADC_InitStructure.m_Clock = ADC_HFCLK;
ADC_InitStructure.m_ClockDiv = ADC_CLK_DIV_2;
ADC_InitStructure.m_ScanMode = TRUE;
ADC_InitStructure.m_ContinuousMode = ADC_SINGLE_MODE;
ADC_InitStructure.m_DataAlign = ADC_DATAALIGN_RIGHT;
ADC_InitStructure.m_ExternalTrig_EN = TRUE;
ADC_InitStructure.m_HPExternalTrig_EN = FALSE;
ADC_InitStructure.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO;
ADC_InitStructure.m_VoltageRef = ADC_REF_AVDD;
ADC_InitStructure.m_NumOfConv = ADC_CH_NUM_MAX;
ADC_InitStructure.m_NumOfHPConv = 1;//不能为0
ADC_Configuration(ADC0_SFR, &ADC_InitStructure);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_14, 0x01);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_15, 0x02);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_58, 0x03);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_60, 0x04);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_68, 0x05);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_69, 0x06);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_70, 0x07);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_72, 0x08);
ADC_Regular_Channel_Config(ADC0_SFR, ADC_CHANNEL_76, 0x09);
ADC_Regular_Channel_DMA_Cmd(ADC0_SFR, TRUE);
ADC_Cmd(ADC0_SFR, TRUE);
/* 使能AD 后,延迟大概5us 后,再去给触发信号去触发AD 转换 */
systick_delay_ms(1);
}