历史上的今天
返回首页

历史上的今天

今天是:2025年02月21日(星期五)

正在发生

2020年02月21日 | 浅谈stm32f1两路adc采集(非DMA)

2020-02-21 来源:eefocus

由于项目的需要写2路ADC采集,发现采集的电压出现很大的误差。(后来换成ADC1和ADC2模式后解决了)仔细看了一下,不会是板子对应的引脚共用,那到底是怎么回事呢?想到了电路上的上拉电阻,测量出现的电压数值跳变不就是高阻态吗?在程序当中要是利用到上拉电阻不就搞定了吗!翻开某库函数关于ADC的介绍如下:


STM32 拥有 1~3 个 ADC(STM32F101/102 系列只有 1 个 ADC),这些 ADC 可以独立使用,也可以使用双重模式(提高采样率)。STM32 的 ADC 是 12 位逐次逼近型的模拟数字转换器。


它有 18 个通道,可测量 16 个外部和 2 个内部信号源。各通道的 A/D 转换可以单次、连续、扫描或间断模式执行。ADC 的结果可以左对齐或右对齐方式存储在 16 位数据寄存器中。模拟看门狗特性允许应用程序检测输入电压是否超出用户定义的高/低阀值。


STM32F103 系列最少都拥有 2 个 ADC,我们选择的 STM32F103ZET 包含有 3 个 ADC。

STM32 的 ADC 最大的转换速率为 1Mhz,也就是转换时间为 1us(在 ADCCLK=14M,采样周期为 1.5 个 ADC 时钟下得到),不要让 ADC 的时钟超过 14M,否则将导致结果准确度下降。


STM32 将 ADC 的转换分为 2 个通道组:规则通道组和注入通道组。规则通道相当于你正

常运行的程序,而注入通道呢,就相当于中断。在你程序正常执行的时候,中断是可以打断你的执行的。同这个类似,注入通道的转换可以打断规则通道的转换, 在注入通道被转换完成之后,规则通道才得以继续转换。STM32 其 ADC 的规则通道组最多包含 16 个转换,而注入通道组


最多包含 4 个通道。STM32 的 ADC 可以进行很多种不同的转换模式,本章仅介绍如何使用规则通道的单次转换模式。STM32 的 ADC 在单次转换模式下,只执行一次转换,该模式可以通过 ADC_CR2 寄存器的 ADON 位(只适用于规则通道)启动,也可以通过外部触发启动(适用于规则通道和注入通道),这是 CONT 位为 0。


以规则通道为例,一旦所选择的通道转换完成,转换结果将被存在 ADC_DR 寄存器中,

EOC(转换结束)标志将被置位,如果设置了 EOCIE,则会产生中断。然后 ADC 将停止,直到下次启动,还是直接上程序吧。


//初始化ADC这里我们仅以规则通道为例,默认将开启通道0~3


void  Adc_Init(void)


ADC_InitTypeDef ADC_InitStructure; 

GPIO_InitTypeDef GPIO_InitStructure;

  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB|RCC_APB2Periph_ADC1|RCC_APB2Periph_ADC2|RCC_APB2Periph_AFIO,ENABLE);


RCC_ADCCLKConfig(RCC_PCLK2_Div6);   //设置ADC分频因子6 72M/6=12,ADC最大时间不能超过14M


//PA1 作为模拟通道输入引脚                         

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; //模拟输入引脚

GPIO_Init(GPIOA, &GPIO_InitStructure);

//////

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_1; //选择你要设置的IO口

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AIN;  

GPIO_Init(GPIOB,&GPIO_InitStructure); /* 初始化GPIO */


ADC_DeInit(ADC1);  //复位ADC1 

ADC_DeInit(ADC2);  //复位ADC2


ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; //ADC工作模式:ADC1和ADC2工作在独立模式

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数据右对齐

ADC_InitStructure.ADC_NbrOfChannel = 1; //顺序进行规则转换的ADC通道的数目

