11363|31

186

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

想问一个关于定时器控制AD采样的问题~ [复制链接]

想写一个程序,用定时器控制AD采样的采样率,想法是这样的:



设置AD,最后在AD中断里面将ADC12MEM的数据赋给result



然后配置定时器,定时器时间设为5ms 进中断 进中断后将result的值提取 处理 最后通过串口输出~



这样的话其实就是5ms得到一次采样点,所以得到的采样率应该是5ms一个采样点,即200Hz



问题:

1.这样的方法可行吗???

2.这两个中断的地方怎么写(不是中断里面的内容)??有个什么顺序神马的没有?

最新回复

ADC12CTL0|=ADC12SC; result=ADC10MEM0; LPM4; 上面这三句,第一句说的是开启ADC转换,也就是这个时候开始让ADC模块开始采样。 第二句,直接读取,由于ADC采样是需要时间的,所以你这个时候读出来的数据是不可靠的。 第三句,进入低功耗模式,这个时候数据已经读出来了,再进低功耗模式已经没用了。 下面这个链接是我之前写的ADC读取语句,你可以参考一下(读Vcc电压): https://bbs.eeworld.com.cn/forum. ... 6450&fromuid=354619 补充一下宏定义和中断服务。 其中flag是全局变量,作用是将其的8个bit分别作为8个标志位使用。 在这里可以不使用这个标志位。 我这么写的原因是我的程序架构比较混乱,唤醒MCU的中断源可能有好几个,不加的话在执行过程中容易出错。 #define ADC_Interrupt flag&0x04 #define Set_ADC_Interrupt flag|=0x04 #define Reset_ADC_Interrupt flag&=0xFB __interrupt void ADC10_ISR (void) {         Set_ADC_Interrupt;         LPM3_EXIT;     // Clear LPM3 bits from 0(SR) }   详情 回复 发表于 2015-5-18 23:17
 
点赞 关注

回复
举报

323

帖子

2

TA的资源

一粒金砂(高级)

推荐
 
楼主直接将ADC的触发源改为定时器即可,只要ADC中断,定时器不用开中断,只要每5ms给一个触发信号就行,在ADC中断里调用串口,把数据送出去

点评

有些430的没有定时器触发的,我看过msp430f5529就没有  详情 回复 发表于 2015-5-14 00:49
 
 

回复

2549

帖子

0

TA的资源

五彩晶圆(初级)

沙发
 
1:你的意思就是AD的中断负责采集数据,然后定时器每5ms取一次数,然后进行处理。
这样的话其实就是5ms得到一次采样点,所以得到的采样率应该是5ms一个采样点,即200Hz)我觉得这话有歧义,实际采样率到底是多少是以你的AD决定的吧,怎么能以你读的时间来衡量呢。。。。。
2:你的思路已经很清楚了,直接把两个中断打开就行了啊,先后顺序没有多大影响,5ms肯定采了好N多次数了,先开哪个都没啥区别

点评

我感觉 定时器的中断并没有按照定时器设定的时间进入中断,而是直接在执行完AD的中断后 就直接进入了定时器中断。。。。。。。  详情 回复 发表于 2015-5-12 16:15
非常感谢你的回复 我按照这个思路写了下程序 先初始化AD 然后UART 然后timer 然后__bis_SR_register(LPM0_bits+GIE);进入中断。 然后我写了AD中断,把ADC12MEM0的值赋给temp 然后写了定时器中断 把tem  详情 回复 发表于 2015-5-12 16:08
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

板凳
 
数码小叶 发表于 2015-5-12 14:59
1:你的意思就是AD的中断负责采集数据,然后定时器每5ms取一次数,然后进行处理。
(这样的话其实就是5ms得到一次采样点,所以得到的采样率应该是5ms一个采样点,即200Hz)我觉得这话有歧义,实际采样率到底是多少是以你的AD决定的吧,怎么能以你读的时间来衡量呢。。。。。
2:你的思路已经很清楚了,直接把两个中断打开就行了啊,先后顺序没有多大影响,5ms肯定采了好N多次数了,先开哪个都没啥区别

非常感谢你的回复
我按照这个思路写了下程序

先初始化AD 然后UART 然后timer

然后__bis_SR_register(LPM0_bits+GIE);进入中断。

然后我写了AD中断,把ADC12MEM0的值赋给temp

然后写了定时器中断 把temp转换后输出到电脑



