chipon芯旺微KF32A156/150系列ADC模块的使用教程

本文详细介绍了芯旺微32位机AD模块的四种工作模式:单通道、循环采样和多通道单次/循环扫描。重点讲解了配置步骤和注意事项,包括引脚配置、AD模块设置和数据获取方式,以及中断和DMA应用的建议。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

请尊重原创,转载需要注明源出处!!!

hello大家好,今天主要来说一下芯旺微32位机的AD模块的使用。本篇文章较长,如有需要不同模式,请耐心仔细看完。首先看一下官方手册提供的AD模块的简介:
在这里插入图片描述
可以看到,AD模块对于常规的使用完全能够覆盖。我们最常用的也就是普通AD通道的采样方式。
AD普通通道同一个ADC模块可以同时配置16个普通通道和4个高优先级通道,在我们使用过程中,不建议两种通道混合使用,本篇以普通通道来讲解。
本次主要讲解三种模式:单通道采样,单通道循环采样,多通道单次扫描采样,多通道循环扫描采样

说在前面:首先AD电路采样电压不建议超过VDDA的电压。
在进行软件配置之前:
首先要对引脚是否能够实现进行确认。通过数据手册的 模拟功能引脚表 进行查询,如图1
图1

通过上图可以看到,144pin的第36脚可实现AD通道号96(ADC_CH96)。第44脚就无法实现AD通道的配置。

正文

使用说明:pin脚上的AD通道是属于硬件通道,这个标号是固定的,比如ADC_CH96,在每个ADC模块进行配置的时候,还需要进行配置采样通道标号(也就是前面说的一个ADC模块最多只能配置16个普通采样通道)。这个是通过软件自行配置。在后面的讲解中有所涉及,需要进行区分。

一、单通道采样配置(以PA1为例,轮询的方式查询结果),此模式触发一次开始采一个通道结束。

老三步:配置引脚,配置外设,配置中断。

1、进行引脚模式配置:配置为模拟端口

GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); ADC_CH66

2、AD模块配置,这里关键参数,时钟,扫描模式失能,循环模式失能,触发源全部失能,通道长度为1,配置1个通道顺序号

ADC_InitTypeDef adcStruct;

	ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟

	/* 初始化 ADC时钟源选择 */
	adcStruct.m_Clock = ADC_HFCLK;
	/* 初始化 ADC时钟分频 */
	adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
	/* 初始化 ADC扫描模式使能 */
	adcStruct.m_ScanMode = FALSE;  //扫描模式,一次触发只转换第一个通道
	/* 初始化 ADC连续转换模式 */
	adcStruct.m_ContinuousMode = ADC_SINGLE_MODE; //不使用连续转换功能,只对设置的通道采样一遍
	/* 初始化 ADC转换结果输出格式 */
	adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
	/* 初始化 ADC常规通道外部触发转换模式使能 */
	adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
	/* 初始化 ADC常规通道外部触发事件 */
	adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
	/* 初始化 ADC高优先级通道外部触发转换模式使能 */
	adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
	/* 初始化 高优先级通道外部触发事件 */
	adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
	/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
	adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
	/* 初始化 ADC常规通道扫描长度 */
	adcStruct.m_NumOfConv = 1; //扫描的长度配置为1个通道
	/* 初始化 ADC高优先级通道扫描长度 */
	adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
	ADC_Configuration (ADC0_SFR, &adcStruct);
	
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
	ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
	
	ADC_Cmd (ADC0_SFR, TRUE); //ADC使能

3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收:

		unsigned short  adc_value ;
		
        /*software triger adc Conversion*/
        ADC_Software_Start_Conv(ADC0_SFR);
        /*wait for the adc conversion to complete*/
        while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
        {
            ;
        }
        /*sampling GPIO PG4 adc value */
        adc_value = ADC_Get_Conversion_Value(ADC0_SFR);

提示:如果是使用中断,只需要将adc和adc的EOC中断打开即可,也就是单次采样结束中断。

