WCH沁恒单片机
直播中

吴藩

9年用户 822经验值
擅长:可编程逻辑
私信 关注
[问答]

求助,ch32v103c8t6注入组采样问题如何解决?

我的目的是采样外部连接PA1,PA2两个模拟信号,以及内部16通道的内部温度。
使用注入方式采样,由外部定时器事件触发,然后ADC连续采样3个通道,最后触发ADC_IT_JEOC中断进行处理

实验的初始化代码如下
void ad_init(void) {
    memset(&ad, 0, sizeof(ad));
    ADC_InitTypeDef ADC_InitStructure = { 0 };
    GPIO_InitTypeDef GPIO_InitStructure = { 0 };
    NVIC_InitTypeDef NVIC_InitStructure = { 0 };

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
    RCC_ADCCLKConfig(RCC_PCLK2_Div8);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

//    ADC1->CTLR1 = 0x00000180;
//    ADC1->CTLR2 = 0x00808801;
//    ADC1->ISQR = 0x00204020;
//    ADC1->SAMPTR1 = 0x00080000;
//    ADC1->SAMPTR2 = 0x00000012;

    ADC_DeInit(ADC1);
    ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;
    ADC_InitStructure.ADC_ScanConvMode = ENABLE;
    ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
    ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigInjecConv_T1_TRGO;
    ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel = 0;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_InjectedDiscModeCmd(ADC1, DISABLE);
    ADC_ExternalTrigInjectedConvCmd(ADC1, ENABLE);

    ADC_InjectedSequencerLengthConfig(ADC1, 3);
    ADC_InjectedChannelConfig(ADC1, ADC_Channel_1, 0,ADC_SampleTime_28Cycles5);
    ADC_InjectedChannelConfig(ADC1, ADC_Channel_2, 1,ADC_SampleTime_28Cycles5);
    ADC_InjectedChannelConfig(ADC1, ADC_Channel_16, 2,ADC_SampleTime_28Cycles5);
    ADC_ITConfig(ADC1, ADC_IT_JEOC, ENABLE);

    ADC_Cmd(ADC1, ENABLE);
    Delay_Us(50);
    ADC_TempSensorVrefintCmd(ENABLE);
    ADC_ResetCalibration(ADC1);
    while(ADC_GetResetCalibrationStatus(ADC1));
    ADC_StartCalibration(ADC1);
    while(ADC_GetCalibrationStatus(ADC1));
    Calibrattion_Val = Get_CalibrationValue(ADC1);

    NVIC_InitStructure.NVIC_IRQChannel = ADC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

}
void timer_init(void) {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure = { 0 };
//定时器1的刷新时间触发AD采样
    RCC_APB2PeriphClockCmd( RCC_APB2Periph_TIM1, ENABLE);
    TIM_TimeBaseInitStructure.TIM_Period = 56250; //=72000000/12800
    TIM_TimeBaseInitStructure.TIM_Prescaler = 0; //不分频
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV4;
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseInitStructure);
    TIM_CtrlPWMOutputs(TIM1, ENABLE);
    TIM_ARRPreloadConfig(TIM1, ENABLE);
    TIM_SelectOutputTrigger(TIM1, TIM_TRGOSource_Update);
TIM_Cmd(TIM1, ENABLE);
}

首先发现了一个bug
ADC_InjectedChannelConfig函数的描述内rank的解释有问题他的取值范围说明是1~4,但实测是0~3.

在中断内读取ADC1->IDATAR1~ADC1->IDATAR3,发现他们的值居然不随外部的电压变化,经使用demo测试判断硬件是没有问题的。
这个问题已经折腾2天,目前没有任何进展,望技术支持





  

回帖(2)

吴纯英

2022-5-12 15:00:55
有两处需要注意一下:
1、若程序中用到中断,注意要加中断声明,即需要采用__attribute__((interrupt("WCH-Interrupt-fast")))声明,具体可参照下图
2、使用ADC时,由于ADC内部通道和外部通道共用一个转换单元,同时使用时,需要先将内部通道使能关掉,待外部通道采样完成再开启使能内部通道。
关于你反馈的ADC_InjectedChannelConfig函数 rank配置问题,首先感谢你的反馈,但rank的值为1-4应该是没问题的,具体可看ADC注入通道序列寄存器(ADC_ISQR),如下图。后续若有问题,可通过邮箱(lzs@wch.cn)跟我联系

举报

王燕

2022-5-12 15:01:00
原因就是启用了内部的温度通道,导致外部采样无法采样
举报

更多回帖

发帖
×
20
完善资料,
赚取积分