首页 > 其他分享 >关于ADC的一些总结

关于ADC的一些总结

时间:2024-08-16 18:54:56浏览次数:17  
标签:总结 转换 规则 关于 ADC 寄存器 注入 通道

前言

        由于在STM32单片机中,主要是数字电路,而数字电路没有多少伏电压的概念,只有高电平和低电平两个概念,如果想要读取电压值,则需要经过ADC模数转换来读取对应引脚的模拟电压,然后存放到对应的寄存器种,通过变量来读取从而进行显示、判断等操作。

1.ADC(Analog-Digital Converter)模拟-数字转换器

         12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部 信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右 对齐方式存储在16位数据寄存器中。 

        上述为手册对ADC的介绍,接下来对上面一一进行解释:

        首先ADC是12位的,而一般的寄存器是16位的,所以在对ADC输出的数据进行存储的时候需要选择对齐方式,左对齐还是右对齐,在后续进行介绍。

        ADC模数转换的方法是一种逐次逼近的比较方法,实际上是用二分法来实现的,在后续进行介绍。

        然后ADC有18个通道输入,其中两个和芯片内部相连接,分别是温度传感器以及内部电压模块相连接,其他的16个通道就对应的接通到其他Pin端口,用于片外外设上的模拟信号读取,如下图。

        最后,这18个通道,都可以分别单独地配置 单次/连续、扫描/非扫描、间断/不间断模式,同样在后续进行介绍。

        同时ADC一般为1us转换时间 (根据产品型号,时钟频率有所不同)

        输入电压范围:0~3.3V,转换结果范围:0~40952的12次方-1)

        对应的是一个线性关系,用图来表示就是:

1.1ADC结构

        接下来看到ADC的结构图:

        首先看到主通道,ADCx_IN0~15,也就对应16个外部通道通过GPIO最终进入到ADC模块中,其中会经过一个数据选择器,同时输入还包含之前提到的温度传感器和内部电压模块

        他的名称为模拟多路开关,也就是决定哪个几个通道输出,可以看到输出可以输出至注入通道最多4通道,也可以输出至规则通道最多16通道