二、单通道循环采样配置(以PA1为例,轮询的方式查询结果),此模式触发一次开始一直不间断采一个通道

1、进行引脚模式配置:配置为模拟端口

GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); //ADC_CH66

2、AD模块配置,这里关键参数,时钟,扫描模式失能,循环模式使能,触发源全部失能,通道长度为1,配置1个通道顺序号

ADC_InitTypeDef adcStruct;

	ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟

	/* 初始化 ADC时钟源选择 */
	adcStruct.m_Clock = ADC_HFCLK;
	/* 初始化 ADC时钟分频 */
	adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
	/* 初始化 ADC扫描模式使能 */
	adcStruct.m_ScanMode = FALSE;  //扫描模式,一次触发只转换第一个通道
	/* 初始化 ADC连续转换模式 */
	adcStruct.m_ContinuousMode = ADC_CONTINUOUS_MODE; //不使用连续转换功能,只对设置的通道采样一遍
	/* 初始化 ADC转换结果输出格式 */
	adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
	/* 初始化 ADC常规通道外部触发转换模式使能 */
	adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
	/* 初始化 ADC常规通道外部触发事件 */
	adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
	/* 初始化 ADC高优先级通道外部触发转换模式使能 */
	adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
	/* 初始化 高优先级通道外部触发事件 */
	adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
	/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
	adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
	/* 初始化 ADC常规通道扫描长度 */
	adcStruct.m_NumOfConv = 1; //扫描的长度配置为1个通道
	/* 初始化 ADC高优先级通道扫描长度 */
	adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
	ADC_Configuration (ADC0_SFR, &adcStruct);
	
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
	ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
	
	ADC_Cmd (ADC0_SFR, TRUE); //ADC使能

3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收,注意,普通通道AD通道采样后数据放在同一个寄存器,故而当上一个采样完成后应及时取走。

		unsigned short  adc_value ;
		
        /*software triger adc Conversion*/
        ADC_Software_Start_Conv(ADC0_SFR);
        /*wait for the adc conversion to complete*/
        while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
        {
            ;
        }
        /*sampling GPIO PG4 adc value */
        adc_value = ADC_Get_Conversion_Value(ADC0_SFR);

三、多通道单次扫描采样(以PA1/PE7为例,轮询的方式查询结果),此模式触发一次开始采2个通道后结束。

1、进行引脚模式配置:配置为模拟端口

GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); //ADC_CH66
GPIO_Write_Mode_Bits (GPIOB_SFR,GPIO_PIN_MASK_7, GPIO_MODE_AN); //ADC_CH67

2、AD模块配置,这里关键参数,时钟,扫描模式使能,循环模式失能,触发源全部失能,通道长度为2。配置2个通道顺序号

ADC_InitTypeDef adcStruct;

	ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟

	/* 初始化 ADC时钟源选择 */
	adcStruct.m_Clock = ADC_HFCLK;
	/* 初始化 ADC时钟分频 */
	adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
	/* 初始化 ADC扫描模式使能 */
	adcStruct.m_ScanMode = TRUE;  //扫描模式,一次触发只转换第一个通道
	/* 初始化 ADC连续转换模式 */
	adcStruct.m_ContinuousMode = ADC_SINGLE_MODE; //不使用连续转换功能,只对设置的通道采样一遍
	/* 初始化 ADC转换结果输出格式 */
	adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
	/* 初始化 ADC常规通道外部触发转换模式使能 */
	adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
	/* 初始化 ADC常规通道外部触发事件 */
	adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
	/* 初始化 ADC高优先级通道外部触发转换模式使能 */
	adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
	/* 初始化 高优先级通道外部触发事件 */
	adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
	/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
	adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
	/* 初始化 ADC常规通道扫描长度 */
	adcStruct.m_NumOfConv = 2; //扫描的长度配置为1个通道
	/* 初始化 ADC高优先级通道扫描长度 */
	adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
	ADC_Configuration (ADC0_SFR, &adcStruct);
	
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
	ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
	ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_67, 0x02);
	
	ADC_Cmd (ADC0_SFR, TRUE); //ADC使能

