OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8319|回复: 6

请教,用HAL库定时采集ADC数据的标准方法是怎样的?谢谢

[复制链接]

7

主题

16

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2018-1-20
在线时间
6 小时
发表于 2018-1-20 08:34:07 | 显示全部楼层 |阅读模式
1金钱
比如我想1秒采集一次ADC数据,我试过的方法是 在TIM的更新中断中加了GetADC(),这个GetADC()用的是阿波罗例程72里的代码。
问题是 执行程序时只读了一次ADC就死循环在while(!(__HAL_ADC_GET_FLAG(hadc, ADC_FLAG_EOC))),ADC_FLAG_EOC一直是0。


请教大家,用HAL库定时采集ADC数据的标准方法是怎样的?谢谢!

相关代码:
//读取ADC值
uint16_t GetADC()
{
  HAL_ADC_Start(&hadc1);
  HAL_ADC_PollForConversion(&hadc1,100);
  return HAL_ADC_GetValue(&hadc1);
}

//定时器更新中断
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{          
        printf("%d\r\n",GetADC());                //返回adc值       
}


最佳答案

查看完整内容[请看2#楼]

不要在中断里执行阻塞式的函数,你定时器设一个标记,到时间就将该标记置1,主循环检测到该标记为1再执行GetADC()并将其清0就可以了。又或者修改Get_ADC()函数,不要用HAL_ADC_Start(),改用 HAL_ADC_Start_IT() ,然后在回调函数里获取数据。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

0

主题

88

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
361
金钱
361
注册时间
2016-11-1
在线时间
119 小时
发表于 2018-1-20 08:34:08 | 显示全部楼层
本帖最后由 Noctis 于 2018-1-20 09:45 编辑

不要在中断里执行阻塞式的函数,你定时器设一个标记,到时间就将该标记置1,主循环检测到该标记为1再执行GetADC()并将其清0就可以了。又或者修改Get_ADC()函数,不要用HAL_ADC_Start(),改用 HAL_ADC_Start_IT() ,然后在回调函数里获取数据。
回复

使用道具 举报

7

主题

16

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2018-1-20
在线时间
6 小时
 楼主| 发表于 2018-1-20 10:39:36 | 显示全部楼层
Noctis 发表于 2018-1-20 09:39
不要在中断里执行阻塞式的函数,你定时器设一个标记,到时间就将该标记置1,主循环检测到该标记为1再执行Ge ...

首先谢谢解答!
1)如果不要在中断里执行阻塞式的函数,你定时器设一个标记,到时间就将该标记置1,主循环检测到该标记为1再执行GetADC()并将其清0就可以了。
这种获取ADC值没问题,不太好的是GetADC()内容的执行要受到main的while(1)里其他代码的干扰,比如要执行完其他代码才能GetADC(),采样快了有可能存在延时。所以我觉得最好还能放在TIM的中断里,代码也规整。
2)又或者修改Get_ADC()函数,不要用HAL_ADC_Start(),改用 HAL_ADC_Start_IT() ,然后在回调函数里获取数据。
我试的结果是改为 HAL_ADC_Start_IT(),同样是在判断EOC那死循环。而且原子哥的例程GetADC()里用的就是 HAL_ADC_Start_IT() 。
回复

使用道具 举报

7

主题

16

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2018-1-20
在线时间
6 小时
 楼主| 发表于 2018-1-20 10:41:31 | 显示全部楼层
Noctis 发表于 2018-1-20 09:39
不要在中断里执行阻塞式的函数,你定时器设一个标记,到时间就将该标记置1,主循环检测到该标记为1再执行Ge ...

我看到论坛有用TIM的TRIGO或PWM触发,是不是目的也是定时ADC采样?刚接触这方面,小白一枚,谢谢。
回复

使用道具 举报

0

主题

88

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
361
金钱
361
注册时间
2016-11-1
在线时间
119 小时
发表于 2018-1-20 11:16:22 | 显示全部楼层
本帖最后由 Noctis 于 2018-1-20 11:34 编辑
练皮境 发表于 2018-1-20 10:39
首先谢谢解答!
1)如果不要在中断里执行阻塞式的函数,你定时器设一个标记,到时间就将该标记置1,主循 ...

第1种方法肯定有会有些延时,不过一般都不需要那么精确的时间吧。况且你就算在中断里获得了数据,但是你对该数据的处理难道不是放在主循环里吗?如果你对该数据的处理也是放在主循环里,那么不也相当于被主循环里的其它功能延时了吗
至于第2种,你是不是用了 HAL_ADC_Start_IT()还继续用HAL_ADC_PollForConversion()?
回复

使用道具 举报

7

主题

16

帖子

0

精华

新手上路

积分
47
金钱
47
注册时间
2018-1-20
在线时间
6 小时
 楼主| 发表于 2018-1-21 08:28:19 | 显示全部楼层
在中断里获得了数据,对该数据的处理可以不放在主循环。比如在中断里比较ADC值大小后,直接发送到外设
第2种,我试了用 HAL_ADC_Start_IT(),不用HAL_ADC_PollForConversion(),程序不卡死,但得到的ADC值怎么都是0。原因应该是上一次ADC采用一直没有完成。
回复

使用道具 举报

0

主题

88

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
361
金钱
361
注册时间
2016-11-1
在线时间
119 小时
发表于 2018-1-21 09:24:55 | 显示全部楼层
练皮境 发表于 2018-1-21 08:28
在中断里获得了数据,对该数据的处理可以不放在主循环。比如在中断里比较ADC值大小后,直接发送到外设
第2 ...

用了HAL_ADC_Start_IT就不需要用HAL_ADC_PollForConversion()的,自己看看源文件,开头的注释里有写用法的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-19 23:15

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表