历史上的今天
返回首页

历史上的今天

今天是:2025年03月10日(星期一)

正在发生

2021年03月10日 | STM32之ADC+步骤小技巧

2021-03-10 来源:eefocus

曾经的电感电压采集让我心碎的多少次、又让我开心了多少次、但已经成为过去、(软件和硬件都会影响),呵呵、估计有人已经猜到我接下来要介绍什么了、在你们面前、我已无秘密、额、其实标题也直接“表白”了、看到标题,别吓到哈、并不是要用英文写、至于原因是什么、请往下看:


好吧、言归正传:STM32的ADC模块,请允许我用如此通俗的语言:普通话来介绍STM32ADC模块的特色


1、1MHz转换速率、12位转换结果(12位、记住这个12位哈、因为2^12=4096 ,也请记住4096哈)


STM32F103系列:在56MHz时转换时间为:1μs


在72MHz时转换时间为:1.17μs


2、转换范围:0~3.6V (3.6v---->当你需要将采集的数据用电压来显示的话:设你采集的数据为:x[0~4095],此时的计算公式就为:(x / 4096) * 3.6))


3、ADC供电要求:2.4V~3.6 V(可千万别接到 5V 的石榴裙子底下呀)


4、ADC输入范围:VREF-≤ VIN ≤VREF+ (VREF+和VREF-只有LQFP100封装才有)


5、双重模式(带2个ADC的设备): 8种转换模式


6、最多有18个通道:16个外部通道


2个内部通道:连接到温度传感器和内部参考电压(VREFINT = 1.2V)


.....(略,请看参考手册哈,由于篇幅,就不过多的列出来了、、说到略、让我想起了月光宝盒诸葛亮的:略懂略懂、、其实我也是略懂略懂而已、、)


12、DMA功能(仅ADC1有)


本博客里,由于篇幅、所以就以独立模式下的单次转换为例哈、打开参考手册可以看到这段话:


单次转换模式下,ADC只执行一次转换。


该模式既可通过设置ADC_CR2寄存器的ADON位(只适用于规则通道)启动也可通过外部触发启动(适用于规则通道或注入通道),这时CONT位为0。


一旦选择通道的转换完成:


● 如果一个规则通道被转换: ─ 转换数据被储存在16位ADC_DR寄存器中 ─EOC(转换结束)标志被设置 ─ 如果设置了EOCIE,则产生中断。


● 如果一个注入通道被转换: ─ 转换数据被储存在16位的ADC_DRJ1寄存器中 ─JEOC(注入转换结束)标志被设置 ─ 如果设置了JEOCIE位,则产生中断。


然后ADC停止。



此图形象的表明了其背后那不为人知的秘密转换关系。。虽然单凭看文字就能想象出来、但是、有图片是不是更加形象呢???




对于以上的寄存器、在此我稍微提提:免得寄存器大神们产生怨气:好不容易等到你讲我老大ADC,却不把我这些背后的勤劳者给导出来




好了,那就恕小弟容禀:




1、ADC状态寄存器(ADC_SR)



2、ADC控制寄存器1(ADC_CR1)



3、ADC控制寄存器2(ADC_CR2)


EXTSEL[2:0]:选择启动规则通道组转换的外部事件 (External event select for regular group)


ALIGN:数据对齐 (Data alignment)


RSTCAL:复位校准 (Reset calibration)


CAL:A/D校准 (A/D Calibration)


CONT:连续转换 (Continuous conversion)


ADON:开/关A/D转换器 (A/D converter ON / OFF)


4、ADC采样时间寄存器1(ADC_SMPR1)


SMPx[2:0]:选择通道x的采样时间 (Channel x Sample time selection)


5、ADC规则序列寄存器1(ADC_SQR1)


L[3:0]:规则通道序列长度 (Regular channel sequence length)


SQ1[4:0]:规则序列中的第1个转换 (1st conversion in regular sequence)(ADC规则序列寄存器3(ADC_SQR3))


6、ADC规则数据寄存器(ADC_DR)


DATA[15:0]:规则转换的数据 (Regular data)


(由于寄存器过于多,我们就不在这一一列举了哈、、因为我主要是用库,所以寄存器相关的位都不具体介绍了哈、请大家参照中文手册)


在这里,向大家介绍下:数据对齐:


ALIGN位用于设置对齐方式:右或左;