3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收:注意,普通通道AD通道采样后数据放在同一个寄存器,故而当上一个采样完成后应及时取走。

		unsigned short  adc_value ;
		
        /*software triger adc Conversion*/
        ADC_Software_Start_Conv(ADC0_SFR);
        /*wait for the adc conversion to complete*/
        while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
        {
            ;
        }
        /*sampling GPIO PG4 adc value */
        adc_value = ADC_Get_Conversion_Value(ADC0_SFR);

四、多通道单次扫描采样(以PA1/PE7为例,轮询的方式查询结果),此模式触发一次开始不间断采2个通道。

1、进行引脚模式配置:配置为模拟端口

GPIO_Write_Mode_Bits (GPIOA_SFR,GPIO_PIN_MASK_1, GPIO_MODE_AN); //ADC_CH66
GPIO_Write_Mode_Bits (GPIOB_SFR,GPIO_PIN_MASK_7, GPIO_MODE_AN); //ADC_CH67

2、AD模块配置,这里关键参数,时钟,扫描模式使能,循环模式使能,触发源全部失能,通道长度为2。配置2个通道顺序号

ADC_InitTypeDef adcStruct;

	ADC_Reset (ADC0_SFR); //复位ADC外设并打开ADC的时钟

	/* 初始化 ADC时钟源选择 */
	adcStruct.m_Clock = ADC_HFCLK;
	/* 初始化 ADC时钟分频 */
	adcStruct.m_ClockDiv = ADC_CLK_DIV_4; //4分频
	/* 初始化 ADC扫描模式使能 */
	adcStruct.m_ScanMode = TRUE;  //扫描模式,一次触发只转换第一个通道
	/* 初始化 ADC连续转换模式 */
	adcStruct.m_ContinuousMode = ADC_CONTINUOUS_MODE; //不使用连续转换功能,只对设置的通道采样一遍
	/* 初始化 ADC转换结果输出格式 */
	adcStruct.m_DataAlign = ADC_DATAALIGN_RIGHT; //转换的结果右对齐
	/* 初始化 ADC常规通道外部触发转换模式使能 */
	adcStruct.m_ExternalTrig_EN = FALSE; //常规通道失能外部条件触发ADC转换,
	/* 初始化 ADC常规通道外部触发事件 */
	adcStruct.m_ExternalTrig = ADC_EXTERNALTRIG_T1TRGO; //常规通道外部触发信号源配置为T1TRGO
	/* 初始化 ADC高优先级通道外部触发转换模式使能 */
	adcStruct.m_HPExternalTrig_EN = FALSE; //高优先级通道失能外部条件触发ADC转换,
	/* 初始化 高优先级通道外部触发事件 */
	adcStruct.m_HPExternalTrig = ADC_HPEXTERNALTRIG_CCP1_CH1; //高优先级通道触发信号源配置为CCP1的通道1
	/* 参考电压选择,取值为宏“ADC参考电压选择”中的一个。 */
	adcStruct.m_VoltageRef=ADC_REF_AVDD; //转换的参考电压源配置为VDDA
	/* 初始化 ADC常规通道扫描长度 */
	adcStruct.m_NumOfConv = 2; //扫描的长度配置为1个通道
	/* 初始化 ADC高优先级通道扫描长度 */
	adcStruct.m_NumOfHPConv = 1; //高优先级通道的扫描长度
	ADC_Configuration (ADC0_SFR, &adcStruct);
	
//这个库函数设置常规通道配置,其中第一参数为ADC模块,
//第二参数为硬件ADC通道标号,第三个参数为采样通道顺序标号。
	ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_66, 0x01);
	ADC_Regular_Channel_Config (ADC0_SFR, ADC_CHANNEL_67, 0x02);
	
	ADC_Cmd (ADC0_SFR, TRUE); //ADC使能