1.1.1注入组和规则组

        首先需要明确注入组和规则组:

        这里引用江科大的例子:

       这一整个过程类比为写菜单点菜,规则组菜单上最多可以写16道菜,如果写16个菜(输入16个规则通道),老板会一次性把16个菜做好(16个通道按顺序依次一次性执行),然而放菜的桌子仅能放一盘菜也就其他前15盘菜会被挤掉(覆盖)(对应的就是AD转换后的前15个规则通道数据都会被覆盖,只会留下IN15通道的数据。

        改进方法,通过DMA转运,防止转换后的数据被覆盖,也就叫服务员先把菜移至别的地方,在后续对DMA的会提到。

        然后是规则组,注入组则是菜单只能够写满四个菜(四个注入通道),同样老板也会一次性做好,在注入组的餐桌上正好能够摆满四个菜(四个注入通道转换后的数据都能够被存储),不会出现有菜被挤掉(覆盖)的情况。

1.1.2ADCCLK时钟

        同时能看到ADCCLK对ADC提供时钟,对应的时钟树部分:

        可以看到,一般都是由系统时钟72MHz输入到ADC预分频器,同时ADCCLK最大为14MHz,所以在系统时钟72MHz输入的情况下,ADC预分频器的值只能为6分频和8分频,对应输出ADCCLK为12MHz、9MHz。

1.1.3VREF+和VREF-

        VREF+和VREF-为参考电压的正负极,下图为各引脚的说明解释:

        实际上,VREF+和VREF-分别接上VDDA和VSSA,然后VDDA和VSSA分别接到VDD和VSS,结果就是VREF+和VREF-分别接到VDD和VSS。

1.1.4中断触发

        可以看到,超过看门狗的上阈值或是低于下阈值会产生AWD标志位,规则组、注入组AD转换结束分别会产生EOC和JEOC标志位,在对应寄存器的位上设置就可以实现转换结束后产生中断:

        上述寄存器是用来存储对应标志位的,需要注意的是,需要软件清除,也即手动清除。当需要使用对应的结束标志位来启动中断的时候,还需要手动清除一下对应的标志位。

        对应的,还需要再下面的寄存器种设置对应的位:

        对应在ADC_ITConfig函数进行产生中断源的选择:

        具体是ADC_IT这个参数,可以选择ADC_IT_EOC、ADC_IT_AWD、ADC_IT_JEOC,分别对应规则组转换完成、模拟看门狗触发、注入组转换完成

        对应的中断通道IRQ的选择,需要根据自身芯片的型号来选择对应的中断通道枚举类型:

        这里我采用的是STM32F103C8T6,在该芯片中,只有ADC1和ADC2两个模块,即对应MD中容量类型如下图:

        由以上的解释,NVIC_IRQChannel=ADC1_2_IRQn;这样即完成对中断通道的配置。

        最终代码如下:

	ADC_ITConfig(ADC1,ADC_IT_EOC,ENABLE);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	
	
	NVIC_InitTypeDef NVIC1;
	NVIC1.NVIC_IRQChannel=ADC1_2_IRQn;
	NVIC1.NVIC_IRQChannelCmd=ENABLE;
	NVIC1.NVIC_IRQChannelPreemptionPriority=2;
	NVIC1.NVIC_IRQChannelSubPriority=1;
	NVIC_Init(&NVIC1);

        这里我定义的结构体变量为NVIC1,对于抢占优先级和响应优先级的设置,要求不高的情况下,随意配置。

        最后配置一下中断函数需要执行的内容,即完成对中断的配置

1.1.5外部触发输入

        也就是ADC结构的下半部分,同时可以看到在右下角,说明了ADC3外设下的触发结构,于ADC1和ADC2左边的结构略有不同,在使用ADC3的时候需要注意一下。

        可以看到输入进注入通道和规则通道之前,有一个与门相当于开关),与门的一位为触发信号输入,另一位则为控制位,通过对控制位的控制来使能或失能触发输入

        对应寄存器:

        这两位分别控制两个与门的控制位,类似于“开关”。

        同时在这个寄存器种,还含有对外部触发输入的数据寄存器控制的位:

        可以看到,基本上都是由TIM定时器产生的触发事件,所以我们可以使用TIM定时器在隔多少秒后使用ADC采集并转换一下数据。

        上述的寄存器位描述用图表表示就是,注入组:

        对应的选择触发函数:

        对应的注入组与门控制位函数:

        规则组:

        规则组与门的控制位函数:

        奇怪的是,并没有规则组的外部触发选择函数,如ADC_ExternalTrigConvConfig,并没有在固件库中找到,而却含有规则组与与门控制位的函数,这里个人推测是ST公司漏装了^ ^,这里就不在深究了,毕竟他们只需要写写函数,而我们考虑的东西就更多了。

        这里说一下JSWSTART、SWSTART:

        对应函数:

        对应函数:

        这两位可以通过软件设置,即通过上述的两个函数,设置后就会开启对应规则/注入通道的转换,同时在转换启动后,该位会由软件自动清除。

        同样的,在外部触发源数据选择器中,置111,对应启动规则/注入通道的转换,同时还需打开与门的控制位,这样才能够真正启动ADC转换。

        再来看看数据手册对触发注入的描述:

        清除ADC_CR1寄存器的JAUTO位,并且设置SCAN位,即可使用触发注入功能。 1. 利用外部触发或通过设置ADC_CR2寄存器的ADON位,启动一组规则通道的转换。 2. 如果在规则通道转换期间产生一外部注入触发,当前转换被复位,注入通道序列被以单次 扫描方式进行转换。 3. 然后,恢复上次被中断的规则组通道转换。如果在注入转换期间产生一规则事件,注入转 换不会被中断,但是规则序列将在注入序列结束后被执行。 注:当使用触发的注入转换时,必须保证触发事件的间隔长于注入序列。例如:序列长度为28个 ADC时钟周期(即2个具有1.5个时钟间隔采样时间的转换),触发之间最小的间隔必须是29个 ADC时钟周期                  先看到JAUTO位:         先看到这个位的描述: 用于开启或关闭规则通道组转换结束后自动的注入通道组转换,也就是在规则通道组转换的时候,此时软件或外部触发注入通道组的转换,通过JAUTO设置可以选择规则通道组转换结束后自动的注入通道组转换。         而清除时满足SCAN位被设置,也即选择扫描模式(在后续会具体介绍),会直接复位规则通道组转换,注入通道组转换被单次(后续介绍)扫描方式进行转换,注入转换后,回复上次的规则组通道转换。         如下图:         突然的注入触发相当于中断,只是没有“保护现场”的功能。         如果,正在注入转换的时候,来了一个规则事件(产生规则通道组转换),并不会中断注入转换,而是会在注入序列结束后再进行规则事件的转换。         类比优先级,抢占和响应优先级。

        同时看到时序图来理解下面的

        当使用触发的注入转换时,必须保证触发事件的间隔长于注入序列。例如:序列长度为28个ADC时钟周期(2个具有1.5个时钟间隔采样时间的转换),触发之间最小的间隔必须是29ADC时钟周期。

        这意味着,从一次触发事件开始到下一次触发事件开始,这段时间必须足够长,以确保当前的注入转换序列能够完全执行完成,以避免不同注入转换序列之间的冲突或中断。

        同时还有一个自动注入:          如果设置了JAUTO位,在规则组通道之后,注入组通道被自动转换。这可以用来转换在 ADC_SQRx和ADC_JSQR寄存器中设置的多至20个转换序列。         在此模式里,必须禁止注入通道的外部触发。         如果除JAUTO位外还设置了CONT位,规则通道至注入通道的转换序列被连续执行。         对于ADC时钟预分频系数为4至8时,当从规则转换切换到注入序列或从注入转换切换到规则序列时,会自动插入1个ADC时钟间隔;当ADC时钟预分频系数为2时,则有2个ADC时钟间隔的 延迟。         注意: 不可能同时使用自动注入和间断模式。

       看到COUNT位: 

        自动注入需要禁止外部触发的注入模式,因为外部触发的注入转换会中断正在执行的规则转换,对应的置JAUTO为1,如果置COUNT位为1,也即选择连续转换模式,当规则通道后面有注入通道在“排队”的时候,当执行完规则转换,自动执行后面的转换。

        需要注意自动注入不能和间断模式共同作用。