对于注入通道,转换结果是减去偏移量的值,可以为一个负数,在右对齐时扩展位位符号位。



那我们现在要怎么来实现呢??这个问题、相信大家在看了那么多的寄存器之后急迫想要知道的吧、、前面的只是个热身、、接下来步骤如下:


1、开启ADC1的时钟,由于ADC1是在PA1上,所以同时也要打开PA的时钟,并进行相关的配置、对于这个配置,要把PA1设置成模拟输入,为什么呢??大家打开中文参考手册可以看到



啊哈、、这下子清楚了吧、


2、复位ADC1,(本人觉得没必要、为什么,待会我会跟你说,留下悬念先),设置ADC1的分频因子,(记住,这里的ADC的时钟不能超过14MHZ),而且其采样周期长点会好点,


ADCCLK---最快可达14MHz, 时钟来自经过分频器的PCLK2(2、4、6、8分频)


整个转换时间 = 采样时间 + 12.5个周期(固定时间)


在14MHz和采样时间位1.5周期时  转换时间:1μs (14个周期 cycles)


当ADCCLK=14MHz和1.5周期的采样时间:


TCONV = 1.5 + 12.5 = 14周期 = 14×(1 / (14 × 1000000)) = 1μs


其采样周期一览表:



涉及到采样周期、这里来看看转换序列:


最多达16个转换通道且可以采样不同的顺序排列,不同的采样时间和过采样的可能性。


例如:- 转换通道:1、2、8、4、7、3、11


- 不同的采样时间;


- Oversampling of channel 7。



3、初始化ADC1的参数、设置ADC1的工作模式和规则序列的相关信息;


大家通过打开"stm32f10.adc.h"可以看到:


typedef struct


{


uint32_t ADC_Mode; //设置ADC模式-->独立模式


FunctionalState ADC_ScanConvMode; //设置是否开启扫描模式 --->否


FunctionalState ADC_ContinuousConvMode; //设置是否开启连续转换模式 ---->否


uint32_t ADC_ExternalTrigConv; //设置启动规则转换组转换模式---->软件触发


uint32_t ADC_DataAlign; //设置数据对齐方式----->右对齐


uint8_t ADC_NbrOfChannel; //设置规则序列的长度---->顺序进行规则转换的ADC通道数目1


}ADC_InitTypeDef;


4、使能ADC并校准


注:在设置完了以上信息后,使能AD转换器,执行复位校准和AD校准(这两步校准一定要,否则数据将不准)


还有记住,每次进行校准之后都要等待校准结束,但是通过什么方式知道校准结束呢?


这里是通过获取校准状态来判断是否校准结束,相关的库函数请看代码


分别的库函数请看待会的代码。(请用比较老外的方式去看,也就是用英语啦,为什么呢?请看下文)


5、读取AD的值


当然,这里说读取AD值并不是那么的简单,以上我们只是准备好了AD,还没有设置相关的规则序列通道,采样顺序,以及采样周期,设置完之后启动AD转换就行了、然后才直接读取哈、、


相关的库函数请看代码、


void Adc_Init(void)


{




ADC_InitTypeDef ADC_InitStructure;


GPIO_InitTypeDef GPIO_InitStructure;




/* Enable ADC1 and GPIOA clock */


RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_GPIOA, ENABLE);




RCC_ADCCLKConfig(RCC_PCLK2_Div6);//12MHZ




/* Configure PA.1 (ADC Channel) as analog input -------------------------*/


GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;


GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;


GPIO_Init(GPIOA, &GPIO_InitStructure);




//ADC_DeInit(ADC1);//在这里复位被我注释掉了、至于为什么,我待会会说




/* ADC1 configuration ------------------------------------------------------*/


ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;//这里对应上面所讲的配置,在这里就不给出注释了


ADC_InitStructure.ADC_ScanConvMode = DISABLE;


ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;


ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;


ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;


ADC_InitStructure.ADC_NbrOfChannel = 1;


ADC_Init(ADC1, &ADC_InitStructure);




/* Enable ADC1 *///知道我为啥要在上面提醒大家要用老外的方式来看了吧、因为这里的注释都是用英文的


//请不要以为我装逼,我这样做是有原因的、、原因我待会会说、你也会明白我最初的标题为何那样写




ADC_Cmd(ADC1, ENABLE);




/* Enable ADC1 reset calibration register */


ADC_ResetCalibration(ADC1);


/* Check the end of ADC1 reset calibration register */