具体代码如下:





  1. #include <msp430f5529.h>
  2. #include "ADfunction.h"
  3. #include "uart.h"
  4. #include "timer.h"

  5. typedef unsigned int uint;
  6. typedef unsigned char uchar;

  7. //volatile unsigned int results[num_of_results];                      //开辟8个16位内存空间
  8. //static uchar index = 0;;
  9. uint temp;
  10. uchar result;
  11. //uint average;
  12. char buffer1[6];


  13. void main( void )
  14. {

  15.   // Stop watchdog timer to prevent time out reset
  16.   WDTCTL = WDTPW + WDTHOLD;                                         //关闭看门狗
  17.   Init_ADC();
  18.   uart_init();
  19.   timer();
  20.   buffer1[5]='\0';
  21.   
  22.   __bis_SR_register(LPM0_bits + GIE);
  23. }
  24. #pragma vector = ADC12_VECTOR
  25. __interrupt void ADC12ISR (void)
  26. {
  27.   switch(__even_in_range(ADC12IV,34))
  28.   {

  29.   case 0 : break;
  30.   case 2 : break;
  31.   case 4 : break;
  32.   case 6 :   
  33.    

  34.     temp = ADC12MEM0;

  35.       break;
  36.   case 8  :break;

  37.   default : break;
  38.   }
  39. }

  40. #pragma vector=TIMER0_A0_VECTOR
  41. __interrupt void TIMER0_A0_ISR(void)
  42. {

  43.   
  44.   result= temp;
  45.     uchar i;     
  46.   Tran_val(temp,buffer1);
  47.         buffer1[4] = buffer1[3];
  48.         buffer1[3] = buffer1[2];
  49.         buffer1[2] = buffer1[1];
  50.         buffer1[1] = 0x2e - 0x30;
  51.        for(i=0;i<4;i++)
  52.        {
  53.          buffer1[i] += 0x30;
  54.        }
  55.   
  56.       
  57.      uart_tx_string(buffer1);
  58.      uart_tx_string("\r");
  59. }
  60.       
  61.    
复制代码




然后我给了个1Hz的正弦波 发现一个正弦波输出了几千个点额。。。。。。不对额。。。。。。。








点评

1000/5,应该有200个点啊  详情 回复 发表于 2015-5-12 19:01
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

4
 
数码小叶 发表于 2015-5-12 14:59
1:你的意思就是AD的中断负责采集数据,然后定时器每5ms取一次数,然后进行处理。
(这样的话其实就是5ms得到一次采样点,所以得到的采样率应该是5ms一个采样点,即200Hz)我觉得这话有歧义,实际采样率到底是多少是以你的AD决定的吧,怎么能以你读的时间来衡量呢。。。。。
2:你的思路已经很清楚了,直接把两个中断打开就行了啊,先后顺序没有多大影响,5ms肯定采了好N多次数了,先开哪个都没啥区别

我感觉 定时器的中断并没有按照定时器设定的时间进入中断,而是直接在执行完AD的中断后 就直接进入了定时器中断。。。。。。。

点评

没看出来你的定时器达到5ms了啊,初始化里达不到吧,最大才到65536而已  详情 回复 发表于 2015-5-12 19:08
 
 
 

回复

2549

帖子

0

TA的资源

五彩晶圆(初级)

6
 
Ben讨厌苦咖啡 发表于 2015-5-12 16:08
非常感谢你的回复
我按照这个思路写了下程序

先初始化AD 然后UART 然后timer

然后__bis_SR_register(LPM0_bits+GIE);进入中断。

然后我写了AD中断,把ADC12MEM0的值赋给temp

然后写了定时器中断 把temp转换后输出到电脑



具体代码如下:








然后我给了个1Hz的正弦波 发现一个正弦波输出了几千个点额。。。。。。不对额。。。。。。。

1000/5,应该有200个点啊
 
 
 

回复

2549

帖子

0

TA的资源

五彩晶圆(初级)

7
 
Ben讨厌苦咖啡 发表于 2015-5-12 16:15
我感觉 定时器的中断并没有按照定时器设定的时间进入中断,而是直接在执行完AD的中断后 就直接进入了定时器中断。。。。。。。

没看出来你的定时器达到5ms了啊,初始化里达不到吧,最大才到65536而已

点评

啊啊啊!!!!我明白了 是因为定时器定了5ms才进入定时器中断,然后当到了5ms的时候才进入定时器中断 对吧?所以,在这5ms之内就要一直在AD中断里面了~哈~~~  详情 回复 发表于 2015-5-13 15:11
用信号源试了下 已经实现了每秒取200个点 然后上传到上位机。 但是现在有个问题 就是我在main里面 写了两个中断,先写了AD中断,又写了定时器中断。 然后debug 让程序一直跑的时候输出的结果没问题,  详情 回复 发表于 2015-5-13 15:02
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