ADC_Init(ADC1, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   

ADC_Init(ADC2, &ADC_InitStructure); //根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存?

  

ADC_RegularChannelConfig(ADC1,ADC_Channel_1,1,ADC_SampleTime_239Cycles5);

ADC_RegularChannelConfig(ADC2,ADC_Channel_9,1,ADC_SampleTime_239Cycles5);


ADC_DiscModeCmd(ADC1, ENABLE);

ADC_DiscModeCmd(ADC2, ENABLE);


ADC_Cmd(ADC1, ENABLE); //使能指定的ADC1

ADC_Cmd(ADC2, ENABLE);

ADC_ResetCalibration(ADC1); //使能复位校准  

  ADC_ResetCalibration(ADC2); //使能复位校准   

while(ADC_GetResetCalibrationStatus(ADC1)); //等待复位校准结束

while(ADC_GetResetCalibrationStatus(ADC2)); //等待复位校准结束

ADC_StartCalibration(ADC1); //开启AD校准

  ADC_StartCalibration(ADC2); //开启AD校准

while(ADC_GetCalibrationStatus(ADC1)); //等待校准结束

  while(ADC_GetCalibrationStatus(ADC2)); //等待校准结束

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能

ADC_SoftwareStartConvCmd(ADC2, ENABLE);

}  

//获得ADC值

//ch:通道值 0~3

u16 Get_Adc(u8 ch)   

{

  //设置指定ADC的规则组通道,一个序列,采样时间

ADC_RegularChannelConfig(ADC1, ch, 1, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期    

  

ADC_SoftwareStartConvCmd(ADC1, ENABLE); //使能指定的ADC1的软件转换启动功能

 

while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC ));//等待转换结束



return ADC_GetConversionValue(ADC1); //返回最近一次ADC1规则组的转换结果

}



u16 Get_Adc2(u8 ch2)   

{

  //设置指定ADC的规则组通道,一个序列,采样时间

ADC_RegularChannelConfig(ADC2, ch2, 2, ADC_SampleTime_239Cycles5 ); //ADC1,ADC通道,采样时间为239.5周期    

  

ADC_SoftwareStartConvCmd(ADC2, ENABLE); //使能指定的ADC1的软件转换启动功能

 

while(!ADC_GetFlagStatus(ADC2, ADC_FLAG_EOC ));//等待转换结束


return ADC_GetConversionValue(ADC2); //返回最近一次ADC1规则组的转换结果////

}


u16 Get_Adc_Average(u8 ch,u8 times)

