STM: 5.ADC模数转换

5.1 ADC模数转换原理

       ADC就是一种数模转换器。ADC的输入电压为0-3.3v,如果ADC我们设置为12位,那么3.3v对应这2的12次方即4096,那么单位数字量对应的模拟量则为3.3/4096。而ADC的功能可以获取数字量X,那么读取ADC获取的数字量X再乘以3.3/4096,就是电压值。

        12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部 信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右 对齐方式存储在16位数据寄存器中。 模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。 ADC的输入时钟不得超过14MHz,它是由PCLK2经分频产生。

5.1.1 ADC电路结构

        注入通道:最多一次性选4路通道,配合4个16位寄存器,就可以一次性转换4路模拟数据。
        规则通道:最多一次性选16路通道,但只有1个16位寄存器,存在新来的数据覆盖上一个数据的问题,此时要么尽快将数据取走,要是使用DMA帮助转运数据,进而可以实现一次性转换16路模拟数据。当然,一次就选一个通道,就是普通的ADC功能。
        触发转换电路:stm32中的ADC触发方式:
                软件触发:在程序中手动调一句代码。
                硬件触发:上图所示的触发源。主要来自于定时器TIMx,也可以外部中断引脚EXTI。正常思路是:定时器每隔1ms产生一次中断 --> 中断函数中开启触发转换信号 --> ADC完成一次转换。
        VDDA、VSSA:ADC的供电引脚。
        VREF+、VREF-:ADC的参考电压,决定了ADC的输入电压的范围。stm32内部已经和VDDA、VSSA连接在一起了。
        ADCCLK:来自ADC的预分频器,这个ADC的预分频器则来自于“RCC时钟树”。具体可以查看时钟树的电路,默认情况就是对72MHz进行ADC预分频,由于ADCCLK最大18MHz,所以只能选择6分频/8分频。
        DMA请求:触发DMA进行数据转运。下一章讲。
注入通道数据寄存器、规则通道数据寄存器:用于存放转换结果。
        模拟看门狗:一旦高于上阈值或低于下阈值,就会申请模拟看门狗的中断,最终进入NVIC。
        转换结束EOC:规则通道转换完成,会在状态寄存器置标志位。
        注入转换结束JEOC:注入通道转换完成,会在状态寄存器置标志位。
        NVIC:嵌套向量中断控制器,控制是否响应上面这三个中断。

 

5.1.2 规则组的转换模式

        stm32的ADC最多同时支持16个通道,那么ADC每次扫描1个通道还是多个通道,便是选择 非扫描模式/扫描模式;而对于单个通道的ADC转换来说,触发一次ADC是只转换一次,还是自动的进行连续转换,便是选择 单次转换/连续转换。两两组合就有四种模式。

        1.单次转换、非扫描模式

        触发一次仅转换一次。读取数据时,需要等待EOC标志位置1,然后从数据寄存器读取结果。如要再进行转换,就需要再次触发转换。

        2. 连续转换、非扫描模式
        仅需要一次触发,ADC就会在一次转换完成后立刻进入下一次转换,实现不断地自动进行转换。此时就不需要读EOC看转换是否完成,直接想读数据的时候就读。

        3. 单次转换、扫描模式
        可以一次性转换多个通道,不过还是触发一次、所有通道只转换一次。

        4. 连续转换、扫描模式
        不仅可以一次性转换多个通道,还可以实现触发一次、自动不间断转换。

5.1.3 数据对齐

        

        右对齐【常用】:读出的值就是实际值。

        左对齐:有时候不需要太大的分辨率,便将12位ADC的转换数据左对齐,然后只取高8位。

void adcInit (void)
{

	//IO初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC, ENABLE);
				
	GPIO_InitTypeDef GPIO_InitStructure = {0};      //创建结构体
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;          //选择引脚
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       //选择速度
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;      //选择模拟输入
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;          //选择引脚
	GPIO_Init(GPIOC, &GPIO_InitStructure);
	
	//外设初始化
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);          //ADC的时钟频率
	
	ADC_DeInit(ADC1);
	ADC_InitTypeDef ADC_InitStructure = {0}; 
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;      //独立工作模式
	ADC_InitStructure.ADC_ScanConvMode = ENABLE;          //是否开启扫描
	ADC_InitStructure.ADC_ContinuousConvMode =ENABLE;       //是否开启连续模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;        //触发方式
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;              //对齐方式
	ADC_InitStructure.ADC_NbrOfChannel = 2;                  //通道个数
	
	ADC_Init(ADC1, &ADC_InitStructure); 
	ADC_Cmd(ADC1,ENABLE);          //启动ADC

	//校准
	ADC_ResetCalibration(ADC1);                //重置ADC校准
	
	while(ADC_GetResetCalibrationStatus( ADC1))            //等待初始化完成
	{
		ADC_StartCalibration(ADC1);              //	开始校准 
	}
	
	while (ADC_GetCalibrationStatus(ADC1));          	// 等待校准完成 
	
	ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_239Cycles5);   //规定规则组内转换顺序,采样时间	
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);       // 启动转换   软件触发
    ADC_DMACmd(ADC1, ENABLE); 
	
}


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值