这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 灵动微MM32G0001A6T的ADC转换---任意通道单次周期转换模式

共4条 1/1 1 跳转至

灵动微MM32G0001A6T的ADC转换---任意通道单次周期转换模式

专家
2024-01-13 19:04:28   被打赏 50 分(兑奖)     打赏

在单周期扫描模式下,A/D 转换通道依软件配置执行一遍,具体流程如下:

1、软件设置寄存器 ADC_ANY_CFG,ADC_CHANY0,ADC_CHANY1,将需要转换的通道、数量设置好,然后置位 CHANY_MDEN。

2、通过软件、外部触发置位 ADCR 寄存器的 ADST,外部触发可软件配置触发延时,A/D 转换方向从CHANY_SEL0 到 CHANY_SEL8 转换通道数量由 CHANY_NUM 配置, 且 CHANY_SEL0 到CHANY_SEL8 是任意配置的,可以完全相同,或完全不相同。

3、每路 A/D 转换完成时,A/D 转换的数据值将有序装载到相应通道的数据寄存器中,ADIF 转换结束标志被设置,若此时控制寄存器 ADCR 的 ADIE 位置 1,将产生 AD 转换结束中断请求。

4、A/D 转换结束后,ADST 位自动清 0,A/D 转换器进入空闲模式。

若在 A/D 转换过程中,软件更新 ADC_ANY_CFG, ADC_CHANY0, ADC_CHANY1,硬件不会立即更新这些配置,只会在当前设置的通道都转换结束时更新,然后等待下一次软件软件置位 ADST。

1.png按照以上说明,我们使用库函数模式,编程测试这种模式下的ADC处理。使用PA3作为ADC的输入,设置ADC中断。每次转换完成后,通过OLED显示,并输出给串口2。根据功能服用,需要设置PA3用于ADC输入通道。

2.png引脚说明:

图片1.png为此在设置ADC时,需要设置ADC1的通道2,并使PA3作为输入口:

主要代码如下:


// 初始化ADC设备,此处只使用PA3作为输入通道
void ADC_Configure(void) {
    ADC_InitTypeDef  ADC_InitStruct;
    GPIO_InitTypeDef GPIO_InitStruct;
    NVIC_InitTypeDef NVIC_InitStruct;
    // 允许时钟
    RCC_APB1PeriphClockCmd(RCC_APB1ENR_ADC1, ENABLE);
    ADC_StructInit(&ADC_InitStruct);
    ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;         // 设置分辨率
    ADC_InitStruct.ADC_PRESCARE   = ADC_PCLK1_PRESCARE_16;      // 时钟分频
    ADC_InitStruct.ADC_Mode       = ADC_Mode_Scan;              // 模式:单次周期
    ADC_InitStruct.ADC_DataAlign  = ADC_DataAlign_Right;        // 数据右对齐
    ADC_Init(ADC1, &ADC_InitStruct);
    ADC_SampleTimeConfig(ADC1, ADC_Samctl_240_5);
    ADC_ClearFlag(ADC1, ADC_FLAG_EOC);                          // 清除比较标志
    ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);                     // 允许转换中断
    RCC_AHBPeriphClockCmd(RCC_AHBENR_GPIOA, ENABLE);
    /* 配置输入通道:PA3(通道2) */
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_3;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
    // 配置ADC中断
    NVIC_InitStruct.NVIC_IRQChannel = ADC1_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelPriority = 0x01;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStruct);
    // 使能ADEN位,即使能ADC转换
    ADC_Cmd(ADC1, ENABLE);
}
// 获取ADC通道数据。ADC完成后会产生中断
float ADC_GetChannelVoltage(ADCCHANNEL_TypeDef Channel) {
    uint16_t Value = 0;
    float Voltage;
    ADC_ANY_NUM_Config(ADC1, 0);
    ADC_ANY_CH_Config(ADC1, 0, Channel);
    ADC_ANY_Cmd(ADC1, ENABLE);
    // 清除中断标志
    ADC_InterruptFlag = 0;
    // 启动转换
    ADC_SoftwareStartConvCmd(ADC1, ENABLE);
    
    // 等待ADC转换完成后产生的中断标志
    while (0 == ADC_InterruptFlag) {
        
    }
    
    // 取得转换结果
    Value = ADC_GetConversionValue(ADC1);
    
    adc_result = Value;
    // 禁止中断
    ADC_ANY_Cmd(ADC1, DISABLE);
    // 转换为电压值
    Voltage = (float)Value / (float)4096 * (float)3.3;
    return (Voltage);
}

中断处理:


void ADC1_IRQHandler(void) {
    if (RESET != ADC_GetITStatus(ADC1, ADC_IT_EOC)) {
// 设置中断标志
        ADC_InterruptFlag = 1;
// 清除状态标志:转换完成的中断标志
        ADC_ClearITPendingBit(ADC1, ADC_IT_EOC);
    }
}


测试结果:


感觉误差还有稍微有点大,不知道是不是和我的测试环境有关。

程序源码:

adc.zip





关键词: 菜鸟学单片机     MM32G0001A6T     ADC    

高工
2024-01-13 20:22:21     打赏
2楼

学习了


专家
2024-01-14 00:35:23     打赏
3楼

为了调试串口,自己又开始作,把SWCLK配置成串口输出。然后这个片子就彻底挂了,不能再烧录程序,无论如何也恢复不了了。唉,厂家也是,明明有这个问题,就应该有解决办法,比如预留一个BOOT管脚。不知道设计的时候,是咋想的。


专家
2024-01-22 03:21:38     打赏
4楼

学习了,谢谢分享!


共4条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]