2.ADC的模式

        前面提到过,ADC的模式有很多种,连续/非连续、扫描/非扫描、间断/非间断,以及在后面还有一个双ADC模式。

2.1连续/非连续模式

在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启 动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。 每个转换后: ● 如果一个规则通道被转换: ─ 转换数据被储存在16位的ADC_DR寄存器中 ─ EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。 ● 如果一个注入通道被转换: ─ 转换数据被储存在16位的ADC_DRJ1寄存器中 ─ JEOC(注入转换结束)标志被设置 ─ 如果设置了JEOCIE位,则产生中断。         上述为数据手册中对连续模式的描述,连续模式也就是连续地进行ADC转换,后面有多少个“排队”的ADC转换,就会执行多少次,同时在每个规则/注入组转换后分别会设置标志位EOC/JEOC,用下图来大致表示:         每一组通道转换完成后都会置EOC。         非连续模式(单次转换模式)也就是,只执行一组通道转换后置EOC就结束。         对应的在COUNT位置1或是置0来使用连续,还是非连续模式。

2.2扫描/非扫描模式

         此模式用来扫描一组模拟通道。         扫描模式可通过设置ADC_CR1寄存器的SCAN位来选择。一旦这个位被设置,ADC扫描所有被 ADC_SQRX寄存器(对规则通道)或ADC_JSQR(对注入通道)选中的所有通道。在每个组的每个 通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。如果设置了CONT 位,转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。         如果设置了DMA位,在每次EOC后,DMA控制器把规则组通道的转换数据传输到SRAM中而 注入通道转换的数据总是存储在ADC_JDRx寄存器中。         同样上述为数据手册对扫描模式的概述,所谓扫描模式,ADC会依次扫描所有规则通道/注入通道,然后将产生的数据存储到对应的寄存器中,如果是规则组中,16个通道只会留下第16位的数据,其他前15位数据会被覆盖。

        上图会依次序列顺序进行转换,直到转换到最后一位序列,然后置EOC标志位。

        非连续就是,只转换第一位序列的通道,而忽略下面序列的通道,第一位序列转换完成直接置EOC标志位。