8
 
数码小叶 发表于 2015-5-12 19:08
没看出来你的定时器达到5ms了啊,初始化里达不到吧,最大才到65536而已

用信号源试了下 已经实现了每秒取200个点 然后上传到上位机。

但是现在有个问题

就是我在main里面

写了两个中断,先写了AD中断,又写了定时器中断。

然后debug

让程序一直跑的时候输出的结果没问题,可是我单步调试的时候 就一直在AD中断里面一直循环,求问一下这是什么情况呀??

因为这个只是个简单的程序,后面我还要在这个基础上改好多东西,加好多东西,所以想搞清楚,请问下~非常感谢!
  1. #include <msp430f5529.h>
  2. #include "ADfunction.h"
  3. #include "uart.h"
  4. #include "timer.h"

  5. typedef unsigned int uint;
  6. typedef unsigned char uchar;

  7. //volatile unsigned int results[num_of_results];                      //开辟8个16位内存空间
  8. //static uchar index = 0;;
  9. uint temp;
  10. uchar result;
  11. //uint average;
  12. char buffer1[6];


  13. void main( void )
  14. {

  15.   // Stop watchdog timer to prevent time out reset
  16.   WDTCTL = WDTPW + WDTHOLD;                                         //关闭看门狗
  17.   Init_ADC();
  18.   uart_init();
  19.   timer();
  20.   buffer1[5]='\0';
  21.   
  22.   __bis_SR_register(LPM0_bits + GIE);
  23. }
  24. #pragma vector = ADC12_VECTOR
  25. __interrupt void ADC12ISR (void)
  26. {
  27.   switch(__even_in_range(ADC12IV,34))
  28.   {

  29.   case 0 : break;
  30.   case 2 : break;
  31.   case 4 : break;
  32.   case 6 :   
  33.    

  34.     temp = ADC12MEM0;

  35.       break;
  36.   case 8  :break;

  37.   default : break;
  38.   }
  39. }

  40. #pragma vector=TIMER0_A0_VECTOR
  41. __interrupt void TIMER0_A0_ISR(void)
  42. {

  43.   
  44.     uchar i;     
  45.   Tran_val(temp,buffer1);
  46.         buffer1[4] = buffer1[3];
  47.         buffer1[3] = buffer1[2];
  48.         buffer1[2] = buffer1[1];
  49.         buffer1[1] = 0x2e - 0x30;
  50.        for(i=0;i<4;i++)
  51.        {
  52.          buffer1[i] += 0x30;
  53.        }
  54.   
  55.       
  56.      uart_tx_string(buffer1);
  57.      uart_tx_string("\r");
  58. }
  59.       
  60.    
复制代码

点评

没看到你的主循环的,也没看到唤醒语句的。 所以MCU进入休眠之后只在中断到来的时候唤醒,处理完中断服务之后继续休眠。 其实你完全可以把程序放在主循环里来做,不过你这样就要大改程序架构了。  详情 回复 发表于 2015-5-13 16:40
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

9
 
数码小叶 发表于 2015-5-12 19:08
没看出来你的定时器达到5ms了啊,初始化里达不到吧,最大才到65536而已

啊啊啊!!!!我明白了 是因为定时器定了5ms才进入定时器中断,然后当到了5ms的时候才进入定时器中断 对吧?所以,在这5ms之内就要一直在AD中断里面了~哈~~~

点评

好吧,你明白就行了,虽然我不懂你在那说啥  详情 回复 发表于 2015-5-13 16:04
 
 
 

回复

2549

帖子

0

TA的资源

五彩晶圆(初级)

10
 
Ben讨厌苦咖啡 发表于 2015-5-13 15:11
啊啊啊!!!!我明白了 是因为定时器定了5ms才进入定时器中断,然后当到了5ms的时候才进入定时器中断 对吧?所以,在这5ms之内就要一直在AD中断里面了~哈~~~

好吧,你明白就行了,虽然我不懂你在那说啥
 
 
 

回复

1193

帖子

0

TA的资源

纯净的硅(高级)

11
 
Ben讨厌苦咖啡 发表于 2015-5-13 15:02
用信号源试了下 已经实现了每秒取200个点 然后上传到上位机。

但是现在有个问题

就是我在main里面

写了两个中断,先写了AD中断,又写了定时器中断。

然后debug

让程序一直跑的时候输出的结果没问题,可是我单步调试的时候 就一直在AD中断里面一直循环,求问一下这是什么情况呀??