3、这里就不使用中断进行数据获取了,不配置中断,采用轮询的方式进行接收:注意,普通通道AD通道采样后数据放在同一个寄存器,故而当上一个采样完成后应及时取走。

		unsigned short  adc_value ;
		
        /*software triger adc Conversion*/
        ADC_Software_Start_Conv(ADC0_SFR);
        /*wait for the adc conversion to complete*/
        while (!ADC_Get_INT_Flag(ADC0_SFR, ADC_INT_EOC))
        {
            ;
        }
        /*sampling GPIO PG4 adc value */
        adc_value = ADC_Get_Conversion_Value(ADC0_SFR);

以上就是ADC的基本使用了。
总结:使用中断来取普通通道转换的数据的方式也都是可以的,芯旺微提供了两个中断源来进行使用,一次采样完成中中断,全部采样完成中断。可以根据自身需求进行选择。

建议:当我们使用多通道扫描或者循环采样的时候,尽可能选择DMA搬运的方式,一来节省CPU资源,二来也能及时的取走数据的以免被下一次的采样数据覆盖导致错误数据。 DMA搬运的方式后续再更。可自行研究一下。

好啦,本次ADC使用就讲解完了。如有待完善的点,欢迎指正。

本次更新时间:2023.12.15

### KF32A156 控制器 DMA 配置与故障排除 #### DMA 功能概述 KF32A156 是一款高性能的控制器,内置了直接存储器访问 (DMA) 控制器来提高数据传输效率并减轻 CPU 负担。DMA 可用于多种外设之间的高效数据传输操作[^1]。 #### DMA 配置流程 配置 DMA 的过程涉及多个寄存器设置: - **使能 DMA**: 使用 `RCC_AHBPeriphClockCmd` 函数启用 DMA 时钟。 - **初始化 DMA 结构体**: 创建一个 `DMA_InitTypeDef` 类型结构体实例,并填充必要的参数,如通道编号、方向、缓冲区大小等。 - **启动 DMA 请求**: 设置好源地址、目标地址以及传输数量后调用 `DMA_Cmd(DMA_Channel, ENABLE)` 来激活指定通道上的 DMA 操作。 ```c // 启动 DMA 时钟 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); // 初始化 DMA 参数 DMA_InitTypeDef dma_init; dma_init.DMA_PeripheralBaseAddr = PERIPHERAL_ADDRESS; // 外设基址 dma_init.DMA_Memory0BaseAddr = MEMORY_BUFFER; // 存储器起始地址 dma_init.DMA_DIR = DMA_DIR_PeripheralToMemory; // 数据流向 dma_init.DMA_BufferSize = BUFFER_SIZE; // 缓冲区长度 dma_init.DMA_PeripheralInc = DMA_PeripheralInc_Disable; // 是否增加外设指针 dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable; // 是否增加内存指针 dma_init.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; dma_init.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; dma_init.DMA_Mode = DMA_Mode_Normal; // 正常模式或循环模式 dma_init.DMA_Priority = DMA_Priority_High; // 中断优先级 dma_init.DMA_FIFOMode = DMA_FIFOMode_Disable; // FIFO 模式开关 dma_init.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;// FIFO 阈值设定 dma_init.DMA_MemoryBurst = DMA_MemoryBurst_Single; // 内存突发传送方式 dma_init.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA1_Channel1, &dma_init); DMA_Cmd(DMA1_Channel1, ENABLE); // 开启 DMA 通道 ``` #### 常见问题及解决方案 - **无法触发 DMA 请求** 如果发现程序运行过程中未能成功发起 DMA 请求,则需确认相关外设已正确配置中断请求位;另外还需验证所使用的 DMA 通道是否已被其他功能占用。 - **数据不一致错误** 当遇到数据读写异常情况时,应仔细检查源/目的地址计算逻辑是否有误,确保每次传输前都重置相应的计数器变量。此外还要注意防止越界访问导致的数据覆盖风险。 - **性能瓶颈** 若感觉系统整体响应速度较慢,可以尝试调整 DMA 工作模式(例如切换到双缓冲或多路复用),优化硬件资源利用率从而提升吞吐量表现。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值