2.3间断/非间断模式

     ADC中的间断模式是一种特殊的转换模式,它允许将一组通道分成多个短序列进行转换,而不是像扫描模式那样连续转换整组通道。   

        此模式在规则组和注入组之间有所不同:

        规则组,此模式通过设置ADC_CR1寄存器上的DISCEN位激活。它可以用来执行一个短序列的n次转换(n<=8),此转换是ADC_SQRx寄存器所选择的转换序列的一部分。数值n由ADC_CR1寄存器的DISCNUM[2:0]位给出。

        位DISCEN在规则通道组上决定失能还是使能。

        DISCNUM[2:0]用来决定短序列的转换次数n。

        这里看起来难以理解,举个例子,例如接下来我需要转换规则通道组:0、1、2、3、5、6、7、8、9、11、15、16这12个通道。

        如果n=4(也即每次转换的次数4),第一次转换为0、1、2、3,第二次转换为5、6、7、8,第三次转换为9、11、15、16。

        再来看n=3的情况,第一次转换为0、1、2,第二次转换为3、5、6,第三次转换为7、8、9,第四次转换为11、15、16。

        这样看来,是不是更好理解规则组下的间断模式。

        当n=4时,如果执行完三次,第四次就会重新执行第一次0、1、2、3规则通道的转化。

        有三个SQR寄存器,处理SQR1中包含L[3:0]确定规则组通道数目,其他都是每五位确定一个转换通道,SQ16~1对应序列16~1。

        接下里介绍注入组,也是类似的:                

        此模式通过设置ADC_CR1 寄存器的JDISCEN位激活。在一个外部触发事件后,该模式按通道顺序逐个转换ADC_JSQR寄存器中选择的序列。         一个外部触发信号可以启动ADC_JSQR 寄存器选择的下一个通道序列的转换,直到序列中所有的转换完成为止。总的序列长度由ADC_JSQR寄存器的JL[1:0]位定义。         对应的使能位,不在赘述        由于注入组中只有4个,也即注入通道只有个,所以并没有注入组的间断模式通道计数,该模式按通道顺序逐个转换ADC_JSQR寄存器中选择的序列。         下面位数据手册中的例子:         n=1,被转换的通道 = 1、2、3         第一次触发:通道1被转换         第二次触发:通道2被转换         第三次触发:通道3被转换,并且产生EOC和JEOC事件         第四次触发:通道1被转换         同样,不难理解,每次触发转换一次通道,只不过相比规则组通道数较少。

小结

        这样在当需要同时监控多个模拟信号,但每个信号的采样频率不同时,可以使用间断模式来优化资源使用,同时相比扫描模式减少不必要的转换,间断模式有助于降低ADC的功耗。

        最后在某些应用场景中,可能需要在不同的时间点获取不同通道的数据,间断模式提供了这种灵活性。

2.4混合模式

        上面连续/非连续(单次)可以和扫描/非扫描混合出四种:连续扫描、连续非扫描、单次扫描、单次非扫描。

        而扫描/非扫描不能和间断/非间断混合,也即剩下连续/非连续混合间断/非间断:连续间断、连续非间断、非连续间断、非连续非间断。

        这样就有八种模式共ADC使用,然而大部分情况下不会用到间断模式,在特殊情况下有可能会用到。        

        然而上述只是单ADC的模式,对应的有双ADC模式,同样对应特殊情况,例如需要采样频率较高的场合下,需要的可以自行查阅手册,这里不进行展开。

3.ADC的校准及温度传感器

3.1ADC的校准

         ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换 中每个电容器上产生的误差。         通过设置ADC_CR2寄存器的CAL位启动校准。一旦校准结束,CAL位被硬件复位,可以开始正常转换。建议在上电时执行一次ADC校准。校准阶段结束后,校准码储存在ADC_DR中。 注意: 1建议在每次上电后执行一次校准。             2启动校准前,ADC必须处于关电状态(ADON=’0’)超过至少两个ADC时钟周期。

        每次使用ADC转换之前,都应该进行ADC的校准,校准可以减小一些误差,对应的CAL为校准位:

        在校准期间置CAL,校准完成置0,同时校准结束会将校准码存储在ADC_DR寄存器中:

        对于库函数,只需要完成如下的代码,即可实现校准:

	ADC_ResetCalibration(ADC1);								//固定流程,内部有电路会自动执行校准
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);

