384|2

1581

帖子

1

TA的资源

五彩晶圆(初级)

【航芯ACM32F403开发板测评】+A/D数据采集及程序分析 [复制链接]

在ACM32F403芯片内,集成了一个多通道的 12 位高精度ADC,其采集速度可达2M sps。

对于A/D数据采集,厂家提供了具用多种工作模式的Demo程序以供用户学习和验证。

以ADC_Test(TEST_POLLING_NCHANNELS)测试为例,其测试结果图1和图2所示。

image.png  

图1 串口通讯就绪

 

image.png  

图2 A/D数据采集

 

即每按下一次板上的用户键,就输出一轮多通道的数据采集值,其程序如下:

void ADC_Test_Polling_Nchannels(void)
{
    uint32_t i, VrefP, Voltage;
    uint32_t lu32_COM_OK  = 0;
    printfS("The ADC test ADC_Test_Polling_Nchannels start.");
    VrefP = ADC_GetVrefP(ADC_CHANNEL_8);
    printfS("The VrefP value is : %d \r\n", VrefP);
    UserKEY_Init();
    printfS("---------- Please press the USR_PB button ----------\r\n");
    ADC_Init_Polling_Nchannels();
    while(1)
    {
        while(false == UserKEY_Get());
        System_Delay_MS(500);
        for (i = 0; i < BUFFER_LENGTH; i++)
        {
            gu32_AdcBuffer[i] = 0;
        }
        HAL_ADC_Polling(&ADC_Handle, gu32_AdcBuffer, ADC_Handle.ChannelNum, 0);
        for (i = 0; i < ADC_Handle.ChannelNum; i++)
        {
            printfS("The adc convert result : Channel %d = 0x%08x. ", gu32_AdcBuffer[i]>>16 & 0xFF,gu32_AdcBuffer[i]);
            Voltage = (gu32_AdcBuffer[i]&0xFFF)*VrefP/4095;
            printfS("The Voltage is: %d mV \r\n", Voltage);
            lu32_COM_OK++;
        }
        printfS("ADC Test OK count %d times \r\n",  lu32_COM_OK);
    }
}

通过仔细观察,会发现这里少了对通道 ADC_CHANNEL_3 和ADC_CHANNEL_11的采集,这是为什么呢?

原来 ADC_CHANNEL_3所使用的引脚是PA2,而ADC_CHANNEL_11所使用的引脚是PA3。

而串口2的TX2所用的引脚正是PA2,RX2所用的引脚则是PA3,为此要使用串口2来输出信息,就必须回避对这2个引脚的使用。

当然,若使用串口1来输出信息是可以避开这个问题,但使用串口1就不能通过调试口来观察信息了,必须外接USB转TTL模块来进行串行通讯。

那为什么采集的通道顺序不是按自然的由小到大顺序呢?

原来这是与其初始化程序的编排有关,其内容为:

void ADC_Init_Polling_Nchannels(void)
{
    ADC_ChannelConfTypeDef ADC_ChannelConf;
    ADC_Handle.Init.ClockDiv = ADC_CLOCK_DIV8;
    ADC_Handle.Init.ConConvMode = ADC_CONCONVMODE_DISABLE;
    ADC_Handle.Init.JChannelMode = ADC_JCHANNELMODE_DISABLE;
    ADC_Handle.Init.DiffMode = ADC_DIFFMODE_DISABLE;
    ADC_Handle.Init.DMAMode = ADC_DMAMODE_DISABLE;
    ADC_Handle.Init.OverMode = ADC_OVERMODE_DISABLE;
    ADC_Handle.Init.OverSampMode = ADC_OVERSAMPMODE_DISABLE;
    ADC_Handle.Init.AnalogWDGEn = ADC_ANALOGWDGEN_DISABLE;
    ADC_Handle.Init.ExTrigMode.ExTrigSel = ADC_SOFTWARE_START;
    ADC_Handle.Init.ChannelEn = ADC_CHANNEL_0_EN | ADC_CHANNEL_1_EN | ADC_CHANNEL_2_EN | \
                                ADC_CHANNEL_4_EN | ADC_CHANNEL_5_EN | ADC_CHANNEL_6_EN | ADC_CHANNEL_7_EN | \
                                ADC_CHANNEL_8_EN | ADC_CHANNEL_9_EN | ADC_CHANNEL_10_EN |  \
                                ADC_CHANNEL_12_EN | ADC_CHANNEL_13_EN | ADC_CHANNEL_14_EN | ADC_CHANNEL_15_EN;

    ADC_Handle.Instance = ADC;
        
    HAL_ADC_Init(&ADC_Handle);

    /* The total adc regular channels number */
    ADC_Handle.ChannelNum = 14;
    
    /* Add adc channels */
    ADC_ChannelConf.Channel = ADC_CHANNEL_0;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ1;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;    
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_15;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ2;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_2;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ3;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_4;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ4;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_5;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ5;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_6;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ6;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_7;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ7;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_8;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ8;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_9;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ9;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_10;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ10;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_12;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ11;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_13;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ12;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_14;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ13;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
    
    ADC_ChannelConf.Channel = ADC_CHANNEL_1;
    ADC_ChannelConf.RjMode = 0;
    ADC_ChannelConf.Sq = ADC_SEQUENCE_SQ14;
    ADC_ChannelConf.Smp = ADC_SMP_CLOCK_320;   
    HAL_ADC_ConfigChannel(&ADC_Handle,&ADC_ChannelConf);
}

这样我们在看如下的主程序,就清晰了很多。

int main(void)  
{
    System_Init(); 
    Uart_Init();  
    ADC_Test(TEST_POLLING_NCHANNELS);
    while(1)
    {
    }
}

此外,在此基础上我们还以随意地裁剪采集的通道数量,乃至只采集需要的指定通道。

只采集通道0和通道15的结果如图3所示,连续对通道1进行数据采集的结果如图4所示。

image.png  

图3 双通道采集

 

image.png  

图4 单通道连续采集

 

最新回复

老师从各种角度都对ADC的驱动,实际串口输出进行了分享,很有借鉴意义,感谢分享优质作品!   详情 回复 发表于 2025-3-7 10:42

赞赏

1

查看全部赞赏


回复
举报

7183

帖子

11

TA的资源

版主

老师从各种角度都对ADC的驱动,实际串口输出进行了分享,很有借鉴意义,感谢分享优质作品!

点评

感谢支持,进行与大家进行分享。  详情 回复 发表于 2025-3-7 11:11

回复

1581

帖子

1

TA的资源

五彩晶圆(初级)

lugl4313820 发表于 2025-3-7 10:42 老师从各种角度都对ADC的驱动,实际串口输出进行了分享,很有借鉴意义,感谢分享优质作品!

感谢支持,进行与大家进行分享。


回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 15

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表