完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
1.1 ADC工作原理
12位ADC是一种逐次逼近型模拟数字转换器。它有多达18个通道,可测量16个外部和2个内部信号源。各通道的A/D转换可以单次、连续、扫描或间断模式执行。ADC的结果可以左对齐或右对齐方式存储在16位数据寄存器中。模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。ADC 的输入时钟不得超过14MHz,它是由PCLK2经分频产生。 图1 ADC框图 1.1.1 ADC主要特征 ● 12位分辨率 ● 转换结束、注入转换结束和发生模拟看门狗事件时产生中断 ● 单次和连续转换模式 ● 从通道0到通道n的自动扫描模式 ● 间断模式执行 ● 自校准 ● 带内嵌数据一致性的数据对齐 ● 采样间隔可以按通道分别编程 ● 规则转换和注入转换均有外部触发选项 ● 双重模式(带2个或以上ADC 的器件) ● ADC转换时间: ─ STM32F103xx增强型产品:时钟为56MHz时为1μs (时钟为72MHz为1.17μs) ─ STM32F101xx基本型产品:时钟为28MHz时为1μs (时钟为36MHz为1.55μs) ─ STM32F102xxUSB型产品:时钟为48MHz 时为1.2μs ─ STM32F105xx和STM32F107xx产品:时钟为56MHz时为1μs (时钟为72MHz为1.17μs) ● ADC供电要求:2.4V到3.6V ● ADC输入范围:VREF- ≤ VIN ≤ VREF+ ● 规则通道转换期间有DMA请求产生。 表1 ADC引脚 【注】VDDA和VSSA应该分别连接到VDD和VSS。 1.1.2 ADC通道选择 表2 ADC对应通道 STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。 通过一个形象的例子可以说明: 假如你在家里的院子内放了 5 个温度探头,室内放了 3 个温度探头; 你需要时刻监视室外温度即可,但偶尔你想看看室内的温度;因此你可以使用规则通道组循环扫描室外的 5 个探头并显示 AD 转换结果,当你想看室内温度时,通过一个按钮启动注入转换组(3 个室内探头)并暂时显示室内温度,当你放开这个按钮后,系统又会回到规则通道组继续检测室外温度。从系统设计上,测量并显示室内温度的过程中断了测量并显示室外温度的过程,但程序设计上可以在初始化阶段分别设置好不同的转换组,系统运行中不必再变更循环转换的配置,从而达到两个任务互不干扰和快速切换的结果。可以设想一下,如果没有规则组和注入组的划分,当你按下按钮后,需要从新配置 AD 循环扫描的通道,然后在释放按钮后需再次配置 AD 循环扫描的通道。 上面的例子因为速度较慢,不能完全体现这样区分(规则通道组和注入通道组)的好处,但在工业应用领域中有很多检测和监视探头需要较快地处理,这样对 AD 转换的分组将简化事件处理的程序并提高事件处理的速度。 STM32 其 ADC 的规则通道组最多包含 16 个转换,而注入通道组最多包含 4 个通道。关于这两个通道组的详细介绍,请参考《STM32 参考手册的》,我们这里就不在一一列举了。 ● 规则组由多达16个转换组成。规则通道和它们的转换顺序在ADC_SQRx寄存器中选择。规则组中转换的总数应写入ADC_SQR1寄存器的L[3:0]位中。 ● 注入组由多达4个转换组成。注入通道和它们的转换顺序在ADC_JSQR寄存器中选择。注入组里的转换总数目应写入ADC_JSQR寄存器的L[1:0]位中。 如果ADC_SQRx或ADC_JSQR寄存器在转换期间被更改,当前的转换被清除,一个新的启动脉冲将发送到ADC 以转换新选择的组。 温度传感器和通道ADC1_IN16相连接,内部参照电压VREFINT和ADC1_IN17相连接。可以按注入或规则通道对这两个内部通道进行转换。 【注意】温度传感器和VREFINT只能出现在主ADC1 中。 1.1.3 ADC转换模式 单次转换模式 单次转换模式下,ADC只执行一次转换。该模式既可通过设置ADC_CR2 寄存器的ADON位(只适用于规则通道)启动也可通过外部触发启动(适用于规则通道或注入通道),这时CONT位为0 。一旦选择通道的转换完成: ● 如果一个规则通道被转换: ─ 转换数据被储存在16位ADC_DR寄存器中 ─ EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。 ● 如果一个注入通道被转换: ─ 转换数据被储存在16位的ADC_DRJ1寄存器中 ─ JEOC(注入转换结束)标志被设置 ─ 如果设置了JEOCIE位,则产生中断。然后ADC停止。 连续转换模式 在连续转换模式中,当前面ADC转换一结束马上就启动另一次转换。此模式可通过外部触发启动或通过设置ADC_CR2寄存器上的ADON位启动,此时CONT位是1。 每个转换后: ● 如果一个规则通道被转换: ─ 转换数据被储存在16位的ADC_DR寄存器中 ─ EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。 ● 如果一个注入通道被转换: ─ 转换数据被储存在16位的ADC_DRJ1寄存器中 ─ JEOC(注入转换结束)标志被设置 ─ 如果设置了JEOCIE位,则产生中断。 扫描模式 此模式用来扫描一组模拟通道。 扫描模式可通过设置ADC_CR1寄存器的SCAN位来选择。一旦这个位被设置,ADC扫描所有被ADC_SQRX 寄存器(对规则通道)或ADC_JSQR(对注入通道)选中的所有通道。在每个组的每个通道上执行单次转换。在每个转换结束时,同一组的下一个通道被自动转换。如果设置了CONT位,转换不会在选择组的最后一个通道上停止,而是再次从选择组的第一个通道继续转换。 如果设置了DMA位,在每次EOC后,DMA控制器把规则组通道的转换数据传输到SRAM 中。而注入通道转换的数据总是存储在ADC_JDRx寄存器中。 间断模式 1)规则组 此模式通过设置ADC_CR1 寄存器上的DISCEN位激活。它可以用来执行一个短序列的n次转换(n《=8),此转换是ADC_SQRx寄存器所选择的转换序列的一部分。数值n由ADC_CR1寄存器的DISCNUM[2:0]位给出。 一个外部触发信号可以启动ADC_SQRx 寄存器中描述的下一轮n次转换,直到此序列所有的转换完成为止。总的序列长度由ADC_SQR1寄存器的L[3:0]定义。 举例: n=3,被转换的通道 = 0 、1、2、3、6、7、9、10 第一次触发:转换的序列为 0 、1、2 第二次触发:转换的序列为 3 、6、7 第三次触发:转换的序列为 9 、10,并产生EOC事件 第四次触发:转换的序列 0 、1、2 注意: 当以间断模式转换一个规则组时,转换序列结束后不自动从头开始。 当所有子组被转换完成,下一次触发启动第一个子组的转换。在上面的例子中,第四次触发重新转换第一子组的通道 0 、1和2。 2)注入组 此模式通过设置ADC_CR1 寄存器的JDISCEN位激活。在一个外部触发事件后,该模式按通道顺序逐个转换ADC_JSQR寄存器中选择的序列。 一个外部触发信号可以启动ADC_JSQR寄存器选择的下一个通道序列的转换,直到序列中所有的转换完成为止。总的序列长度由ADC_JSQR寄存器的JL[1:0]位定义。 例子: n=1,被转换的通道 = 1 、2、3 第一次触发:通道1被转换 第二次触发:通道2被转换 第三次触发:通道3被转换,并且产生EOC和JEOC事件 第四次触发:通道1被转换 【注意】 1 当完成所有注入通道转换,下个触发启动第1个注入通道的转换。在上述例子中,第四个触发重新转换第1个注入通道1。 2 不能同时使用自动注入和间断模式。 3 必须避免同时为规则和注入组设置间断模式。间断模式只能作用于一组转换。 1.2 ADC寄存器描述 我们介绍一下我们执行规则通道的单次转换,需要用到的 ADC 寄存器。第一个要介绍的是 ADC 控制寄存器(ADC_CR1 和 ADC_CR2)。 ADC_CR1 的各位描述如图2所示。 图2 ADC_CR1 寄存器各位描述 这里我们不再详细介绍每个位,而是抽出几个我们本章要用到的位进行针对性的介绍,详细的说明及介绍,请参考《STM32 参考手册》。 ADC_CR1 的 SCAN 位,该位用于设置扫描模式,由软件设置和清除,如果设置为 1,则使用扫描模式,如果为 0,则关闭扫描模式。在扫描模式下,由 ADC_SQRx 或 ADC_JSQRx 寄存器选中的通道被转换。如果设置了 EOCIE 或 JEOCIE,只在最后一个通道转换完毕后才会产生 EOC 或 JEOC 中断。 ADC_CR1[19: 16]用于设置 ADC 的操作模式,详细的对应关系如图3所示。 图3 ADC 操作模式 本章我们要使用的是独立模式,所以设置这几位为 0 就可以了。接着我们介绍 ADC_CR2,该寄存器的各位描述如图4所示。 图4 ADC_CR2 寄存器操作模式 该寄存器我们也只针对性的介绍一些位: ADON 位用于开关 AD 转换器。而 CONT 位用于设置是否进行连续转换,我们使用单次转换,所以 CONT 位必须为 0。 CAL 和 RSTCAL 用于AD 校准。 ADC_CR2寄存器中的ALIGN位选择转换后数据储存的对齐方式。数据可以左对齐或右对齐,如图5和图6所示。 注入组通道转换的数据值已经减去了在ADC_JOFRx寄存器中定义的偏移量,因此结果可以是一个负值。SEXT位是扩展的符号值。 对于规则组通道,不需减去偏移值,因此只有12个位有效。 图5数据右对齐 图6数据左对齐 EXTSEL[2: 0]用于选择启动规则转换组转换的外部事件,详细的设置关系如图7所示。 图7 ADC 选择启动规则转换事件设置 我们这里使用的是软件触发(SWSTART),所以设置这 3 个位为 111。 ADC_CR2 的SWSTART 位用于开始规则通道的转换,我们每次转换(单次转换模式下)都需要向该位写 1。AWDEN 为用于使能温度传感器和 Vrefint。 STM32 内部的温度传感器我们将在后文介绍。 第二个要介绍的是 ADC 采样事件寄存器(ADC_SMPR1 和 ADC_SMPR2),这两个寄存器用于设置通道 0~17 的采样时间,每个通道占用 3 个位。 ADC_SMPR1 的各位描述如图8。 图8 ADC_SMPR1 寄存器各位描述 ADC_SMPR2 的各位描述如下图9所示。 图9 ADC_SMPR2 寄存器各位描述 对于每个要转换的通道,采样时间建议尽量长一点,以获得较高的准确度,但是这样会降低 ADC 的转换速率。 ADC 的转换时间可以由以下公式计算: Tcovn=采样时间+12.5 个周期 其中: Tcovn 为总转换时间,采样时间是根据每个通道的 SMP 位的设置来决定的。例如,当 ADCCLK=14Mhz 的时候,并设置 1.5 个周期的采样时间,则得到: Tcovn=1.5+12.5=14 个周期=1us。 常见的周期有: 1.5周期、7.5周期、13.5周期、28.5周期、41.5周期、55.5周期、71.5周期、239.5周期。 第三个要介绍的是 ADC 规则序列寄存器(ADC_SQR1~3) ,该寄存器总共有 3 个,这几个寄存器的功能都差不多,这里我们仅介绍一下 ADC_SQR1,该寄存器的各位描述如图10所示。 图10 ADC_ SQR1 寄存器各位描述 L[3: 0]用于存储规则序列的长度,我们这里只用了 1 个,所以设置这几个位的值为 0。其他的 SQ13~16 则存储了规则序列中第 13~16 个通道的编号(0~17)。另外两个规则序列寄存器同 ADC_SQR1 大同小异,我们这里就不再介绍了,要说明一点的是:我们选择的是单次转换,所以只有一个通道在规则序列里面,这个序列就是 SQ1,通过 ADC_SQR3 的最低 5 位(也就是 SQ1) 设置。 第四个要介绍的是 ADC 规则数据寄存器(ADC_DR)。规则序列中的 AD 转化结果都将被存在这个寄存器里面,而注入通道的转换结果被保存在 ADC_JDRx 里面。 ADC_DR 的各位描述如图11。 图11 ADC_ DRx 寄存器各位描述 图12 ADC_ SR 寄存器各位描述 这里要提醒一点的是,该寄存器的数据可以通过 ADC_CR2 的 ALIGN 位设置左对齐还是右对齐。在读取数据的时候要注意。 最后一个要介绍的 ADC 寄存器为 ADC 状态寄存器(ADC_SR),该寄存器保存了 ADC 转换时的各种状态。该寄存器的各位描述如图12。 这里我们要用到的是 EOC 位,我们通过判断该位来决定是否此次规则通道的 AD 转换已经完成,如果完成我们就从 ADC_DR 中读取转换结果,否则等待转换完成。 1.3 ADC具体代码分析 接下来笔者将通过三种方式实现ADC单通道电压数据采集,先看看笔者使用的开发板的硬件电路,其中PC0外接了一个滑动电阻。 1.3.1 ADC单通道电压采集查询方式实现 ADC详细设置步骤: 1)开启 PC 口时钟和 ADC1 时钟,设置 PC0 为模拟输入。 STM32F103ZET6 的ADC 通道 10在 PC0上,所以,我们先要使能 PORTA 的时钟和 ADC1时钟,然后设置 PC0为模拟输入。 使能 GPIOA 和 ADC 时钟用 RCC_APB2PeriphClockCmd 函数,设置 PC0的输入方式,使用 GPIO_Init 函数即可。 STM32 的 ADC 通道与GPIO 对应表2。 2)复位 ADC1,同时设置 ADC1 分频因子。 开启 ADC1 时钟之后,我们要复位 ADC1, 将 ADC1 的全部寄存器重设为缺省值之后我们就可以通过 RCC_CFGR 设置 ADC1 的分频因子。分频因子要确保 ADC1 的时钟(ADCCLK)不要超过 14Mhz。 这个我们设置分频因子位 8, 时钟为 72/8=9MHz,库函数的实现方法是: void RCC_ADCCLKConfig(uint32_t RCC_PCLK2); 这个函数非常容易理解,就是复位指定的 ADC。 输入参数范围: #define RCC_PCLK2_Div2 ((uint32_t)0x00000000) #define RCC_PCLK2_Div4 ((uint32_t)0x00004000) #define RCC_PCLK2_Div6 ((uint32_t)0x00008000) #define RCC_PCLK2_Div8 ((uint32_t)0x0000C000) STM32的ADC最大的转换速率为1Mhz,也就是转换时间为1us(在ADCCLK=14M,采样周期为1.5个ADC时钟下得到),不要让ADC的时钟超过14M,否则将导致结果准确度下降。 3) 初始化 ADC1 参数, 设置 ADC1 的工作模式以及规则序列的相关信息。 在设置完分频因子之后,我们就可以开始 ADC1 的模式配置了,设置单次转换模式、触发方式选择、数据对齐方式等都在这一步实现。 同时,我们还要设置 ADC1 规则序列的相关信息,我们这里只有一个通道,并且是单次转换的,所以设置规则序列中通道数为 1。 这些在库函数中是通过函数 ADC_Init 实现的,下面我们看看其定义: void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct); 从函数定义可以看出,第一个参数是指定 ADC 号。这里我们来看看第二个参数,跟其他外设初始化一样,同样是通过设置结构体成员变量的值来设定参数。 typedef struct { uint32_t ADC_Mode; FunctionalState ADC_ScanConvMode; FunctionalState ADC_ContinuousConvMode; uint32_t ADC_ExternalTrigConv; uint32_t ADC_DataAlign; uint8_t ADC_NbrOfChannel; }ADC_InitTypeDef; ADC_Mode 故名是以是用来设置 ADC 的模式。前面讲解过, ADC 的模式非常多, 包括独立模式,注入同步模式等等,这里我们选择独立模式,所以参数为 ADC_Mode_Independent。 ADC_ScanConvMode 用来设置是否开启扫描模式, 因为是单次转换,这里我们选择不开启值 DISABLE 即可。 ADC_ContinuousConvMode 用来设置是否开启连续转换模式,因为是单次转换模式,所以我们选择不开启连续转换模式, DISABLE 即可。 ADC_ExternalTrigConv 是用来设置启动规则转换组转换的外部事件,这里我们选择软件触发,选择值为 ADC_ExternalTrigConv_None 即可。 DataAlign 用来设置 ADC 数据对齐方式是左对齐还是右对齐,这里我们选择右对齐方式ADC_DataAlign_Right。 ADC_NbrOfChannel 用来设置规则序列的长度,这里我们是单次转换,所以值为 1 即可。通过上面对每个参数的讲解, 下面来看看我们的初始化范例: ADC_InitTypeDef ADC_InitStructure; ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC 工作模式:独立模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE; //AD 单通道模式 ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //AD 单次转换模式 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //转换由软件而不是外部触发启动 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //ADC 数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的 ADC 通道的数目 1 ADC_Init(ADC1, &ADC_InitStructure); //根据指定的参数初始化外设 ADCx 4)使能 ADC 并校准。 在设置完了以上信息后, 我们就使能 AD 转换器,执行复位校准和 AD 校准,注意这两步是必须的!不校准将导致结果很不准确。 使能指定的 ADC 的方法是: ADC_Cmd(ADC1, ENABLE); //使能指定的 ADC1 执行复位校准的方法是: ADC_ResetCalibration(ADC1); 执行 ADC 校准的方法是: ADC_StartCalibration(ADC1); //开始指定 ADC1 的校准状态 记住,每次进行校准之后要等待校准结束。 这里是通过获取校准状态来判断是否校准是否结束。 下面我们一一列出复位校准和 AD 校准的等待结束方法: while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束 while(ADC_GetCalibrationStatus(ADC1)); //等待校 AD 准结束 ADC有一个内置自校准模式。校准可大幅减小因内部电容器组的变化而造成的准精度误差。在校准期间,在每个电容器上都会计算出一个误差修正码(数字值),这个码用于消除在随后的转换中每个电容器上产生的误差。 通过设置ADC_CR2寄存器的CAL位启动校准。一旦校准结束,CAL位被硬件复位,可以开始正常转换。建议在上电时执行一次ADC校准。校准阶段结束后,校准码储存在ADC_DR 中。 【注意】 1.建议在每次上电后执行一次校准。 2.启动校准前,ADC必须处于关电状态(ADON=’0’)超过至少两个ADC时钟周期。 5)读取 ADC 值。 在上面的校准完成之后, ADC 就算准备好了。接下来我们要做的就是设置规则序列 1 里面的通道,采样顺序, 以及通道的采样周期, 然后启动 ADC 转换。在转换结束后,读取 ADC 转换结果值就是了。 这里设置规则序列通道以及采样周期的函数是: void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime); 我们这里是规则序列中的第 1 个转换,同时采样周期为 239.5,所以设置为: ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); 软件开启 ADC 转换的方法是: ADC_SoftwareStartConvCmd(ADC1, ENABLE);//使能指定的 ADC1 的软件转换启动功能 开启转换之后,就可以获取转换 ADC 转换结果数据, 方法是: ADC_GetConversionValue(ADC1); 同时在 AD 转换中,我们还要根据状态寄存器的标志位来获取 AD 转换的各个状态信息。 库函数获取 AD 转换的状态信息的函数是: FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint8_t ADC_FLAG); 比如我们要判断 ADC1d 的转换是否结束,方法是: while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束 1.3.2 ADC单通道电压采集中断方式实现 中断方式和查询方式不同的地方在于需要开启ADC中断服务,配置中断优先级和中断服务函数。笔者接下来之讲与查询方式不同的地方。 1.需要在ADC配置函数中开启ADC中断 ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); 2. NVIC配置 因为我们是在转换完成后利用中断,在中断函数中读取数据,所以要首先配置中断函数的优先级,值得注意的是,程序还有一个串口中断,最好把优先组设置在同一组中。 static void ADC_NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } 3.中断服务函数 在中断函数中进行读取数据,将数据存放在变量ADC_ConvertedValue中。需要注意的是,此处使用关键字extern声明,代表变量ADC_ConvertedValue已经在其他文件中定义。 void ADC1_2_IRQHandler(void) { if (ADC_GetITStatus(ADC1,ADC_IT_EOC)==SET) { // 读取 ADC 的转换值 ADC_ConvertedValue = ADC_GetConversionValue(ADC1);//获取ADC数据 } ADC_ClearITPendingBit(ADC1,ADC_IT_EOC); } 4.主函数 主函数负责接收转换的值,并将其转换为电压值,然后通过串口打印出来,便于查看ADC转换值。 int main(void) { SysTick_Init(); /*串口初始化*/ USART1_Config(); /*ADC初始化*/ ADC_Configuration(); printf(“rn ----这是一个ADC实验(中断方式)----rn”); while(1) { ADC_ConvertedValueLocal =(float) ADC_ConvertedValue/4096*3.3; // 读取转换的AD值 printf(“The current AD value = 0x%04X rn”, ADC_ConvertedValue); printf(“The current AD value = %f V rnrn”,ADC_ConvertedValueLocal); //实际电压值 Delay_ms(1000); } } 完整代码请参看附件。 1.3.3 ADC单通道电压采集DMA方式实现 DMA方式实现的代码结构和查询方式差不多,主要是ADC配置不同。 static void ADC1_Mode_Config(void) { DMA_InitTypeDef DMA_InitStructure; ADC_InitTypeDef ADC_InitStructure; /* DMA channel1 configuration */ DMA_DeInit(DMA1_Channel1); DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_Address; //ADC地址 DMA_InitStructure.DMA_MemoryBaseAddr = (u32)&ADC_ConvertedValue; //内存地址 DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = 1; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设地址固定 DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Disable; //内存地址固定 DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //半字 DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //循环传输 DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(DMA1_Channel1, &DMA_InitStructure); /* Enable DMA channel1 */ DMA_Cmd(DMA1_Channel1, ENABLE); /* ADC1 configuration */ ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //独立ADC模式 ADC_InitStructure.ADC_ScanConvMode = DISABLE ; //禁止扫描模式,扫描模式用于多通道采集 ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; //开启连续转换模式,即不停地进行ADC转换 ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; //不使用外部触发转换 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; //采集数据右对齐 ADC_InitStructure.ADC_NbrOfChannel = 1; //要转换的通道数目1 ADC_Init(ADC1, &ADC_InitStructure); /*配置ADC时钟,为PCLK2的8分频,即9MHz*/ RCC_ADCCLKConfig(RCC_PCLK2_Div8); /*配置ADC1的通道11为55. 5个采样周期,序列为1 */ ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_55Cycles5); /* Enable ADC1 DMA */ ADC_DMACmd(ADC1, ENABLE); /* Enable ADC1 */ ADC_Cmd(ADC1, ENABLE); /*复位校准寄存器 */ ADC_ResetCalibration(ADC1); /*等待校准寄存器复位完成 */ while(ADC_GetResetCalibrationStatus(ADC1)); /* ADC校准 */ ADC_StartCalibration(ADC1); /* 等待校准完成*/ while(ADC_GetCalibrationStatus(ADC1)); /* 由于没有采用外部触发,所以使用软件触发ADC转换 */ ADC_SoftwareStartConvCmd(ADC1, ENABLE); } 代码的注释已经很详细了,我不再赘述了。完整代码请参看附件。 这里还需要说明一下 ADC 的参考电压,开发板的芯片是STM32F103ZET6, 该芯片有外部参考电压: Vref-和 Vref+,其中 Vref-必须和 VSSA 连接在一起, 而 Vref+的输入范围为: 2.4~VDDA。需要设置 Vref-和 Vref+设置参考电压,默认的我们是通过跳线帽将 Vref-接到 GND, Vref+接到 VDDA,参考电压就是 3.3V。如果大家想自己设置其他参考电压,将你的参考电压接在 Vref-和 Vref+上就 OK 了。本章我们的参考电压设置的是 3.3V。一般的开发板已经设置好了,不在需要单独去设置。 通过以上几个步骤的设置,我们就能正常的使用 STM32 的 ADC1 来执行 AD 转换操作了。 1.4实验现象 将程序编译好后下载到板子中,打开串口助手可以看到如下现象,当然了,普通方式和DMA方式都是一样的现象。 图14实验现象 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1777 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1080 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1678 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
595浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
554浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 04:49 , Processed in 0.978891 second(s), Total 46, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号