{

u32 temp_val=0;

u8 t;

for(t=0;t{

temp_val+=Get_Adc(ch);

delay_ms(5);

}

return temp_val/times;

}  


u16 Get_Adc_Average2(u8 ch,u8 tim)

{

u32 temp_val=0;

u8 t;

for(t=0;t{

temp_val+=Get_Adc2(ch);

delay_ms(5);

}

return temp_val/tim;


}  


这样一来,只要在main 里面初始化和调用Get_Adc_Average(ADC_Channel_1,10); 和Get_Adc_Average2(ADC_Channel_9,10); 就可以啦,其他多路采集也可以参照上述方式进行,(PS:第一次写博客,有不足之处请大佬们指出,谢谢)

推荐阅读

史海拾趣

DAVE Embedded Systems公司的发展小趣事

随着公司的发展,DAVE Embedded Systems不断投入研发力量,致力于技术创新和产品创新。他们基于最新技术(如多核ARM Cortex、PowerPC和X86)设计了一系列高端嵌入式系统模块,这些产品不仅满足了客户对性能的需求,还提供了更好的可靠性和可扩展性。此外,公司还积极开发基于Android和Windows平台的嵌入式系统模块,以满足不同客户的需求。

Henkel公司的发展小趣事

随着公司的发展,DAVE Embedded Systems不断投入研发力量,致力于技术创新和产品创新。他们基于最新技术(如多核ARM Cortex、PowerPC和X86)设计了一系列高端嵌入式系统模块,这些产品不仅满足了客户对性能的需求,还提供了更好的可靠性和可扩展性。此外,公司还积极开发基于Android和Windows平台的嵌入式系统模块,以满足不同客户的需求。

DuPont公司的发展小趣事

为了进一步拓展电子市场,DuPont公司积极寻求与全球知名电子企业的合作。通过与国际知名品牌的战略合作,DuPont成功进入了多个重要的电子市场领域,如智能手机、平板电脑、汽车电子等。这些合作不仅为DuPont公司带来了广阔的市场空间,也促进了公司在电子领域的技术创新和产品升级。

Advanced Microelectronic Products Inc公司的发展小趣事

在电子行业竞争日益激烈的背景下,AMP公司面临着来自同行的巨大压力。为了应对这一挑战,公司进行了战略调整,将重心转向高端电子产品的研发和生产。通过不断提升产品性能和品质,AMP公司成功打造了多个高端品牌,并在细分市场中取得了显著优势。此外,公司还积极拓展新的应用领域,为未来发展奠定了坚实基础。

Anaren公司的发展小趣事

AMP公司深知人才是企业发展的核心动力。因此,公司高度重视人才培养和团队建设。公司建立了一套完善的人才培养机制,通过内部培训、外部引进等方式,不断提升员工的专业技能和综合素质。同时,公司还注重团队建设,鼓励员工之间的合作与交流,营造积极向上的工作氛围。这些举措为AMP公司的持续发展提供了有力的人才保障。

ACCRETECH公司的发展小趣事

在追求经济效益的同时,AMP公司也积极履行社会责任,致力于实现可持续发展。公司注重环保和节能减排,采用先进的生产工艺和设备,减少对环境的影响。此外,公司还积极参与社会公益事业,为社会发展和进步贡献力量。这些举措不仅提升了AMP公司的社会形象,也为其赢得了更多消费者的支持和信任。

请注意,以上故事均为虚构内容,旨在展示一个假设的电子行业公司在发展过程中可能遇到的情境和策略。实际公司的发展历程和细节将因公司而异,并受到市场环境、技术变革、政策调整等多种因素的影响。

问答坊 | AI 解惑

编译linux内核生成的system.map文件详解

有时system.map文件可以帮助我们理解内核编译,它记录了所有代码的运行地址。 下面一起看看如何读懂它 system.map内容格式为:线性地址 类型 符号 具体内容如下: 00100000 A phys_startup_32 c0100000 T startup_32 c0100000 A _text ...…

查看全部问答>

fpga流水线问题

大家就FPGA流水线技术广泛讨论一下啊…

查看全部问答>

如何在设备上加usb device,连接上电脑可当做移动硬盘

现在手头上有一个设备(一个播放器),挂有大容量的硬盘,设备本身支持很多种接口(SATA,PCI,USB HOST),现在需要在上面加上一个usb device 接口,并能实现接上PC是能认出大容量存储器,目前还没有思路,请这方面的牛人们指点一下。…

查看全部问答>

寻找有USB和12位AD的IC

                                 本来想用STM32系列,可惜就是价格。。。。不知道各位能否推荐几款拥有USB和12位AD的IC,价格比STM32便宜一些的,谢 ...…

查看全部问答>

开关电源讲议

开关电源讲议,对初学者很有帮助的! [ 本帖最后由 aishuang 于 2011-7-17 07:43 编辑 ]…

查看全部问答>

Xemga A3U 能干什么

带USB口的Xemga系列能干什么?如果价格降到多少钱大家就不会用STM了?好怀念用AVR代码的时代,现在正被逼着用STM。郁闷中,想辞职。想告诉老板xemga国内有货了,也带USB…

查看全部问答>

这种图用什么软件画的,主要画出凹凸效果

大家看看,这种图用什么软件画的,个人觉得凹凸效果比较有质感。 …

查看全部问答>

自控

本帖最后由 paulhyde 于 2014-9-15 03:06 编辑 昨天才拿到瑞萨的芯片,要是真用他们的芯片,那玩个球    …

查看全部问答>

在一个数组实现整型和浮点型的显示

请问,我想在IAR中定义数组,包含两组数据,一组是由zigbee接温度传感器测得的int型数据,另一组是自己写入的,要带小数的,请问这怎么定义啊??eg:22和602.55,在一个数组定义。或者我可以不定义数组,有什么别的方式实现这种做法?…

查看全部问答>