while(ADC_GetResetCalibrationStatus(ADC1));




/* Start ADC1 calibration */


ADC_StartCalibration(ADC1);


/* Check the end of ADC1 calibration */


while(ADC_GetCalibrationStatus(ADC1));


}




u16 Get_val(u8 ch)


{


u16 DataValue; //又是英文注释、、啊哈


/* ADC1 regular channel14 configuration */


ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5);




/* Start ADC1 Software Conversion */


ADC_SoftwareStartConvCmd(ADC1, ENABLE);




/* Test if the ADC1 EOC flag is set or not */




while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));




//FlagStatus Status;


//Status = ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC);


//while(!Status);---->这样做实现不了、请注意


/*Returns the ADC1 Master data value of the last converted channel*/


DataValue = ADC_GetConversionValue(ADC1);


return DataValue;


}




u16 ADC_Get_aveg(u8 ch,u8 n)


{


u32 ad_sum = 0;


u8 i;


for(i=0;i

{


ad_sum += Get_val(ch);


delay_ms(5);


}


return (ad_sum / n);


}




adcx=ADC_Get_aveg(ADC_Channel_1,10);//获取AD数值(0~4095)




temp=(float)adcx*(3.3/4096);//获取相应的电压值




到了这一步,我们已经完成了AD采集数据的任务、接下来,有人可能有时候会觉得很纳闷,为什么有些人知道要完成特定的功能,它的步骤是怎么样的、为什么我就不知道??这个问题嘛、、接下来我讲的希望能稍微帮你,也希望你能好好的借鉴、




步骤小技巧:其实也没啥的、大家知道下载库的文件的时候,里面都有包含每个模块的例子和一个模版、拿ADC这个模块来举例:



点击main.c可以看到神奇的一幕:



大家仔细看看,可以发现在官方给的历程中的步骤里并没有复位ADC的函数,个人觉得所以没有必要去复位当然复位也不是什么坏事哈、看你个人、、看到这、应该明白了我前面的说法了吧、还有、大家应该也注意到了、都是英文的注释、、所以看到这大家也清楚了,前面不是我装逼、、所以呢、其实英语对于我们来说还是很重要的、、那有人问,时钟的分频因子呢?怎么没有设置??不急哈、、请看:




对于分频因子的设置,也在这个函数里:而这个RCC_Configuration()在最开始已经使用 了、、



所以大家要好好利用官方给的历程、说到这、你猜我词穷了吗?


答案是否定的、、我还有话要说:


做一件事要有一个目的、、才不会显得自己做的很空泛、、我写博客也一样、、我想让我自己理清思路、也希望自己在写的过程中能领悟到自己在学的时候没领悟到的知识点、、也希望能帮到跟我有一样困惑的人、、我把我不懂的理解后写下来、我也知道会有人跟我一样遇到同样不懂的地方、、所以这就是我的目的哈、、希望能帮到你们、、尽管不认识你们、、啊哈、、初学者、难免有出错、、所以、写错或理解错的请帮我指出来、臣不甚感激,今当远离,零表涕零,不知所言、、


推荐阅读

史海拾趣

遨格芯微(AGM)公司的发展小趣事

遨格芯微(AGM)自2012年成立以来,始终致力于可编程逻辑技术的研发。经过数年的努力,AGM成功开发出具有自主知识产权的FPGA核心技术,并在FPGA编译软件和电路领域取得了先进和成熟的技术成果。2014年,AGM的PLD芯片成熟并开始在行业得到应用,这标志着AGM在可编程逻辑技术领域取得了重大突破。随后,AGM推出三个系列的CPLD、FPGA、Programmable SoC产品,并进入量产阶段,得到了包括三星在内的多家知名厂商的认证,为公司的进一步发展奠定了坚实基础。

Global Communications公司的发展小趣事
温度传感器和晶体振荡器都可能受到外界噪声的干扰,影响测量和补偿的准确性。因此,在电路设计中需要采取屏蔽、滤波等措施来降低噪声干扰。
Block USA Inc.公司的发展小趣事

除了支付业务外,Block USA Inc.还积极投身于软件SAAS服务的研发与创新。公司推出了一系列针对餐厅、薪资发放和预约等领域的软件解决方案,帮助商家提升运营效率和管理水平。这些软件服务的推出,不仅进一步丰富了Block的产品线,也为其在电子行业中树立了创新者的形象。

华宇创公司的发展小趣事

为了进一步扩大市场份额,华宇创开始积极拓展国内外市场。公司参加了多场国际电子展和博览会,与全球各地的客户建立了广泛的联系。同时,华宇创还与国际知名电子企业建立了战略合作关系,共同研发新技术、新产品。这些国际合作不仅为华宇创带来了更多的商业机会,也提升了公司在国际市场的地位和影响力。

Beck IPC GmbH公司的发展小趣事

为了进一步增强公司的竞争力,Beck IPC积极寻求与其他优秀企业的收购与合作机会。在某一时期,公司成功收购了一家在边缘网关系列产品领域具有领先地位的企业。通过这次收购,Beck IPC不仅获得了更多先进的技术和产品,还进一步巩固了其在工业物联网领域的地位。此外,公司还与多家知名企业建立了战略合作关系,共同推动行业发展。

Advanced Detector Corp公司的发展小趣事

Advanced Detector Corp公司成立于上世纪80年代,由一群热衷于探测器技术研发的科学家和工程师创立。在创立初期,ADC便专注于开发高精度、高灵敏度的探测器技术,以满足当时日益增长的电子测量需求。公司通过持续的技术创新,逐渐在探测器领域取得了突破性的进展,并成功推出了一系列具有竞争力的产品。

问答坊 | AI 解惑

交通系统

本系统是基于FPGA的代码…

查看全部问答>

急急急急——高分求救,可加分!串口通讯相关,打印相关,wince + vs2005 + c/c++

配置:wince6.0 , vs2005 使用语言: c/c++ 问题背景:现在有一个类似于PDA的终端设备,使用RS232片,需要驱动其打印机来打印由磁卡扫描得到的数据,可是,使用串口COM均失败。使用GetLastError得到的错误为55,即设备不可用。首要问题,如何解 ...…

查看全部问答>

WIN XP驱动程序无法实现自动安装,请各位大侠指点迷津!多谢!

我们开发了一个USB  MODEM,想开发一个驱动程序的自动安装程序。但是发现在先连接上USB设备是再安装驱动程序可以成功;但是如果不插USB设备,安装完成后,插入USB she设备后,驱动程序无法实现自动安装,WIN XP会弹出“驱动设备安装“对 ...…

查看全部问答>

求助:IAR怎么通过JTAG下载调试

                                 RT,IAR怎么通过JTAG下载调试?需要怎么设置?…

查看全部问答>

proteus自动退出解决方法

      今天把装的proteus7.7 拉出来用了一下,结果发现打开一会就会自动关闭,很是不爽。 在网上找了很多,都说没什么好的解决方法,最后在一位高手的博客中看到了一个很小的解决方法,拿出来共享一下, 解决大家的麻烦 ...…

查看全部问答>

求助MSP430学习?

我想学习MSP430,可是不知道买什么开发板?上次参加活动获得MSP430 LaunchPad 发现不会玩,好是困惑。帖子上关于如何学习MSP430的回复很少,望好心者提供建议 …

查看全部问答>

新手提问跑马灯按键问题

最近刚接触FPGA,接触的第一个实验室是流水灯,我流水灯已经能跑通了,现在想在实验室里加一个按键,按一下流水灯就暂停,再按一下流水灯接着跑。下边是我的代码,流水灯每1秒钟左移1位,求高人指点上边按键的问题。     刚接触问题很多 ...…

查看全部问答>

multisim仿真max275原理图,希望对大家有用~

multisim仿真max275原理图,希望对大家有用~ 前两天在网上没有找到max275的仿真资料,没有办法就自己按datasheet做了个仿真的原理图,现在贴出来方便大家能快速入手。 可能图中也有不当之处,或者更好的实现方式,也请大家不吝赐教。 软件用的mu ...…

查看全部问答>

【跟TI学电源】系列------ TI 功率电池管理解决方案

replyreload += \',\' + 1492307;TI 功率电池管理解决方案 Timson,如果您要查看本帖隐藏内容请回复…

查看全部问答>

TI 电池电量监测芯片 bq27x00 进行精确计量电量值

尽管电压测量已经单独被用于许多便携式产品估算电池的剩余电量,但是这种方法可能存在高达 50% 的误差。电池电压和电量之间的关系会随放电率、温度和电池老化程度而有所不同。例如,相比相同电量损耗的低放电率,高放电率会带来更大的压降。当电池 ...…

查看全部问答>