求助AVR使用timer1的ISR程序,没效果-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2418|回复: 6

[已解决] 求助AVR使用timer1的ISR程序,没效果

[复制链接]
发表于 2020-9-9 10:52 | 显示全部楼层 |阅读模式
本帖最后由 glace12123 于 2020-9-9 11:49 编辑

pro mini或者uno板子,芯片是ATMega328P,小弟要输出周期可精确调整的脉冲,所以需要用到ISR函数来控制timer1,看网上大神写的程序,我仿照做了1个,在某个数字IO上输出方波,但可惜失败了。

我用delay()函数是没问题的,可惜delay函数精度不够。

所以求助大神,贴上源码,看看是否我的程序有问题,或者代码环境有问题,小弟先谢过。

  1. #define OUTPIN_led 13

  2. volatile boolean ledFlag = false;

  3. void Timer1Init()
  4. {
  5.   TCCR1A = 0;
  6.   TCNT1 = 0;
  7.   TCCR1B = 0;
  8.   TIMSK1 = (1<<OCIE1A);
  9.   OCR1A = 62500-1; // count for 1s
  10.   sei();  
  11. }

  12. void Timer1Start()
  13. {
  14.   TCCR1B = (1<<WGM12)|(1<<CS12)|(0<<CS11)|(0<<CS10);  // 16MHz/256 = 625000 Hz
  15. }

  16. void setup()
  17. {
  18.   // put your setup code here, to run once:
  19.   pinMode(OUTPIN_led, OUTPUT);
  20.   digitalWrite(OUTPIN_led,  LOW);
  21.   Timer1Init();
  22. }

  23. void loop()
  24. {
  25.   // put your main code here, to run repeatedly:
  26.   Timer1Start();
  27. }

  28. ISR(TIMER1_COMPA_vect)
  29. {
  30.   digitalWrite(OUTPIN_led,  ledFlag);
  31.   ledFlag = ~ledFlag;
  32. }
复制代码

 楼主| 发表于 2020-9-9 10:55 | 显示全部楼层
本帖最后由 glace12123 于 2020-9-9 10:58 编辑

简单描述一下问题,上述代码,貌似只了ISR(),LED由灭变亮,然后就维持常亮了,感觉后面timer1没有再工作了,不知道是何问题。
 楼主| 发表于 2020-9-9 11:04 | 显示全部楼层
顺便再问下,这种嵌套gcc-avr编程方式的,需不需要引用什么h文件啊?
 楼主| 发表于 2020-9-9 12:10 | 显示全部楼层
本帖最后由 glace12123 于 2020-9-9 12:17 编辑

问题解决了,但我觉得很奇怪,我AVR IO寄存器PORTB去直接操作IO,替代digitalWrite()函数,灯就成功闪起来了,好奇怪啊,digitalWrite函数用在ISR里有什么问题吗?还是说,ledFlag这个boolean型变量,在ISR有什么问题?

  1. ISR(TIMER1_COMPA_vect)
  2. {
  3.   
  4.   //digitalWrite(OUTPIN_led,  ledFlag);
  5.   PORTB ^= (1<<PB5);
  6.   ledFlag = ~ledFlag;
  7. }
复制代码

 楼主| 发表于 2020-9-9 12:19 | 显示全部楼层
事实证明,是ledFlag这个全局变量没能成功取反,如下代码,和之前错误的情况一样,维持常亮。
  1. ISR(TIMER1_COMPA_vect)
  2. {
  3.   if(ledFlag == true)
  4.   {
  5.     PORTB = (1<<PB5);
  6.   }
  7.   else
  8.   {
  9.     PORTB = (0<<PB5);
  10.   }
  11.   
  12.   //digitalWrite(OUTPIN_led,  ledFlag);
  13.   //PORTB ^= (1<<PB5);
  14.   ledFlag = ~ledFlag;
  15. }
复制代码
发表于 2020-9-9 12:26 | 显示全部楼层
你一直start当然不行。。。。
 楼主| 发表于 2020-9-9 12:44 | 显示全部楼层
终于找到原因了,为什么ledFlag没在ISR里被正常取反。
我之前认为既然boolean可以当做0/1一样的bit直接写给某个port,那么它可以用“位取反(bitwise not)”的方式来进行取反操作,然而不是,boolean型变量只能进行“逻辑取反(logic not)”,才能被正常取反,看下面代码,2种取反,被注释的就是错误的位取反。

  1. ISR(TIMER1_COMPA_vect)
  2. {  
  3.   digitalWrite(OUTPIN_led,  ledFlag);
  4.   ledFlag = !ledFlag;   // logic not
  5.   //ledFlag = ~ledFlag; // bitwise not
  6. }
复制代码


这也许就涉及到计算机变量类型的知识了,我不太懂,我是做FPGA的,想当然就把bool等于成bit了。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-30 01:50 , Processed in 0.079292 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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