3.2温度传感器

        前面提到过,再ADC1中,温度传感器和内部电源模块分别再ADC通道的17和18中:

        温度传感器可以用来测量器件周围的温度(TA)。         温度传感器在内部和ADC1_IN16输入通道相连接,此通道把传感器输出的电压转换成数字值。 温度传感器模拟输入推荐采样时间是17.1μs。         当没有被使用时,传感器可以置于关电模式。 注意: 必须设置TSVREFE位激活内部通道:ADC1_IN16(温度传感器)ADC1_IN17(VREFINT)的转换         通过设置上面的位来使能温度传感器和内部电源模块,对应函数: 读温度 为使用传感器:
  • 选择ADC1_IN16输入通道
  • 选择采样时间为17.1 μs
  • 设置ADC控制寄存器2(ADC_CR2)的TSVREFE位,以唤醒关电模式下的温度传感器
  • 通过设置ADON位启动ADC转换(或用外部触发)
  • 读ADC数据寄存器上的VSENSE 数据结果
        利用下列公式得出温度         温度(°C) = {(V25 - VSENSE) / Avg_Slope} + 25 这里: V25 = VSENSE在25°C时的数值         Avg_Slope = 温度与VSENSE曲线的平均斜率(单位为mV/ °C 或 μV/ °C)         参考数据手册的电气特性章节中V25 和Avg_Slope的实际值。 注意: 传感器从关电模式唤醒后到可以输出正确水平的VSENSE前,有一个建立时间。ADC在上电后也 有一个建立时间,因此为了缩短延时,应该同时设置ADONTSVREFE位。                  上述为手册对温度传感器的温度公式进行计算,有需要的自行查阅。

4.模拟看门狗

        如果被ADC 转换的模拟电压低于低阀值或高于高阀值, AWD 模拟看门狗状态位被设置。阀值位于ADC_HTR 和 ADC_LTR 寄存器的最低 12 个有效位中。通过设置 ADC_CR1 寄存器的 AWDIE 位 以允许产生相应中断。         阀值独立于由ADC_CR2 寄存器上的 ALIGN位选择的数据对齐模式。比较是在对齐之前完成的。通过配置 ADC CR1 寄存器,模拟看门狗可以作用于 1 个或多个通道如下图:          对应函数:          对应的AWDCH[4:0]选择位:         对应单一通道选择函数:         需要注意的是,ADC1、ADC2、ADC3模拟输入通道的内部连接有所不同。         同时模拟看门的警戒区如下图:         对应寄存器:         上下阈值配置对应函数:                  以上就是对模拟看门够的描述,当 被ADC 转换的模拟电压低于低阀值或高于高阀值, AWD 模拟看门狗状态位被设置。

5.数据对齐以及采样时间的计算

5.1数据对齐

        数据对齐是因为ADC为12位,而寄存器位16位,所以就存在一个数据对齐的问题。

        分为,左对齐和右对齐,对于注入组:

        注入组通道转换的数据值已经减去了在ADC_JOFRx 寄存器中定义的偏移量,因此结果可以是一个负值。SEXT 位是扩展的符号值,SEXT可以位负号。         对应的下图:

        一般使用的是右对齐,这样读取到的结果就直接是转换的结果。

        左对齐会是转换后的数据增大,左移一位×2,对应规则组就是扩大16倍。

        如果你不需要这右对齐这么高的精度(分辨率)也就是0~4095(2的12次方-1),就是做一个简单的判断,将数据左移4位,然后舍弃低八位的数据,这样12位的ADC就被当作8位ADC来使用。

5.2采样时间的计算

AD转换的步骤:采样,保持,量化,编码

STM32 ADC的总转换时间为:     

        TCONV = 采样时间 + 12.5个ADC周期

例如:当ADCCLK=14MHz,采样时间为1.5个ADC周期     

        TCONV = 1.5 + 12.5 = 14个ADC周期 = 1μs

        其中 量化、编码这两个过程属于逐次比较的过程,一般位数较多,花的时间也就越多。         而 采样、保持是配合 逐次逼近比较的,因为 采集的数据是动态的,同时量化编码又需要一段时间,所以需要 采样保持来使电压不变。         其内部由一个采样开关和一个电容构成,当采样电压时,闭合开关,储存好了采样电压,就断开开关,由于电容的作用,能够保持一段时间该电压不变。         采样时间越大,越能避免一些毛刺信号的干扰,但花费的时间也越长

6.逐次逼近比较法

        接下里通过对一个8位ADC来介绍逐次逼近比较法:

                 首先从外部接收到一个未知编码的电压进入到比较器,同时DAC数模转换中为一个已知编码 值的电压进入到比较器中。通过比较,在逐次逼近寄存器SAR中不断改变DAC内的编码电压,直到 DAC输出的电压和外部输入的电压近视相等,就输出到锁存寄存器中储存。         具体操作是,由于该ADC为8位,对应的值就为0~255,通过二分法:         如上图,就会不断的进行二分比较目标值188,第一次DAC为255和0中间的127,第二次是127和255之间的191,以此类推,最终大概第6次的时候,就能近似188目标值,然后输出DAC的值到锁存寄存器中储存。         实际上,二分法对应的就是二进制从高位第8位到低位的判断1还是0的过程,例如: 188=1011 1100,对应二分法中DAC的值比188小的时候就改位就置1。         对应的,12位ADC也就是0~4095,同样的对应12位的输出DAC的值,12位的存储寄存器,都是类似的方法。         接下里就介绍ADC的不同配置。

