ADC
Stm32内置12位ADC,具体数目请查阅芯片选型手册。以stm32F103xx的内置ADC为例:
框图解析
1、ADC引脚
ADC供电要求:2.4V到3.6V
ADC输入范围:VREF- ≤ VIN ≤ VREF+
名称
| 信号类型
| 注解
|
VREF+
| 输入,模拟参考正极
| ADC正极参考电压。2.4V≤VREF+≤VDDA
|
VREF-
| 输入,模拟参考负极
| ADC负极参考电压。VREF-= VSSA
|
VDDA
| 输入,模拟电源
| ADC的电源,2.4V≤VDDA +≤VDD
|
VSSA
| 输入,模拟电源地
| ADC的电源地
|
ADCX_INX
| 输入,模拟输入信号源
| 模拟输入通道
|
设计原理图时,将VSSA和VREF-接地,VDDA和VREF+接3.3V,即可得到ADCX_INX的输入范围为:0~3.3V,使用现成的板子就不用在意这些引脚。
2、ADC输入通道
ADC有多达18个通道,其中,有16个作为外部信号源转换通道ADCX_INX,2个作为内部信号源转换通道:温度传感器、VREFINT。具体数目请查阅芯片选型手册,例如stm32c8t6只有12个通道,10个外部ADCX_IN0~9以及2个内部。每个外部通道ADCX_INX,对应着各自的IO口,具体查阅芯片手册。因此使用外部通道时,需要配置对应的IO口为模拟输入。
3、规则通道组和注入通道组
规则通道组(排队转换):
图 1
规则通道组有16个通道(1~16),每个通道按顺序(由通道1至通道16的顺序)转换ADC的外部信号源(ADC通道),例如图1,有四路需要转换的ADC1信号源,将ADC1的外部信号源IN1装入通道2、IN2装入通道3、IN5装入通道1、IN9装入通道4,则ADC1的转换顺序为IN5->IN1->IN2->IN9。
需要注意的是,规则通道组需要提前说明转换所需的通道个数,你转换几个外部信号源,就要先声明几个通道:转换1个信号,声明1个通道;转换4个信号,声明4个通道,等等。
具体操作:
首先,声明你所需要的通道数:配置ADC规则序列寄存器 1(ADC_SQR1) 的“L[3:0]:规则通道序列长度”位,配置你需要转换的通道数。然后,将外部信号源装入通道中:配置
ADC1->SQR1 &= ~(0XF<<20); //清零
ADC1->SQR1 &= ~(0X03<<20); //设置规则通道的数目
ADC1->SQR3 &= 0XFFF00000; //复位规则通道1、2、3、4
ADC1->SQR3 |= 0x05<<0; //将ADC1_IN5装入规则通道1
ADC1->SQR3 |= 0x01<<5; //将ADC1_IN1装入规则通道2
ADC1->SQR3 |= 0x02<<10; //将ADC1_IN2装入规则通道3
ADC1->SQR3 |= 0x09<<15; //将ADC1_IN9装入规则通道4
ADC1->CR2 |= 1<<22; //开始转换规则通道
while(!(ADC1->SR & 1<<1)); //判断SR的第一位,如果为0则继续等待,如果为1则跳出
return ADC1->DR; //返回AD转换结果
注入通道组(插队转换):
图 2
注入通道组有4个通道(1~4),因此它只有一个“ADC注入序列寄存器(ADC_JSQR)”,进行通道数的选择,以及装入外部信号源。注入通道组强行插入规则通道组进行转换,例如图2,有3个规则通道和2个注入通道,当转换完成规则通道1时,若发生了事件(中断等),于是插入了注入通道组,转换完注入通道组后,才回到规则通道组进行转换。
图 3
注入通道组的转换顺序有些特殊,我们来看看图3,注入通道组的4个通道以次放入了外部信号源IN5、IN1、IN9、IN3,若是使用4个注入通道,则他们的转换顺序即:IN5->IN1->IN9->IN3。若使用4个以下的通道,ADC注入序列寄存器(ADC_JSQR)中详细讲了:“不同于规则转换序列,如果JL[1:0]的长度小于4,则转换的序列顺序是从(4-JL)开始。”那么“从(4-JL)开始”是什么意思呢?例如:
我只要注入通道组转换3个外部信号源,因此声明了3个通道,那么它的转换顺序就是“从(4-3)开始”那就从编号1的通道开始,也就是通道2开始(通道1的编号是0,通道2是1以此类推),顺序就为IN1->IN9->IN3。
如果只需要2个通道,即(4-2),那就从编号2的通道开始,也就是通道3开始,顺序就为IN9->IN3。
如果只需要1个通道,即(4-1),那就从编号3的通道开始,也就是通道4开始,顺序就为IN3。
因此,外部信号源应根据通道数,放入对应的通道。操作方法同规则通道组,不同的只是转换顺序。
4、触发源
ADC设置好通道后,可以进行ADC转换了,ADC转换由“ADC控制寄存器 2(ADC_CR2)
”的“ADON”位控制。也可以由ADC_CR2寄存器的“EXTSEL” 位和“JEXTSEL” 位,来设置外部触发源触发ADC转换。触发源包括定时器触发和外部IO触发,设置好触发源后由该寄存器的“EXTTRIG”位和“JEXTTRIG”位,来启用外部触发源转换模式
5、转换时间
ADC时钟:
打开时钟树,我们可以看到,ADC的时钟ADCCLK由PCLK2经过分频产生,其能承受的最大时钟为14MHz,超过后精度就有所下降,因此我们需要找到“时钟配置寄存器(RCC_CFGR)”的ADC预分频器(ADCPRE),来配置ADCCLK的时钟,APB2预分频器若不分频,则PCLK2的时钟为最大时钟72MHz,若要ADCCLK≤14MHz,则72MHz/6 =12MHz。注:由于ADC时钟是根据PCLK2的时钟来计算的,PCLK2又由APB2预分频决定,再往前SYSCLK又由外部时钟、内部时钟决定,因此若改变系统时间的话,就需从系统时钟一路下来计算ADCCLK的时钟。
采样时间:
完成一个通道的读取叫做采样周期。公式为:采样周期=采样时间+12.5个时钟周期。采样时间就是采样一个通道所花费的时钟周期,通过“ADC采样时间寄存器 (ADC_SMPRx)”来设置各个通道的采样时间(每个通道均可以使用不同的采样时间),设置采样时间越长ADC转换越精确,反过来说,采样时间越短,转换的速度就越快。转换时间计算方法:1/ADCCLK*采样周期,例:ADCCLK为12MHz,采样时间设置为1.5周期,则转换时间为:1/12000000*(1.5+12.5)≈1.17us。注:ADC_SMPRx设置的是采样时间的时种周期,不是采样周期,它还要加上12.5个时钟周期才是采样周期,不要搞混了!
6、数据寄存器
ADC转换后,数据根据转换组,存放在“ADC规则数据寄存器(ADC_DR)”或“ADC 注入数据寄存器x (ADC_JDRx) (x= 1..4)”中。
规则数据寄存器:
规则数据寄存器是一个32位的寄存器,若仅使用单个ADC,则ADC1/ADC2/ADC3使用寄存器的低16位,若是同时使用两个ADC则ADC1使用低16位,ADC2使用高16位。由于ADC是12位的,因此数据还分左对齐模式和右对齐模式,由“ADC控制寄存器 2(ADC_CR2)”的“ALIGN数据对齐”位设置DR和JDR寄存器的数据对齐模式
规则数据寄存器仅有一个,为应付多个转换通道, DR寄存器采用覆盖数据的方法,将新的转换数据替换掉旧的转换数据,因此,单个通道转换完成后,必须先读取它的数据(读取DR寄存器),才可以继续下个转换,否则数据会被覆盖。最好的方法是使用DMA,将数据传输到内存里(sram等)。
注入数据寄存器:
与规则数据寄存器不同的是,注入数据寄存器有4个,对应着4个ADC注入通道,因此不存在数据覆盖的问题。
DMA请求:
除了数据寄存器,ADC转换完成后,还可以发送DMA请求,直接将数据经由DMA通道存入SRAM里,而不用存在数据寄存器中,只有ADC1、ADC3可以发送DMA请求。
7、中断
ADC转换完成后,可以产生中断,中断分为三种:规则通道转换结束中断,注入转换
通道转换结束中断,模拟看门狗中断。
转换结束中断:
转换结束中断就和普通的中断一样,中断后拉标志位,写中断服务函数等。通过ADC_CR1的“EOCIE规则通道转换结束中断”位和“JEOCIE注入通道转换结束中断”位,来允许中断。标志位在“ADC状态寄存器(ADC_SR)”中有说明。
模拟看门狗中断:
图 4
模拟看门狗,例如图4,我使用ADC转换模拟量,得到一个电压值为1.5V,而我的模拟看门狗设置的低阈值(LTR)为0.5V,高阈值(HTR)为2V,则不触发模拟看门狗中断。
图 5
例如图5,转换模拟量,得到的电压值为3V,超过了我设置的高阈值2V,结果触发模拟看门狗中断。同理,若得到的电压值低于低阈值,也触发模拟看门狗中断。高阈值由“ADC看门狗高阀值寄存器(ADC_HTR)”设置,低阈值由“ADC看门狗低阀值寄存器(ADC_LRT)”设置,因为ADC数据是12位的,因此这两个寄存器也使用12个位来设置其阈值,即最大值为4095(0xFFF),ADC->HTR=阈值/3.3*4095。注:阈值简单来说就是“限”,上限或者下限,超过上限或超过下限就产生中断。
8、电压转换
ADC有一个电压转换公式为:Y = (3.3 * X ) / 4096。Y为模拟电压值,X为转换后的数值,3.3是电压测量量程的最大值3.3V,4095是12位ADC的最大数值212,就有:
①:3.3V为模拟量,得3.3=Y;4095为ADC的数值,得4095=X。
②:因为最大测量电压为3.3V,而12位ADC的最大量程为4095,所以3.3V就对应4095。因此3.3*X=3.3*4095,同理3.3/X=3.3/4095。
最后,计算时应取最大量程为4096。公式Y = (3.3 * X ) / 4096就是这么来的
参考资料:野火秉火STM32
ADC
Stm32内置12位ADC,具体数目请查阅芯片选型手册。以stm32F103xx的内置ADC为例:
框图解析
1、ADC引脚
ADC供电要求:2.4V到3.6V
ADC输入范围:VREF- ≤ VIN ≤ VREF+
名称
| 信号类型
| 注解
|
VREF+
| 输入,模拟参考正极
| ADC正极参考电压。2.4V≤VREF+≤VDDA
|
VREF-
| 输入,模拟参考负极
| ADC负极参考电压。VREF-= VSSA
|
VDDA
| 输入,模拟电源
| ADC的电源,2.4V≤VDDA +≤VDD
|
VSSA
| 输入,模拟电源地
| ADC的电源地
|
ADCX_INX
| 输入,模拟输入信号源
| 模拟输入通道
|
设计原理图时,将VSSA和VREF-接地,VDDA和VREF+接3.3V,即可得到ADCX_INX的输入范围为:0~3.3V,使用现成的板子就不用在意这些引脚。
2、ADC输入通道
ADC有多达18个通道,其中,有16个作为外部信号源转换通道ADCX_INX,2个作为内部信号源转换通道:温度传感器、VREFINT。具体数目请查阅芯片选型手册,例如stm32c8t6只有12个通道,10个外部ADCX_IN0~9以及2个内部。每个外部通道ADCX_INX,对应着各自的IO口,具体查阅芯片手册。因此使用外部通道时,需要配置对应的IO口为模拟输入。
3、规则通道组和注入通道组
规则通道组(排队转换):
图 1
规则通道组有16个通道(1~16),每个通道按顺序(由通道1至通道16的顺序)转换ADC的外部信号源(ADC通道),例如图1,有四路需要转换的ADC1信号源,将ADC1的外部信号源IN1装入通道2、IN2装入通道3、IN5装入通道1、IN9装入通道4,则ADC1的转换顺序为IN5->IN1->IN2->IN9。
需要注意的是,规则通道组需要提前说明转换所需的通道个数,你转换几个外部信号源,就要先声明几个通道:转换1个信号,声明1个通道;转换4个信号,声明4个通道,等等。
具体操作:
首先,声明你所需要的通道数:配置ADC规则序列寄存器 1(ADC_SQR1) 的“L[3:0]:规则通道序列长度”位,配置你需要转换的通道数。然后,将外部信号源装入通道中:配置
ADC1->SQR1 &= ~(0XF<<20); //清零
ADC1->SQR1 &= ~(0X03<<20); //设置规则通道的数目
ADC1->SQR3 &= 0XFFF00000; //复位规则通道1、2、3、4
ADC1->SQR3 |= 0x05<<0; //将ADC1_IN5装入规则通道1
ADC1->SQR3 |= 0x01<<5; //将ADC1_IN1装入规则通道2
ADC1->SQR3 |= 0x02<<10; //将ADC1_IN2装入规则通道3
ADC1->SQR3 |= 0x09<<15; //将ADC1_IN9装入规则通道4
ADC1->CR2 |= 1<<22; //开始转换规则通道
while(!(ADC1->SR & 1<<1)); //判断SR的第一位,如果为0则继续等待,如果为1则跳出
return ADC1->DR; //返回AD转换结果
注入通道组(插队转换):
图 2
注入通道组有4个通道(1~4),因此它只有一个“ADC注入序列寄存器(ADC_JSQR)”,进行通道数的选择,以及装入外部信号源。注入通道组强行插入规则通道组进行转换,例如图2,有3个规则通道和2个注入通道,当转换完成规则通道1时,若发生了事件(中断等),于是插入了注入通道组,转换完注入通道组后,才回到规则通道组进行转换。
图 3
注入通道组的转换顺序有些特殊,我们来看看图3,注入通道组的4个通道以次放入了外部信号源IN5、IN1、IN9、IN3,若是使用4个注入通道,则他们的转换顺序即:IN5->IN1->IN9->IN3。若使用4个以下的通道,ADC注入序列寄存器(ADC_JSQR)中详细讲了:“不同于规则转换序列,如果JL[1:0]的长度小于4,则转换的序列顺序是从(4-JL)开始。”那么“从(4-JL)开始”是什么意思呢?例如:
我只要注入通道组转换3个外部信号源,因此声明了3个通道,那么它的转换顺序就是“从(4-3)开始”那就从编号1的通道开始,也就是通道2开始(通道1的编号是0,通道2是1以此类推),顺序就为IN1->IN9->IN3。
如果只需要2个通道,即(4-2),那就从编号2的通道开始,也就是通道3开始,顺序就为IN9->IN3。
如果只需要1个通道,即(4-1),那就从编号3的通道开始,也就是通道4开始,顺序就为IN3。
因此,外部信号源应根据通道数,放入对应的通道。操作方法同规则通道组,不同的只是转换顺序。
4、触发源
ADC设置好通道后,可以进行ADC转换了,ADC转换由“ADC控制寄存器 2(ADC_CR2)
”的“ADON”位控制。也可以由ADC_CR2寄存器的“EXTSEL” 位和“JEXTSEL” 位,来设置外部触发源触发ADC转换。触发源包括定时器触发和外部IO触发,设置好触发源后由该寄存器的“EXTTRIG”位和“JEXTTRIG”位,来启用外部触发源转换模式
5、转换时间
ADC时钟:
打开时钟树,我们可以看到,ADC的时钟ADCCLK由PCLK2经过分频产生,其能承受的最大时钟为14MHz,超过后精度就有所下降,因此我们需要找到“时钟配置寄存器(RCC_CFGR)”的ADC预分频器(ADCPRE),来配置ADCCLK的时钟,APB2预分频器若不分频,则PCLK2的时钟为最大时钟72MHz,若要ADCCLK≤14MHz,则72MHz/6 =12MHz。注:由于ADC时钟是根据PCLK2的时钟来计算的,PCLK2又由APB2预分频决定,再往前SYSCLK又由外部时钟、内部时钟决定,因此若改变系统时间的话,就需从系统时钟一路下来计算ADCCLK的时钟。
采样时间:
完成一个通道的读取叫做采样周期。公式为:采样周期=采样时间+12.5个时钟周期。采样时间就是采样一个通道所花费的时钟周期,通过“ADC采样时间寄存器 (ADC_SMPRx)”来设置各个通道的采样时间(每个通道均可以使用不同的采样时间),设置采样时间越长ADC转换越精确,反过来说,采样时间越短,转换的速度就越快。转换时间计算方法:1/ADCCLK*采样周期,例:ADCCLK为12MHz,采样时间设置为1.5周期,则转换时间为:1/12000000*(1.5+12.5)≈1.17us。注:ADC_SMPRx设置的是采样时间的时种周期,不是采样周期,它还要加上12.5个时钟周期才是采样周期,不要搞混了!
6、数据寄存器
ADC转换后,数据根据转换组,存放在“ADC规则数据寄存器(ADC_DR)”或“ADC 注入数据寄存器x (ADC_JDRx) (x= 1..4)”中。
规则数据寄存器:
规则数据寄存器是一个32位的寄存器,若仅使用单个ADC,则ADC1/ADC2/ADC3使用寄存器的低16位,若是同时使用两个ADC则ADC1使用低16位,ADC2使用高16位。由于ADC是12位的,因此数据还分左对齐模式和右对齐模式,由“ADC控制寄存器 2(ADC_CR2)”的“ALIGN数据对齐”位设置DR和JDR寄存器的数据对齐模式
规则数据寄存器仅有一个,为应付多个转换通道, DR寄存器采用覆盖数据的方法,将新的转换数据替换掉旧的转换数据,因此,单个通道转换完成后,必须先读取它的数据(读取DR寄存器),才可以继续下个转换,否则数据会被覆盖。最好的方法是使用DMA,将数据传输到内存里(sram等)。
注入数据寄存器:
与规则数据寄存器不同的是,注入数据寄存器有4个,对应着4个ADC注入通道,因此不存在数据覆盖的问题。
DMA请求:
除了数据寄存器,ADC转换完成后,还可以发送DMA请求,直接将数据经由DMA通道存入SRAM里,而不用存在数据寄存器中,只有ADC1、ADC3可以发送DMA请求。
7、中断
ADC转换完成后,可以产生中断,中断分为三种:规则通道转换结束中断,注入转换
通道转换结束中断,模拟看门狗中断。
转换结束中断:
转换结束中断就和普通的中断一样,中断后拉标志位,写中断服务函数等。通过ADC_CR1的“EOCIE规则通道转换结束中断”位和“JEOCIE注入通道转换结束中断”位,来允许中断。标志位在“ADC状态寄存器(ADC_SR)”中有说明。
模拟看门狗中断:
图 4
模拟看门狗,例如图4,我使用ADC转换模拟量,得到一个电压值为1.5V,而我的模拟看门狗设置的低阈值(LTR)为0.5V,高阈值(HTR)为2V,则不触发模拟看门狗中断。
图 5
例如图5,转换模拟量,得到的电压值为3V,超过了我设置的高阈值2V,结果触发模拟看门狗中断。同理,若得到的电压值低于低阈值,也触发模拟看门狗中断。高阈值由“ADC看门狗高阀值寄存器(ADC_HTR)”设置,低阈值由“ADC看门狗低阀值寄存器(ADC_LRT)”设置,因为ADC数据是12位的,因此这两个寄存器也使用12个位来设置其阈值,即最大值为4095(0xFFF),ADC->HTR=阈值/3.3*4095。注:阈值简单来说就是“限”,上限或者下限,超过上限或超过下限就产生中断。
8、电压转换
ADC有一个电压转换公式为:Y = (3.3 * X ) / 4096。Y为模拟电压值,X为转换后的数值,3.3是电压测量量程的最大值3.3V,4095是12位ADC的最大数值212,就有:
①:3.3V为模拟量,得3.3=Y;4095为ADC的数值,得4095=X。
②:因为最大测量电压为3.3V,而12位ADC的最大量程为4095,所以3.3V就对应4095。因此3.3*X=3.3*4095,同理3.3/X=3.3/4095。
最后,计算时应取最大量程为4096。公式Y = (3.3 * X ) / 4096就是这么来的
参考资料:野火秉火STM32
举报