1.3. GPADC
SARADC是12 Bit ADC(A/D转换器),支持6bit/8bit/10bit/12bit数据位宽采样,该外设时钟最大不可超过12MHz,最小250KHz。
Note
该外设涉及的源码文件包括 gpadc.c,gpadc.h,gpadc_api.h。
1.3.1. GPADC相关宏配置
1.3.1.1. 数据采样位宽配置
GPADC持6bit/8bit/10bit/12bit数据位宽采样。
//ADC采样数据位宽
#define ADC_SEL_6_BIT (0x0)
#define ADC_SEL_8_BIT (0x1)
#define ADC_SEL_10_BIT (0x2)
#define ADC_SEL_12_BIT (0x3)
#define ADC_BIT_SEL ADC_SEL_12_BIT //adc工作采样宽度
1.3.1.2. 时钟配置
GPADC时钟最大不可超过12MHz。
#define ADC_CLK (300000L) //非DNA单通道模式工作时钟
#define ADC_DMA_CONTI_CLK (10000000L) //DMA单通道模式工作时钟
1.3.2. GPADC采集通道
GPADC采集通道包括普通IO通道,模拟ANA通道(含PMU等通道),差分DIFF通道。
enum AD_CH {
//ANA通道(模拟通道只支持CPU采集,不支持DMA采集)
AD_ANA_PMU_CH_VBG = (AD_PMU_TEST | ADC_PMU_CH_VBG),
AD_ANA_PMU_CH_VP17,
AD_ANA_PMU_CH_VLCD_DIV_4,
AD_ANA_PMU_CH_AVDDR_DIV_2,
AD_ANA_PMU_CH_VTEMP,
AD_ANA_PMU_CH_VPWR_DIV_4,
AD_ANA_PMU_CH_AVDDCP_DIV_4,
AD_ANA_PMU_CH_AVDDCP_DIV_2,
AD_ANA_PMU_CH_AVDDCP_VB17,
AD_ANA_PMU_CH_DCVDD = (AD_PMU_TEST | ADC_PMU_CH_DCVDD),
AD_ANA_PMU_CH_DVDD,
AD_ANA_PMU_CH_WVDD = (AD_PMU_TEST | ADC_PMU_CH_WVDD),
//IO通道(支持CPU采集和DMA采集)
AD_CH_PA0 = (AD_IO_TEST | ADC_IO_CH_PA0),
AD_CH_PA8,
AD_CH_PA4,
AD_CH_PA12,
AD_CH_PA2,
AD_CH_PA10,
AD_CH_PA6,
AD_CH_DM,
AD_CH_PA1,
AD_CH_PA9,
AD_CH_PA5,
AD_CH_DP,
AD_CH_PA3,
AD_CH_PA11,
AD_CH_PA7,
//DIFF通道(支持CPU采集和DMA采集)
AD_DIFF_CH_SP_PA2_SN_PA3 = (AD_DIFF_TEST | ADC_DIFF_CH_SP_PA2_SN_PA3),
AD_DIFF_CH_SP_PA2_SN_PA4,
AD_DIFF_CH_SP_PA2_SN_PA5,
AD_DIFF_CH_SP_PA3_SN_PA2 = (AD_DIFF_TEST | ADC_DIFF_CH_SP_PA3_SN_PA2),
AD_DIFF_CH_SP_PA3_SN_PA4 = (AD_DIFF_TEST | ADC_DIFF_CH_SP_PA3_SN_PA4),
AD_DIFF_CH_SP_PA3_SN_PA5,
AD_DIFF_CH_SP_PA4_SN_PA2 = (AD_DIFF_TEST | ADC_DIFF_CH_SP_PA4_SN_PA2),
AD_DIFF_CH_SP_PA4_SN_PA3,
AD_DIFF_CH_SP_PA4_SN_PA5 = (AD_DIFF_TEST | ADC_DIFF_CH_SP_PA4_SN_PA5),
AD_DIFF_CH_SP_PA5_SN_PA2 = (AD_DIFF_TEST | ADC_DIFF_CH_SP_PA5_SN_PA2),
AD_DIFF_CH_SP_PA5_SN_PA3,
AD_DIFF_CH_SP_PA5_SN_PA4,
AD_DIFF_CH_VB = (AD_DIFF_TEST | ADC_DIFF_CH_VB),
};
1.3.3. GPADC采集模式
GPADC采集模式包括CPU采集模式,CPU阻塞采集模式,DMA多通道采集模式和DMA单通道采集模式。
Note
ANA通道只能使用CPU模式采集。工作在DMA单通道采集模式时,CPU模式无法同时工作。
1.3.3.1. CPU采集模式
由CPU访问,逐次读取各通道电压值。
该模式接口介绍如下。
1.3.3.1.1. adc_add_sample_ch
添加ch到CPU采集模式ADC采集队列
原型:
void adc_add_sample_ch(enum AD_CH ch);
- 参数:
ch
ADC通道
返回值
通道ADC值
示例:
adc_add_sample_ch(AD_CH_PA0);
1.3.3.1.2. adc_remove_sample_ch
删除CPU采集模式ADC采集队列里的ch
原型:
void adc_remove_sample_ch(enum AD_CH ch);
- 参数:
ch
ADC通道
返回值
无
示例:
adc_remove_sample_ch(AD_CH_PA0);
1.3.3.2. CPU阻塞采集模式
由CPU访问,阻塞CPU采集模式,打断ADC转换队列,立即获取对应通道的ADC值或电压值。
该模式接口介绍如下。
1.3.3.2.1. adc_get_value_by_blocking
阻塞CPU模式采集,打断ADC转换队列,立即获取对应通道的ADC值,不支持中断调用
原型:
s16 adc_get_value_by_blocking(u32 ch, u8 times)
- 参数:
ch
ADC通道
times
采集次数
返回值
通道ADC值
示例:
adc_get_value_by_blocking(AD_CH_PA0, 8);
1.3.3.2.2. adc_get_voltage_by_blocking
阻塞CPU模式采集,打断ADC转换队列,立即获取对应通道的电压值,内部做了滤波取平均处理,不支持中断调用
原型:
s16 adc_get_voltage_by_blocking(u32 ch, u8 times)
- 参数:
ch
ADC通道
times
采集次数
返回值
通道电压
示例:
adc_get_voltage_by_blocking(AD_CH_PA0, 8);
1.3.3.3. DMA多通道采集模式
通过配置固定的采样率和通道数,使用DMA多通道采集模式自动读取通道电压值。 使用DMA多通道采集模式的同时,CPU采集模式也可以同时操作读取不同通道电压值,但需要做好采样时间分配。
1.3.3.3.1. adc_dma_add_sample_ch
添加ch到DMA多通道采集模式ADC采集队列。
原型:
void adc_dma_add_sample_ch(enum AD_CH ch);
- 参数:
ch
ADC通道
返回值
通道ADC值
示例:
adc_dma_add_sample_ch(AD_CH_PA0);
1.3.3.3.2. adc_dma_remove_sample_ch
删除DMA多通道采集模式ADC采集队列里的ch。
原型:
void adc_dma_remove_sample_ch(enum AD_CH ch);
- 参数:
ch
ADC通道
返回值
无
示例:
adc_dma_remove_sample_ch(AD_CH_PA0);
1.3.3.4. DMA单通道采集模式
1.3.3.4.1. adc_dma_enter_single_ch_sample
ADC进入DMA单通道连续采集模式(该模式下CPU模式采样无法进行)。 注意需要与adc_dma_exit_single_ch_sample()成对使用。 回调函数16bits的buf,有效数据为bit16~4,低4位无效,读取时需>>4。
原型:
void adc_dma_enter_single_ch_sample(enum AD_CH ch, void (*gpadc_dma_irq_callback)(u16 *buf, u32 len));
- 参数:
ch
ADC通道
gpadc_dma_irq_callback
DMA单通道中断回调函数
返回值
无
示例:
adc_dma_enter_single_ch_sample(AD_CH_PA0, callback_func);
1.3.3.4.2. adc_dma_exit_single_ch_sample
ADC退出DMA单通道连续采集模式(恢复DMA多通道模式采集和CPU模式采集)。 注意需要与adc_dma_enter_single_ch_sample()成对使用。
原型:
void adc_dma_exit_single_ch_sample(enum AD_CH ch);
- 参数:
ch
ADC通道
返回值
无
示例:
adc_dma_exit_single_ch_sample(AD_CH_PA0);
1.3.3.5. 公共API
1.3.3.5.1. adc_init
GPADC初始化。
原型:
void adc_init(void);
- 参数:
无
无
1.3.3.5.2. adc_get_value
获取对应通道的ADC值。需确保通道有存在于CPU或DMA的采集队列,否则需先通过adc_add_sample_ch/adc_dma_add_sample_ch注册通道。
原型:
s16 adc_get_value(enum AD_CH ch);
- 参数:
ch
ADC通道
返回值
通道ADC值
示例:
adc_get_value(AD_CH_PA0);
1.3.3.5.3. adc_get_voltage
获取对应通道的电压值。需确保通道有存在于CPU或DMA的采集队列,否则需先通过adc_add_sample_ch/adc_dma_add_sample_ch注册通道。
原型:
s32 adc_get_voltage(enum AD_CH ch);
- 参数:
ch
ADC通道
返回值
通道电压
示例:
adc_get_voltage(AD_CH_PA0);
1.3.4. GPADC使用示例demo
#include "gpadc_api.h"
#include "asm/clock.h"
void gpadc_cpu_mode_demo(void)
{
printf("\n@_0 gpadc cpu mode demo test start\n");
printf("@_0 cpu add ch PA5\n");
adc_add_sample_ch(AD_CH_PA5);
printf("@_0 cpu add ch VPWR\n");
adc_add_sample_ch(AD_ANA_PMU_CH_VPWR_DIV_4);
mdelay(10);
printf("@_0 PA5 adc res: %d\n", adc_get_value(AD_CH_PA5));
printf("@_0 PA5 voltage: %dmV\n", adc_get_voltage(AD_CH_PA5));
printf("@_0 VPWR adc res: %d\n", adc_get_value(AD_ANA_PMU_CH_VPWR_DIV_4));
printf("@_0 VPWR voltage: %dmV\n", adc_get_voltage(AD_ANA_PMU_CH_VPWR_DIV_4) * 4);
printf("@_0 cpu remove ch PA5\n");
adc_remove_sample_ch(AD_CH_PA5);
printf("@_0 cpu remove ch VPWR\n");
adc_remove_sample_ch(AD_ANA_PMU_CH_VPWR_DIV_4);
}
void gpadc_dma_mode_demo(void)
{
printf("\n@_1 gpadc dma mode demo test start\n");
printf("@_1 dma add ch PA5\n");
adc_dma_add_sample_ch(AD_CH_PA5);
printf("@_1 dma add ch DIFF SP_PA2_SN_PA3\n");
adc_dma_add_sample_ch(AD_DIFF_CH_SP_PA2_SN_PA3);
mdelay(10);
printf("@_1 PA5 adc res: %d\n", adc_get_value(AD_CH_PA5));
printf("@_1 PA5 voltage: %dmV\n", adc_get_voltage(AD_CH_PA5));
printf("@_1 DIFF SP_PA2_SN_PA3 adc res: %d\n", adc_get_value(AD_DIFF_CH_SP_PA2_SN_PA3));
printf("@_1 DIFF SP_PA2_SN_PA3 voltage: %dmV\n", adc_get_voltage(AD_DIFF_CH_SP_PA2_SN_PA3));
printf("@_1 dma remove ch PA5\n");
adc_dma_remove_sample_ch(AD_CH_PA5);
printf("@_1 dma remove ch DIFF SP_PA2_SN_PA3\n");
adc_dma_remove_sample_ch(AD_DIFF_CH_SP_PA2_SN_PA3);
}
void gpadc_blocking_mode_demo(void)
{
printf("\n@_2 gpadc blocking mode demo test start\n");
printf("@_2 PA8 adc res: %d\n", adc_get_value_by_blocking(AD_CH_PA8, 8));
printf("@_2 PA8 voltage: %dmV\n", adc_get_voltage_by_blocking(AD_CH_PA8, 8));
}
void gpadc_dma_conti_mode_callback(u16 *buf, u32 len)
{
/* printf("len: %d\n", len); */
}
void gpadc_dma_conti_mode_demo(void)
{
printf("\n@_3 gpadc blocking mode demo test start\n");
printf("@_3 enter sample DIFF SP_PA2_SN_PA3\n");
adc_dma_enter_single_ch_sample(AD_DIFF_CH_SP_PA2_SN_PA3, gpadc_dma_conti_mode_callback);
mdelay(1);
printf("@_3 exit sample DIFF SP_PA2_SN_PA3\n");
adc_dma_exit_single_ch_sample(AD_DIFF_CH_SP_PA2_SN_PA3);
}
//gpadc测试demo
void gpadc_test_demo(void)
{
printf("\n***** GPADC module test begin *****\n");
adc_init();
//cpu模式测试
gpadc_cpu_mode_demo();
//dma模式测试
gpadc_dma_mode_demo();
//打断模式测试
gpadc_blocking_mode_demo();
//dma单通道测试
gpadc_dma_conti_mode_demo();
printf("\n***** GPADC module test end *****\n");
}