因项目需要使用到STM32的ADC功能,虽然对ADC的使用并不陌生,但是第一接触stm32的ADC功能还是有种无从下手的感觉,主要是因为STM32ADC设计较为复杂,一时对相关的专业术语较为生疏,此外固件库中涉及到的函数虽都进行了分门别类但是还是感觉函数较多,难以很快掌握,现就将个人理解写出,以便大家共同进步。
一、stm32 ADC特点
认识事物首先还是要从整体上把握,ADC也一样的道理,STM32的ADC外设提供了非常完善的功能,虽然其中很大一部分不见得能在项目中使用,但加深对其的认识对于合理利用其资源也是非常有必要的。
下面以项目采用的STM32L151为例,其他类型大同小异。参考RM0038 Reference manual(CD00240193.pdf)
先看原文:
• 12-bit, 10-bit, 8-bit or 6-bit configurable resolution
• Interrupt generation at the end of regular conversions, end of injected conversions, and in case of analog watchdog or overrun events (for regular conversions)
//在规则转换结束、注入转换结束以及模拟看门狗溢出和overrun事件(规则转换模式)发生时能产生中断
• Single and continuous conversion modes //有单次和连续转换模式
• Scan mode for automatic conversions in a fully programmable order //在自动转换中支持完成可编程的扫描模式
• Programmable data alignment with in-built data coherency //数据对齐方式可编程
• Programmable and individual sampling time for each ADC channel //可以为每个通道设置独立的采样时间
• External trigger option with configurable edge detection for both regular and injected
conversions //外部触发模式对规则和注入转换模式均支持可配置的边沿触发方式
• Discontinuous mode //非连续模式
• ADC conversion time: 1 μs at full speed (ADC clocked at 16 MHz) down to 4 μs at low speed (ADC clocked at 4 MHz), independent of the APB clock//最低采样时间
• Automatic power-up/power-down to reduce the power consumption//自动的上下电便于节能
• ADC supply requirements:
– 2.4 V to 3.6 V at full speed or with reference zooming (VREF+ < VDDA)
– down to 1.8 V at slower speeds //工作电压范围
• ADC input range: VREF– ≤ VIN ≤ VREF+
• Automatic programmable hardware delay insertion between conversions
• DMA request generation during regular channel conversion //规则转换支持DMA
从官方的描述中可以了解到STM32ADC所提供的强大功能,及一些工作特性,那么如何才能使用这些功能呢?
首先要明确两个概念
1.规则组和注入组
区分二者非常重要,因为它关系到实际ADC的能力,这里有篇介绍感觉不错,推荐给大家,(http://wenku.baidu.com/link?url=blwVQAxelZqJCbVMuq3QsH9N-J3A8LNlhTTwO01yVsT2z8UCn4tjPyHGeRvR5g925gqJjRVSHYHRXDcstUdvnjZwSDyCfTmrxlq6z2oqwS7)我的理解是规则组就是按照一定的规则执行(大多用于大规模的连续转换条件下)而注入组则多执行单次的转换,只在我们需要时转换。在我们的项目中会不定时的读取某个挂在ADC上的温度传感器,因此对其的读取采用了注入组,同时还需要周期性的连续读取数个通道的ADC数据多次,因此对其的操作选用了规则组的方式。
单次/连续和扫描模式
单次对应于连续,这个很容易理解,也即单次只进行一次转换,连续方式中在触发转换以后会一直进行转换。
而扫描模式则表示,在一个通道转换结束后马上进行下个通道的转换(通道转换顺序需指定)其不论在单次还是在连续模式下均有意义。
理解了这些就可以进行初步的编程,考虑到对寄存器的操作需要对寄存器较为熟悉,而项目工期又比较紧张,因此采用了固件库的方式。
2.STM32固件库简单介绍
项目中采用了V1.2版的固件库(stsw-stm32077),在固件库中集成了大量的示例程序,对于快速上手非常有帮助。
在来看在stm32l1xx_adc.h中所提供的函数:
/* Function used to set the ADC configuration to the default reset state *****/
void ADC_DeInit(ADC_TypeDef* ADCx);
/* Initialization and Configuration functions *********************************/
void ADC_Init(ADC_TypeDef* ADCx, ADC_InitTypeDef* ADC_InitStruct);
void ADC_StructInit(ADC_InitTypeDef* ADC_InitStruct);
void ADC_CommonInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
void ADC_CommonStructInit(ADC_CommonInitTypeDef* ADC_CommonInitStruct);
void ADC_Cmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_BankSelection(ADC_TypeDef* ADCx, uint8_t ADC_Bank);
/* Power saving functions *****************************************************/
void ADC_PowerDownCmd(ADC_TypeDef* ADCx, uint32_t ADC_PowerDown, FunctionalState NewState);
void ADC_DelaySelectionConfig(ADC_TypeDef* ADCx, uint8_t ADC_DelayLength);
/* Analog Watchdog configuration functions ************************************/
void ADC_AnalogWatchdogCmd(ADC_TypeDef* ADCx, uint32_t ADC_AnalogWatchdog);
void ADC_AnalogWatchdogThresholdsConfig(ADC_TypeDef* ADCx, uint16_t HighThreshold,uint16_t LowThreshold);
void ADC_AnalogWatchdogSingleChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel);
/* Temperature Sensor & Vrefint (Voltage Reference internal) management function */
void ADC_TempSensorVrefintCmd(FunctionalState NewState);
/* Regular Channels Configuration functions ***********************************/
void ADC_RegularChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_SoftwareStartConv(ADC_TypeDef* ADCx);
FlagStatus ADC_GetSoftwareStartConvStatus(ADC_TypeDef* ADCx);
void ADC_EOCOnEachRegularChannelCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_ContinuousModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_DiscModeChannelCountConfig(ADC_TypeDef* ADCx, uint8_t Number);
void ADC_DiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
uint16_t ADC_GetConversionValue(ADC_TypeDef* ADCx);
/* Regular Channels DMA Configuration functions *******************************/
void ADC_DMACmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_DMARequestAfterLastTransferCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
/* Injected channels Configuration functions **********************************/
void ADC_InjectedChannelConfig(ADC_TypeDef* ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime);
void ADC_InjectedSequencerLengthConfig(ADC_TypeDef* ADCx, uint8_t Length);
void ADC_SetInjectedOffset(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel, uint16_t Offset);
void ADC_ExternalTrigInjectedConvConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConv);
void ADC_ExternalTrigInjectedConvEdgeConfig(ADC_TypeDef* ADCx, uint32_t ADC_ExternalTrigInjecConvEdge);
void ADC_SoftwareStartInjectedConv(ADC_TypeDef* ADCx);
FlagStatus ADC_GetSoftwareStartInjectedConvCmdStatus(ADC_TypeDef* ADCx);
void ADC_AutoInjectedConvCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
void ADC_InjectedDiscModeCmd(ADC_TypeDef* ADCx, FunctionalState NewState);
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel);
/* Interrupts and flags management functions **********************************/
void ADC_ITConfig(ADC_TypeDef* ADCx, uint16_t ADC_IT, FunctionalState NewState);
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint16_t ADC_FLAG);
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint16_t ADC_FLAG);
ITStatus ADC_GetITStatus(ADC_TypeDef* ADCx, uint16_t ADC_IT);
void ADC_ClearITPendingBit(ADC_TypeDef* ADCx, uint16_t ADC_IT);
/* ******************* flags management functions **********************************/
FlagStatus ADC_GetFlagStatus(ADC_TypeDef* ADCx, uint16_t ADC_FLAG);
void ADC_ClearFlag(ADC_TypeDef* ADCx, uint16_t ADC_FLAG);
从上面不同的颜色及注释均能看到函数按功能分成几部分相互之间相互独立(flags management 除外)明白了这些对与我们使用库函数编程非常有帮助。
二、stm32 ADC的初始化
外设的初始化无外乎包含时钟、GPIO功能(复用型)、外设功能设置、中断配置等步骤,项目中参考了固件库示例程序初始化部分,下面就以示例程序(ADC1_Freeze)初始化为例讲解。
1.找到ADC_Config
void ADC_Config(void)
{
/* Enable The HSI (16Mhz) */
RCC_HSICmd(ENABLE);//时钟源选择及配置,参见时钟树
/* Check that HSI oscillator is ready */
while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);
/* Configure RV3 input voltage */
/* Enable the GPIOF Clock */
RCC_AHBPeriphClockCmd(IDD_MEASUREMENT_GPIO_CLK, ENABLE);
/* Configure PF.10 (ADC Channel31) or PA.12 (ADC channel 18) in analog mode */
//GPIO部分,比较乱,对实用到的GPIO都配置为模拟输入的方式
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_X;
GPIO_Init(IDD_MEASUREMENT_GPIO, &GPIO_InitStructure);
/* Configure the IDD input */
/* Configure PF.11 (ADC channel 1b) or PA.05 (ADC channel 5) in analog mode */
GPIO_InitStructure.GPIO_Pin = GPIO_PIN_Y;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(IDD_MEASUREMENT_GPIO, &GPIO_InitStructure);
/* ADC1 Configuration ------------------------------------------------------*/
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);//ADC1时钟,建议和上面时钟放一起
/* ADC1 DeInit */
ADC_DeInit(ADC1);
#ifdef USE_STM32L152D_EVAL
/* Select ADC Bank channel */
ADC_BankSelection(ADC1, ADC_Bank_B);
#endif
/* ADC1 Configuration of channel18/31 and channel5/1b : continuous mode, external trigger (TIM2) *///ADC初始化部分,根据需要选择配置
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12bit 分辨率
ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描方式开启
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转换
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Falling;//上升沿触发
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_TRGO;//外部触发,与上配置匹配
//项目采用了软件触发,触发方式:无 与示例不同
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfConversion = 2;//转换的个数(扫描方式特有)项目该项设置为6 (最大为16),连续采用6个通道的数据
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 Regular Channel Config *///规则通道顺序配置,项目中将使用到的四个通道分别设置为1-4的顺序
ADC_RegularChannelConfig(ADC1, IDD_MEASUREMENT_ADC_CHANNEL, 1, ADC_SampleTime_192Cycles);
ADC_RegularChannelConfig(ADC1, RV3_MEASUREMENT_ADC_CHANNEL, 2, ADC_SampleTime_192Cycles);
//这里没设置注入通道,注入通道需要将通道配置才能使用,这样每个通道才对应于一个注入通道数据寄存器(数目为4),因此可选择通道数目最大为4,配置方式与上相同,只需更换配置函数为ADC_InjectedChannelConfig即可。项目设置了4个注入通道
//此外示例没有采用中断和DMA方式,这样采样得到的数据很容易丢失,因为规则通道公用一个数据寄存器,因此需要在一个转换周期内读出数据,紧接着读取下一个通道的数据。
/* Enables the ADC1 Power Down during Delay */ //节能模式,可选
ADC_PowerDownCmd(ADC1, ADC_PowerDown_Idle_Delay, ENABLE);
/* Delay until the converted data has been read */
ADC_DelaySelectionConfig(ADC1, ADC_DelayLength_Freeze);
/* Enable ADC1 *///使能外设电源,外设开始工作
ADC_Cmd(ADC1, ENABLE);
/* Wait until the ADC1 is ready *///等待外设稳定工作ADC_GetFlagStatus
while(ADC_GetFlagStatus(ADC1, ADC_FLAG_ADONS) == RESET)
{
}
}
//初始化部分完成
三、对外设的使用
外设的使用无外乎选择合理的方式读取到通道数据。
首先是读取注入通道的数据,注入通道需要启动转换,所采用函数均在库函数中注入组的函数组中(flag除外)
以注入组1为例
int ADC_Injected_Read(void)
{
int ad_val;
ADC_SoftwareStartInjectedConv(ADC1);//软件触发,启动转换
while(RESET ==ADC_GetFlagStatus(ADC1,ADC_FLAG_JEOC));//等待注入组转换完成
ad_val = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); //获取注入通道1数据,对应于初始化配置中的ADC通道
return ad_val; //数据未做进一步处理
}
规则组采用DMA传输,需在初始化中进行设置。
上一篇:stm32的几种读保护措施讲解
下一篇:STM32的AD用DMA方式时的请注意初始化顺序
推荐阅读
史海拾趣
为了更好地推动快充技术的发展和应用,联智加入了终端快充行业协会。作为该协会的成员,联智积极贡献自身在快充协议、电源管理无线充电芯片和方案研发方面的经验和技术,与协会其他成员共同推动充电技术的标准化、产业化应用和推广。这一举措不仅有助于提升联智在快充行业的知名度和影响力,还将促进整个行业的健康发展。
联智的半导体集成电路芯片研发及产业化项目是其发展历程中的又一重要里程碑。该项目总投资高达20亿元,分两期建设。一期项目将建设半导体集成电路模拟芯片封测生产线,预计年产量可达1.5亿颗。二期项目将研发更高功率有线无线融合一体化电源管理芯片和新一代A4WP远距离无线充电芯,同时布局物联网IoT芯片市场。这一项目的实施将进一步提升联智的技术实力和市场竞争力。
Antenna Factor公司最初由几位热衷于无线通信技术的工程师创立。创业初期,他们面临着资金短缺、技术难题和市场认可度低等多重挑战。然而,他们凭借着对技术的执着和不懈的努力,成功开发出了一款具有高性价比的天线产品,并获得了市场的初步认可。这一突破性的产品为公司的发展奠定了坚实的基础。
人才是企业发展的核心。Compostar Technology Co Ltd深知这一点,因此一直注重人才培养和团队建设。公司建立了完善的人才培训体系,为员工提供了广阔的职业发展空间。同时,公司还积极营造良好的企业文化氛围,激发员工的创新精神和团队合作精神。这些举措使得公司拥有一支高素质、高效率的员工队伍,为公司的持续发展提供了有力保障。
Compostar Technology Co Ltd公司自成立以来,一直致力于电子技术的研发与创新。在早期,公司凭借一款具有高效能耗比的电源管理芯片,成功打入了市场。随着技术的不断进步,公司逐渐将业务扩展到通信、智能家居和可穿戴设备等多个领域。公司不断投入研发资金,吸引了一批优秀的科研人才,成功研发出多款具有竞争力的产品,逐渐在电子行业中树立了良好的口碑。
进入1950年代,Eclipse Magnetics迎来了一次重要的创新。公司决定将磁铁涂上红色,这一独特的红色磁铁迅速在市场上获得了认可。同时,公司还设计了与红色磁铁相配的马蹄形标志,这一标志后来成为Eclipse Magnetics的国际通用标记。随着品牌的国际化,Eclipse Magnetics的产品开始进入全球市场。
最近几天也在跟朋友聊,关于创业的事,创业意味着自己有了奔向自由资金的潜力,因而,不管目前状况多窘迫,只要坚持下来,总有收获的。 那么如果想组建个自己的弱电公司,你觉得需要具备哪些条件呢? 也有朋友说,如果不是从产品入手而是从工程入 ...… 查看全部问答∨ |
|
[招聘]西安一知名公司招聘fpga设计/验证工程师、嵌入式软件工程师等 西安一个业界知名公司的研发中心正在招聘,主要面向fpga设计/验证工程师、嵌入式软件工程师。待遇绝对有竞争力,如有意向速发邮件至:nwumengfei@163.com… 查看全部问答∨ |
|
环境:EVC4+SP4 PB5.0 问题:使用Directshow,包含头文件 <streams.h>, <dmodshow.h> <dmoreg.h> <wmcodec.h> 这些头文件使用到了库文件strmiids.lib、dmoguids.lib,提示错误是canno open file srmiids.lib、dmo ...… 查看全部问答∨ |
以前用sunrain_hjb 前辈的wince串口调试助手,但是最近发现这个程序一旦打开就会造成系统运行很慢,刚开始我以为是我的串口驱动问题,但是我找一个比较简单的来用,发现我那个基本不会导致系统慢,并且我放到开发板也是一样的效果。 现在请大伙提 ...… 查看全部问答∨ |
亲爱的盆友们, 一家德资的知名电子公司招聘模拟电子工程师,公司中国区总部在深圳,中山、广州等地均有工厂。招聘量较大,2年至8、9、10年经验都ok的~ JD如下,请将简历发至wmm0415@126.com 或者 ...… 查看全部问答∨ |
设计资源 培训 开发板 精华推荐
- 直播已结束【英飞凌智能门锁解决方案】
- 有奖直播:使用 NI CompactDAQ 和 LabVIEW构建基于传感器的测试系统
- 有奖直播报名:赛灵思和安富利专注嵌入式视觉应用,助力人工智能和汽车辅助驾驶!
- 【技术直播】 MPS、Nexperia、泰克专家齐聚,畅谈新能源汽车动力设计注意要点
- 学习Altera《SoC FPGA:体系结构重要吗?》文章,答题赢好礼!
- 下载MPS AI电源资料包,赢【Keep体脂秤、按摩眼罩、电脑支架】
- 直播已结束|TI Zigbee 3.0及多协议解决方案
- 【主题月活动】二极管,你了解多少
- 关注、评论赢好礼!《美光2022台北国际电脑展主题演讲精选:智能边缘与智能制造专辑》