第十九章 AT32F403A基于V2库 adc采集

目录

概述

硬件

ADC

软件

初始化    

ADC转换时间

初始化代码

采样代码

取平均值

测试

最后


概述

         本文主要是使用AT32F403A开发板,基于V2库实现adc采集电压的功能。

         串口工具使用的Atlink-ez自带的串口功能。

         工程建立、调试工具配置在前面章节有详细介绍。


硬件

         硬件方面使用的是参考官方AT32F437 SURF板子而设计的一个AT32F403A开发板,板子上的芯片是AT32F403AVGT7的型号,开发板上面还板载了一个atlink-ez的仿真器,atlink-ez除了可以在线仿真和下载之外还有一个串口的功能,硬件上是通过跳线帽接到了MCU的串口1,pa9/10上面。

        如下图是开发板pcb图,以及硬件资源。(左边上角的就是atlink-ez,用usb线接到pc即可):

        如下是实物图:

        本功能是使用ad采集可变电阻的电压值,相关原理图如下:


ADC

         ADC也就是模数转换,把外部电路的电压转换成具体的数值,在根据参考电压就可以计算出外部电路的实际电压值。

         AT32F403A有三个12bit的ADC转换器,ADC的工作时钟最高是28M,采样率最高可达 2MSPS,多达 18 个通道源可进行采样及转换,其中最后两个通道是连接到了内部电压和内部温度传感器,其他的16个通道都是对外的。

        如上图,PA1是ADC123_IN1,ADC123是指的ADC的三个转换器,PA1可以使用ADC1转换器,也可以使用ADC2转换器,也可以使用ADC3转换器,IN1指的是通道1。

         AT32系列的ADC供电要求是2.6V到3.6V ,ADC输入范围是VREF- ≤ VIN ≤ VREF+,VREF+也就是参考电压,这个引脚是100pin才有的引脚,小于100pin的是内部连接到vcc上,在电压方面最高必须是3.6v,大于这个值的都会对adc转换器产生影响,导致所有的adc的采用都是不对的。


软件

初始化    

         本文使用ADC1的通道10来转换电压,也就是PC0,IO要设置为模拟输入模式,无上下拉。

         开启ADC1的时钟,设置ADC分频系数,ADC123都是挂载在apb2总线下面,所以ADC的工作时钟是apb2总线的时钟除以ADC的分频系数,当系统时钟为240M,apb2为120M时钟,那么ADC的分频系数最小是六分频,也就是20M的工作时钟,因为AT32F403A的ADC的工作时钟最高是28M。

ADC转换时间

         ADC转换时需要时间的,转换时间计算方式如下图:

         采样时间由下面函数设置:图中设置的是239.5周期。

         接上面的我们设置的ADC的工作时钟20M,那么周期就是0.05us,转换时间就是239.5+12.5个周期,即252*0.05=12.6us,一次完整的转换时间就是12.6us。

ADC参数结构体如下:

         typedef struct

{

  confirm_state                          sequence_mode;           /*!< adc sequence mode */

  confirm_state                          repeat_mode;             /*!< adc repeat mode */

  adc_data_align_type                    data_align;              /*!< adc data alignment */

  uint8_t                                ordinary_channel_length; /*!< adc ordinary channel sequence length*/

} adc_base_config_type;

         sequence_mode:顺序转换模式

         repeat_mode:重复转换模式

         data_align:adc数据对齐

         ordinary_channel_length:普通通道数

        设置ADC工作模式位独立模式,这里我们只是转换1个通道,并且不需要重复转换,所以前面两个参数都不使能,数据一般是设置右对齐,普通通道的数量为1,开启软件触发方式,使能ADC,最后在校准下adc,初始化就完成了。后续需要转换时,设置通道并调用软件触发即可进行ad的采集。

         需要注意的是AT32使用adc的时候,所使用的IO口不能悬空。当需要精度比较高的时候就对输入内阻要求内阻要小,所以当没有速度需求的时候尽量降低ADC工作时钟,加大采样时间,同时使用多次采样并去掉第一个值和最后一个值然后求平均的方式。

初始化代码

/*
*adc 轮询采样
*ADC1-CH10 (PC0)
*软件触发
*普通通道转换
*
*/

void adc_loop_init(void)
{
	gpio_init_type gpio_initstructure;
	adc_base_config_type adc_base_struct;

	crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);		//开启gpioc时钟
	crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);		//开启ADC1时钟
	crm_adc_clock_div_set(CRM_ADC_DIV_6);						//时钟六分频。

	gpio_default_para_init(&gpio_initstructure);
	gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;			//模拟输入模式
	gpio_initstructure.gpio_pins = GPIO_PINS_0 ;				//PC0
	gpio_init(GPIOC, &gpio_initstructure);

	adc_combine_mode_select(ADC_INDEPENDENT_MODE);				//设置adc工作模式,独立模式
	
	adc_base_default_para_init(&adc_base_struct);
	adc_base_struct.sequence_mode = FALSE;						//关闭序列模式
	adc_base_struct.repeat_mode = FALSE;						//关闭重复模式
	adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;			//数据右对齐
	adc_base_struct.ordinary_channel_length = 1;				//通道数为1
	adc_base_config(ADC1, &adc_base_struct);					//初始化参数

	adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);		//普通通道触发设置为软件触发

	adc_enable(ADC1, TRUE);				//使能ADC1
	
	adc_calibration_init(ADC1);			//初始化校准
	while(adc_calibration_init_status_get(ADC1));	//初始化校准完毕
	adc_calibration_start(ADC1);				//开始校准
	while(adc_calibration_status_get(ADC1));	//校准完毕
  
}

采样代码

/*
*获得ADC值
*adc_channel:要获取的通道
*
*/

u16 get_adcval(adc_channel_select_type adc_channel)   
{
	adc_ordinary_channel_set(ADC1, adc_channel, 1, ADC_SAMPLETIME_239_5);	//ADC1,ADC通道,序列号1,采样时间为239.5周期	  			    
  
	adc_ordinary_software_trigger_enable(ADC1, TRUE);						//使能指定的ADC1的软件转换启动功能	
	 
	while(!adc_flag_get(ADC1, ADC_CCE_FLAG ));								//等待转换结束

	return adc_ordinary_conversion_data_get(ADC1);							//返回最近一次ADC1普通通道的转换结果
}

取平均值

/*
*获取adc平均值
*adc_channel:要获取的通道
*times:总次数
*去掉第一和最后一个数据再取平均值。
*/

u16 get_adcval_average(adc_channel_select_type adc_channel,u8 times)
{
	u16 adc_val[100];
	u32 adc_valsum=0;
	
	u8 cut;
	for(cut=0;cut<times;cut++)							//多次获取adc的值
	{
		adc_val[cut]=get_adcval(adc_channel);
		delay_ms(5);
	}
	for(cut=1;cut<times-1;cut++)						//去掉第一次和最后一次的值
	{
		adc_valsum+=adc_val[cut];
		
	}
	
	return adc_valsum/(times-2);						//返回平均值
}

测试

        测试代码

        通过每3秒采集12次通道1的值并且去掉第一个值和最后一个值取然后平均值。硬件上通过手动来调节可变电阻。

        测试结果

        手动调节可变电阻的时候,ad采集的值也在对应的变化,测试通过。

         电压的计算:采样得到的值*参考电压/4096(2的12次方)


最后

         有问题的可以加QQ群技术交流,同时相关代码上传到QQ群中。

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值