7.ADC的配置

        首先是开启时钟,以及初始化ADC采样输入的接口。

	/*开启时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);	//开启ADC1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	//开启GPIOA的时钟

	/*设置ADC时钟*/
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);						//选择时钟6分频,ADCCLK = 72MHz / 6 = 12MHz
	
	/*GPIO初始化*/
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);					//将PA0引脚初始化为模拟输入

        模式采用模拟输入模式(GPIO_Mode_AIN),GPIO引脚直接接入ADC中:

        最后还需关注一个模式输入的引脚重映射,来选择GPIO端口:

        接下来配置ADC规则组通道:

	/*规则组通道配置*/
	ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);		//规则组序列1的位置,配置为通道0
	
	

        上述采用的ADC规则组,使用的函数是ADC_RegularChannelConfig ,对应的如果想要使用ADC的注入组,使用函数ADC_InjectedChannelConfig,接下来对ADC_RegularChannelConfig 规则组进行展开。

        跳转到定义:

        参数较多,首先是ADCx,也就是选择ADC1~3外设。

        然后是ADC_Channel,也就选择规则组的通道,每个外设ADC都会有所差异,PAx为默认重映射的引脚如下图:

        下一个参数是选择第几行,行数值小的先执行,如下图先:

        先选择通道二ADC_Channel_2,然后放到第一行(rank)1

        最后一个ADC_SampleTime转换时间,根据自身的需求来选择,如果你需要更快的转换,则选择更小的参数,也即ADC_SampleTime_1Cycles5;

        需要更稳定的转换,则选择更大的参数ADC_SampleTime_71Cycles5,相应的转换时间也会更长。

        如果都没要求,可以任意选择。

        这样就配置好规则组通道的配置,如果还想再设置一个通道,就可以对上述代码进行复制,修改一下通道和RANK就行。

        然后配置ADC通道的模式、数量等参数:

/*ADC初始化*/
	ADC_InitTypeDef ADC_InitStructure;						//定义结构体变量
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;		//模式,选择独立模式,即单独使用ADC1
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//数据对齐,选择右对齐
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//外部触发,使用软件触发,不需要外部触发
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;		//非连续转换(单次转换),每转换一次规则组序列后停止
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;			//非扫描模式,只转换规则组的序列1这一个位置
	ADC_InitStructure.ADC_NbrOfChannel = 1;					//通道数,为1,仅在扫描模式下,才需要指定大于1的数,在非扫描模式下,只能是1
	ADC_Init(ADC1, &ADC_InitStructure);						//将结构体变量交给ADC_Init,配置ADC1

        首先是ADC_Mode,跳转定义:

        其中,除了第一个的单ADC模式,其他的都为双ADC模式下的选择。

        接着是数据对齐方式,一般是右对齐。

        然后是外部触发ADC来源选择,选择需要要外部触发,也即软件触发。

        接着是扫描和连续的选择,这个也是根据自身的需求来的,同时结合扫描和连续的作用,这里转换一个通道一次,选择非扫描、非连续(单次)转换的模式。

        然后是通道数量,根据配置的通道数量来选择,这里选1,1个通道。

	ADC_Cmd(ADC1, ENABLE);									//使能ADC1,ADC开始运行
	
	/*ADC校准*/
	ADC_ResetCalibration(ADC1);								//固定流程,内部有电路会自动执行校准
	while (ADC_GetResetCalibrationStatus(ADC1) == SET);
	ADC_StartCalibration(ADC1);
	while (ADC_GetCalibrationStatus(ADC1) == SET);

        接着是ADC使能以及ADC校准,这里就不在进行展开了。

        最后设置一个返回ADC转换值的函数:

uint16_t AD_GetValue(uint8_t ADC_Channel)
{
	ADC_RegularChannelConfig(ADC1, ADC_Channel, 1, ADC_SampleTime_55Cycles5);	//在每次转换前,根据函数形参灵活更改规则组的通道1
	ADC_SoftwareStartConvCmd(ADC1, ENABLE);					//软件触发AD转换一次
	while (ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC) == RESET);	//等待EOC标志位,即等待AD转换结束
	return ADC_GetConversionValue(ADC1);					//读数据寄存器,得到AD转换的结果
}

        通过读取AD_GetValue函数的返回值,就可以得到AD转换后的数值。

8.总结

        以上就是对ADC模数转换器的全部介绍了,其中没有介绍到的双ADC模式,自行查阅资料进行展开,不过最重要的还是得回归数据手册来进行理解,最后欢迎大家来进行讨论以及指正文章错误的地方。

文章参考:[7-2] AD单通道&AD多通道_哔哩哔哩_bilibili

标签:总结,转换,规则,关于,ADC,寄存器,注入,通道
From: https://blog.csdn.net/qq_68915581/article/details/141180786

相关文章

  • failed to solve: process “/bin/sh -c yum -y install vim“ did not complete succ
    网上有好多种方法(都试过了只有方法四可以用):方法一:systemctl restart  docker(生产上不建议)方法二:看看你的网络是否有问题,检查一下网络连通性方法三:有可能是容器版本的问题,推荐使用centos7,看网上说最新的镜像会有这类的的问题方法四:就像这个博主大佬说的修改主机源修改......
  • Servlet总结
    Serevlet一、概念Servlet(ServerApplet)是JavaServlet的简称,称为小服务程序或服务连接器,泛指用 Java编写的服务器端程序。在编程过程中也指一切 实现了Servlet接口的类(约定以Servlet结尾命名)。二、使用在src.com.qf.servlet包中创建Servlet01类extendHttpServlet,重写......
  • linux驱动总结
    一.前言做linux开发也有一段时间了,对整个系统已经熟悉了很多,linux是一个非常大的系统,现在对常见的驱动做一个总结,以此来加深记忆和理解。二.常见驱动及其子系统分类1.Linux设备分类linux系统抽象出的设备可以分为三类:char_dev,block_dev,net_dev。字符设备是产品开发用的最多......
  • 关于sizeof()与strlen()的详解与题例
    ......
  • 【课程总结】day24(下):大模型部署调用(vLLM+LangChain)
    前言在上一章【课程总结】day24(上):大模型三阶段训练方法(LLaMaFactory)内容中主要了解一个大模型的训练过程,无论是第三方的大模型还是自研的大模型,都需要部署到服务端,提供对应API接口供上层应用使用。所以,本章将主要了解vLLm+langchain的基本使用方法。大模型应用框架......
  • Spring经典面试题总结
    spring是什么?轻量级的开源的J2EE框架。它是一个容器框架,用来装javabean(java对象),中间层框架(万能胶)可以起一个连接作用,比如说把Struts和hibernate粘合在一起运用,可以让我们的企业开发更快、更简洁Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架–从大小与开销......
  • JS中构造函数继承问题注意事项总结
    在JavaScript中,继承是通过原型链来实现的。当你想要创建一个子类(比如Student)继承一个父类(比如Person)时,通常会使用Object.create来创建Student的原型对象。这背后有一些重要的原因:1.共享与独立性当你执行Student.prototype=Person.prototype时,Student的原型......
  • 关于JS里的字符表情乱码
    背景1、业务背景公司在处理业务时,需要使用socket传输字符串内容,在A处输入,在B处显示。但反馈说输入表情符号经过传输后,ios会变成问号,PC会乱码。如下情况:2、表情乱码表情符号乱码的原因通常与UTF-8编码的处理不当有关。表情符号属于Unicode中的高码点字符,需要使用4个字......
  • [笔记]关于在linux中通过yum安装mysql错误--因为Centos 7官方镜像不可用的解决方法
     因为Centos7在2024年6月30号停止维护   在执行命令时找不到镜像源, 在下载时出现的错误为,还有一种错误由于没有截图,但是问题一样先通过yumremovemariadb*-y去删除自带的sql包通过命令编辑这个文本文件 vim/etc/yum.repos.d/CentOS-Base.repo这里举......
  • MySQL - [18] mysql中关于cascade的用法
    dropdatabase语句用于删除数据库。但如果想要删除一个数据库并且还要删除所有依赖于该数据库的存储过程、函数等,可以使用cascade关键字。dropdatabasetestcascade的效果相当于以下步骤: 一、查询依赖于该数据库的对象SELECT*FROMinformation_schema.VIEWSWHERETAB......