因为这个只是个简单的程序,后面我还要在这个基础上改好多东西,加好多东西,所以想搞清楚,请问下~非常感谢!

没看到你的主循环的,也没看到唤醒语句的。
所以MCU进入休眠之后只在中断到来的时候唤醒,处理完中断服务之后继续休眠。


其实你完全可以把程序放在主循环里来做,不过你这样就要大改程序架构了。





初始化();

while(1)

{

休眠();

开始ADC转换();

休眠();

处理数据、外发数据();

}




ADC中断服务()

{

唤醒单片机();

}




定时器中断服务()

{

唤醒单片机();

}

点评

还有想弱弱的问问版主大人,你说的休眠 是让单片机进入某个低功耗模式吗??  详情 回复 发表于 2015-5-14 09:39
我总感觉我的程序不对 而且确实我也奇怪为什么不用一个while(1) 可是我就直接写了两个中断程序就一直在进中断执行,出来后继续进中断。。。。。。继续执行,这个地方我也有点迷惑~~~  详情 回复 发表于 2015-5-13 18:18
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

12
 
qiushenghua 发表于 2015-5-13 16:40
没看到你的主循环的,也没看到唤醒语句的。
所以MCU进入休眠之后只在中断到来的时候唤醒,处理完中断服务之后继续休眠。


其实你完全可以把程序放在主循环里来做,不过你这样就要大改程序架构了。





初始化();

while(1)

{

休眠();

开始ADC转换();

休眠();

处理数据、外发数据();

}




ADC中断服务()

{

唤醒单片机();

}




定时器中断服务()

{

唤醒单片机();

}

我总感觉我的程序不对

而且确实我也奇怪为什么不用一个while(1)

可是我就直接写了两个中断程序就一直在进中断执行,出来后继续进中断。。。。。。继续执行,这个地方我也有点迷惑~~~
 
 
 

回复

1291

帖子

0

TA的资源

纯净的硅(中级)

13
 
snoweaglemcu 发表于 2015-5-12 18:27
楼主直接将ADC的触发源改为定时器即可,只要ADC中断,定时器不用开中断,只要每5ms给一个触发信号就行,在ADC中断里调用串口,把数据送出去

有些430的没有定时器触发的,我看过msp430f5529就没有
 
 
 

回复

1291

帖子

0

TA的资源

纯净的硅(中级)

14
 
就按照qiushenghua版主的就可以了,我现在的程序全都跑定时器中断的,具体就是把你任务分成几个,然后定时某个时间进定时器中断,我一般是1ms,然后任务都在定时器跑,主函数while基本不跑什么代码,基本上都是跑些发送数据这类的任务

点评

不推荐在定时器中断服务里跑任务,因为中断不可嵌套,在中断服务里太久会影响程序的正常运行。 所以建议将程序放回主循环中,中断服务的作用仅仅是唤醒MCU,或者进行标志位的设定。 然后主循环里根据这些标志  详情 回复 发表于 2015-5-14 08:31
 
 
 

回复

1193

帖子

0

TA的资源

纯净的硅(高级)

15
 
强仔00001 发表于 2015-5-14 00:53
就按照qiushenghua版主的就可以了,我现在的程序全都跑定时器中断的,具体就是把你任务分成几个,然后定时某个时间进定时器中断,我一般是1ms,然后任务都在定时器跑,主函数while基本不跑什么代码,基本上都是跑些发送数据这类的任务

不推荐在定时器中断服务里跑任务,因为中断不可嵌套,在中断服务里太久会影响程序的正常运行。

所以建议将程序放回主循环中,中断服务的作用仅仅是唤醒MCU,或者进行标志位的设定。

然后主循环里根据这些标志位的组合来完成某些功能。




楼主的程序属于特例,因为他的程序太简单了,两个服务就能完成所有任务。


其实很多低端MCU能完成的工作,就因为程序架构设计不当,最终总感觉资源不够用,被迫更换了高端的MCU。



点评

这个我知道,我也是在中断进行简单的任务而已,或者我的任务在中断时间内就可以,不过还是用标志位传递到主函数的好  详情 回复 发表于 2015-5-14 10:10
版主大人说得有道理啊~我现在就发现可能因为程序框架不对 导致现在执行程序感觉资源不够啊~虽然程序简单,但感觉都不够~ 写程序还有好长的路要走啊~  详情 回复 发表于 2015-5-14 09:35
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

16
 
