【AT-START-L021 测评】ADC采样
ADC 是一个将模拟输入信号转换为12位、10位、8位、6位的数字信号的外设。采样率最高可达2MSPS。多达19个通道源可进行采样及转换。
ADC 主要特征
模拟方面有以下特征:
- 支持分辨率12 位、10 位、8 位、6 位的转换
- 自校准时间: 154 个ADC 时钟周期
- ADC 转换时间
- ADC时钟在最大频率28MHz时转换时间为0.50 μs(分辨率12位时)
- ADC时钟在最大频率28MHz时转换时间为0.28 μs(分辨率6位时)
- ADC 供电要求:参考Datasheet
- ADC 输入范围:VSSA ≤ VIN ≤ VDDA
数字控制方面有以下特征:
- 通道管理区分优先权不同的普通通道与抢占通道
- 普通通道与抢占通道具备各自独立的触发侦测电路
- 各通道均可独立配置采样时间
- 转换顺序管理支持多种不同的多通道转换
- 过采样器:硬件过采样最高可实现16 位分辨率
- 可选择的数据对齐方式
- 可配置的电压监测边界
- 支持DMA 传输的普通通道数据
- 可设定以下事件发生时响应中断
- 抢占通道组转换结束
- 通道转换结束
- 电压监测超出范围
通道管理
模拟信号通道输入
每个ADC 拥有多达19个模拟信号通道输入,以ADC_INx 表示,x=0至18。 ADC_IN0至ADC_IN14为外部模拟输入,ADC_IN15、ADC_IN16为V~SSA~,ADC_IN17为内部参考电压,ADC_IN18为V~DDA~。
通道转换
转换区分为普通通道转换与抢占通道转换,抢占通道的转换优先权高于普通通道。
抢占通道触发若发生于普通通道转换途中,优先进行抢占通道的转换,普通通道于抢占通道转换结束后重新开始转换被打断的通道。普通通道触发若发生于抢占通道转换途中,普通通道的转换会等待抢占通道转换完成后才开始。
将通道(ADC_INx)编排进普通通道序列(ADC_OSQx)以及抢占通道序列(ADC_PSQ),相同通道可重复编排,序列总数由OCLEN 与PCLEN 定义,接着即可启动普通通道转换或抢占通道转换。
ADC基础操作流程
工程测试
1. 参考电压检测
使用 ADC1 内部通道17 监测 VREF 电压值
数据转换如下
- adc1_ordinary_value ---> adc1_channel_17
代码
主函数代码
int main(void)
{
__IO uint32_t index = 0;
system_clock_config();
at32_board_init();
at32_led_off(LED2);
at32_led_off(LED3);
at32_led_off(LED4);
uart_print_init(115200);
dma_config();
adc_config();
printf("adc1_vref_check \r\n");
while(1)
{
at32_led_on(LED2);
delay_ms(200);
adc_ordinary_software_trigger_enable(ADC1, TRUE);
while(dma_flag_get(DMA1_FDT1_FLAG) == RESET);
dma_flag_clear(DMA1_FDT1_FLAG);
printf("vref_value = %f V\r\n", ((double)1.2 * 4095) / adc1_ordinary_value);
}
}
效果
使用 Arduino IDE 串口绘图功能获取电压数值监测数据曲线
2. 六位分辨率采样
本项目展示了如何使用 6 位分辨率转换数据。 触发源设为软件。
数据转换如下
- adc1_ordinary_valuetabn ---> adc1_channel_4
- adc1_ordinary_valuetabn ---> adc1_channel_5
- adc1_ordinary_valuetabn ---> adc1_channel_6
代码
int main(void)
{
__IO uint32_t index = 0;
system_clock_config();
at32_board_init();
at32_led_off(LED2);
at32_led_off(LED3);
at32_led_off(LED4);
uart_print_init(115200);
gpio_config();
dma_config();
adc_config();
printf("resolution_6bit \r\n");
adc_ordinary_software_trigger_enable(ADC1, TRUE);
while(dma_trans_complete_flag == 0);
for(index = 0; index < 10; index++)
{
printf("adc1_ordinary_valuetab[%d][0] = 0x%x\r\n", index, adc1_ordinary_valuetab[index][0]);
printf("adc1_ordinary_valuetab[%d][1] = 0x%x\r\n", index, adc1_ordinary_valuetab[index][1]);
printf("adc1_ordinary_valuetab[%d][2] = 0x%x\r\n", index, adc1_ordinary_valuetab[index][2]);
}
at32_led_on(LED2);
while(1)
{
}
}
效果
短按 Reset 键,串口输出六位 ADC 采样值
resolution_6bit
adc1_ordinary_valuetab[0][0] = 0x1d
adc1_ordinary_valuetab[0][1] = 0x1a
adc1_ordinary_valuetab[0][2] = 0x1a
adc1_ordinary_valuetab[1][0] = 0x1a
adc1_ordinary_valuetab[1][1] = 0x1a
adc1_ordinary_valuetab[1][2] = 0x1a
adc1_ordinary_valuetab[2][0] = 0x1a
adc1_ordinary_valuetab[2][1] = 0x1a
adc1_ordinary_valuetab[2][2] = 0x1a
adc1_ordinary_valuetab[3][0] = 0x1a
adc1_ordinary_valuetab[3][1] = 0x1a
adc1_ordinary_valuetab[3][2] = 0x1a
adc1_ordinary_valuetab[4][0] = 0x1a
adc1_ordinary_valuetab[4][1] = 0x1a
adc1_ordinary_valuetab[4][2] = 0x1a
adc1_ordinary_valuetab[5][0] = 0x1a
adc1_ordinary_valuetab[5][1] = 0x1a
adc1_ordinary_valuetab[5][2] = 0x1a
adc1_ordinary_valuetab[6][0] = 0x1a
adc1_ordinary_valuetab[6][1] = 0x1a
adc1_ordinary_valuetab[6][2] = 0x1a
adc1_ordinary_valuetab[7][0] = 0x1a
adc1_ordinary_valuetab[7][1] = 0x1a
adc1_ordinary_valuetab[7][2] = 0x1a
adc1_ordinary_valuetab[8][0] = 0x1a
adc1_ordinary_valuetab[8][1] = 0x1a
adc1_ordinary_valuetab[8][2] = 0x1a
adc1_ordinary_valuetab[9][0] = 0x1a
adc1_ordinary_valuetab[9][1] = 0x1a
adc1_ordinary_valuetab[9][2] = 0x1a
3. 电压监测器
本项目展示了如何监视 ADC 频道的电压。
数据转换如下
- adc1_ordinary_valuetab[0] ---> adc1_channel_4
- adc1_ordinary_valuetab[1] ---> adc1_channel_5
- adc1_ordinary_valuetab[2] ---> adc1_channel_6
电压监测通道为:adc1_channel_5
代码
主函数代码如下
int main(void)
{
__IO uint32_t index = 0;
system_clock_config();
at32_board_init();
at32_led_off(LED2);
at32_led_off(LED3);
at32_led_off(LED4);
uart_print_init(115200);
gpio_config();
dma_config();
adc_config();
printf("voltage_monitoring \r\n");
while(1)
{
at32_led_toggle(LED2);
delay_ms(200);
if(vmor_flag_index == 1)
{
vmor_flag_index = 0;
printf("out of range:adc1_channel_5 value is = %x!\r\n", adc1_ordinary_valuetab[1]);
}
adc_ordinary_software_trigger_enable(ADC1, TRUE);
}
}
效果
板载 LED2 和 LED3 循环点亮。