qiushenghua 发表于 2015-5-14 08:31
不推荐在定时器中断服务里跑任务,因为中断不可嵌套,在中断服务里太久会影响程序的正常运行。

所以建议将程序放回主循环中,中断服务的作用仅仅是唤醒MCU,或者进行标志位的设定。

然后主循环里根据这些标志位的组合来完成某些功能。




楼主的程序属于特例,因为他的程序太简单了,两个服务就能完成所有任务。


其实很多低端MCU能完成的工作,就因为程序架构设计不当,最终总感觉资源不够用,被迫更换了高端的MCU。

版主大人说得有道理啊~我现在就发现可能因为程序框架不对 导致现在执行程序感觉资源不够啊~虽然程序简单,但感觉都不够~
写程序还有好长的路要走啊~
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

17
 
qiushenghua 发表于 2015-5-13 16:40
没看到你的主循环的,也没看到唤醒语句的。
所以MCU进入休眠之后只在中断到来的时候唤醒,处理完中断服务之后继续休眠。


其实你完全可以把程序放在主循环里来做,不过你这样就要大改程序架构了。





初始化();

while(1)

{

休眠();

开始ADC转换();

休眠();

处理数据、外发数据();

}




ADC中断服务()

{

唤醒单片机();

}




定时器中断服务()

{

唤醒单片机();

}

还有想弱弱的问问版主大人,你说的休眠 是让单片机进入某个低功耗模式吗??

点评

是这个意思,关掉CPU,程序就卡在那里了,直到进入中断服务将其唤醒。唤醒之后正好接着做下一件事情。 如果有多件事情混着做,设置好标志位,每个循环将所有事情都做一遍,符合标志位再做,循环结束休眠。 中  详情 回复 发表于 2015-5-14 09:57
 
 
 

回复

1193

帖子

0

TA的资源

纯净的硅(高级)

18
 
Ben讨厌苦咖啡 发表于 2015-5-14 09:39
还有想弱弱的问问版主大人,你说的休眠 是让单片机进入某个低功耗模式吗??

是这个意思,关掉CPU,程序就卡在那里了,直到进入中断服务将其唤醒。唤醒之后正好接着做下一件事情。

如果有多件事情混着做,设置好标志位,每个循环将所有事情都做一遍,符合标志位再做,循环结束休眠。

中断服务在唤醒单片机之前将标志位置位了,这样就能混着执行服务了。

当然,休眠之前需要先判断是否所有标志位的程序都已经执行完毕,不然可能会出现冲突。

点评

想再弱弱地问一下 版主 唤醒单片机。。。。。。这个。。。。。。怎么唤醒啊? 版主的意思是 比如我让单片机进入低功耗模式4,然后唤醒的时候执行个语句进入低功耗模式0 这样 好几个时钟就工作了 就是唤  详情 回复 发表于 2015-5-15 09:41
 
 
 

回复

1291

帖子

0

TA的资源

纯净的硅(中级)

19
 
qiushenghua 发表于 2015-5-14 08:31
不推荐在定时器中断服务里跑任务,因为中断不可嵌套,在中断服务里太久会影响程序的正常运行。

所以建议将程序放回主循环中,中断服务的作用仅仅是唤醒MCU,或者进行标志位的设定。

然后主循环里根据这些标志位的组合来完成某些功能。




楼主的程序属于特例,因为他的程序太简单了,两个服务就能完成所有任务。


其实很多低端MCU能完成的工作,就因为程序架构设计不当,最终总感觉资源不够用,被迫更换了高端的MCU。

这个我知道,我也是在中断进行简单的任务而已,或者我的任务在中断时间内就可以,不过还是用标志位传递到主函数的好
 
 
 

回复

186

帖子

0

TA的资源

一粒金砂(中级)

20
 
qiushenghua 发表于 2015-5-14 09:57
是这个意思,关掉CPU,程序就卡在那里了,直到进入中断服务将其唤醒。唤醒之后正好接着做下一件事情。

如果有多件事情混着做,设置好标志位,每个循环将所有事情都做一遍,符合标志位再做,循环结束休眠。

中断服务在唤醒单片机之前将标志位置位了,这样就能混着执行服务了。

当然,休眠之前需要先判断是否所有标志位的程序都已经执行完毕,不然可能会出现冲突。

想再弱弱地问一下 版主 唤醒单片机。。。。。。这个。。。。。。怎么唤醒啊?



版主的意思是 比如我让单片机进入低功耗模式4,然后唤醒的时候执行个语句进入低功耗模式0 这样 好几个时钟就工作了 就是唤醒了吗??
 
 
 

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

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/8 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表