7364浏览
查看: 7364|回复: 5

如何点一盏LED灯

[复制链接]
本帖最后由 Holiday 于 2014-1-15 18:21 编辑

事情的起始原因是这样的,今天进窑洞搬砖,里面漆黑的一片,对搬砖进度造成了很大的阻挠,没得办法,就有人说,现在都高科技的天下了,于是就用Arduino点了一盏灯,
电路是这样的:如何点一盏LED灯图1

工友们表示智商上受不了打击,都抄起了身边的砖头走向那个受害者。。。合理的情绪宣泄过后,总会有人理智的提出,点灯应该是这样的:
  1. // Pin 13 has an LED connected on most Arduino boards.
  2. // give it a name:
  3. int led = 9;
  4. // the setup routine runs once when you press reset:
  5. void setup() {               
  6.   // initialize the digital pin as an output.
  7.   pinMode(led, OUTPUT);     
  8. }
  9. // the loop routine runs over and over again forever:
  10. void loop() {
  11.   digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  12.   delay(1000);               // wait for a second
  13. }
复制代码
如何点一盏LED灯图2
我满意地点了点头,正要表示赞扬,身边的工友抄起砖头走了过去。。。
工友回来了,呆着些许的遗憾,从他的眼神中我看出了他要表达的程序应该是这样的(电路图不做改动,1s的频率闪烁):
  1. #include <avr/io.h>
  2. #include <avr/interrupt.h>
  3. int led=9;
  4. volatile int state = LOW;
  5. void init_time()
  6. {
  7.   TCCR2A |= (1 <<WGM21) | (1 << WGM20);
  8.   TCCR2B |= (1 << CS22 );  //by clk/64
  9.   TCCR2B &= ~((1 <<CS21) | (1 <<CS20));  //by clk/64
  10.   TCCR2B &= ~((1 << WGM21 ) | (1 << WGM20));
  11.   ASSR |= ( 1 << AS2 );
  12.   TIMSK2 |= ( 1 << TOIE2 ) | ( 0 << OCIE2B );
  13.   TCNT2 = 6;
  14.   sei();
  15. }
  16. int count = 0;
  17. SIGNAL(TIMER2_OVF_vect)
  18. {
  19.   TCNT2 = 6;
  20.   ++count;
  21.   if( count == 1000 )
  22.   {
  23.     state=!state;
  24.     digitalWrite(led,state);
  25.     count=0;
  26.   }
  27. }
  28. /*
  29. */
  30. void setup(void)
  31. {
  32.   Serial.begin(115200);
  33.   init_time();
  34. }
  35. void loop( void )
  36. {
  37.   Serial.println("start ... ...");
  38.   while( 1 )
  39.   {
  40.     delay( 100 );
  41.   }
  42. }
复制代码
我被我这些神一样的砖友惊呆了,忍不住点下头来,还好窑洞比较黑,因为我发现对面的砖友手上拿着个砖头走了过来。。。

一会儿过后,他回到了原来的地方,从背影中我大概可以知道他的意思是没事你瞎闪个毛啊,从他的步伐中我看出了他的意见:
电路:如何点一盏LED灯图3
程序:
  1. #define LED 9
  2. volatile int state = LOW;
  3. void setup()
  4. {
  5.   pinMode(LED,OUTPUT);
  6.   attachInterrupt(0,led_function,CHANGE);
  7. }
  8. void loop()
  9. {
  10.   digitalWrite(LED,state);
  11. }
  12. void led_function()
  13. {
  14.   state =!state;
  15. }
复制代码
按键按下改变小灯亮暗。我这次收住了自己放荡不羁的性格,观察了下,心想要是点头了那还得了
本来事情就这么过去了,大家又可以一心一意搬砖了,可有人提出,两个中断的优先级问题,妹的我们是搬砖的好吧,别这么耽误生意好吧。。当然我是在心里这么想的,因为将这个想法说出来的人。。。哎,太暴力了。。
自古大神多搬砖,有人说了见解:AVR的中断有2种类型的,一种是设置标志位为"1"的可挂起中断,一种是不影响标志位的不可挂起中断.大部分的中断属于第一种形式的. >>在中断服务程序执行的时候又来一个中断请求........ AVR在进入响应中断过程中,由硬件自动将全局中断允许标志清另,因此在中断服务程序执行过程中是不会再响应其它的中断了,所以后来的中断不会不会马上得到响应. 根据后来中断类型的不同,后续的处理也不一样: 如果是第一类型的中断,它的中断标志已经为"1",尽管AVR没有马上响应,但标志位保持着,等代AVR的响应(称为中断挂起).当AVR从中断返回后,如果标志位没有被软件清除,在执行一条指令后,会响应该中断的(尽管中断产生条件已经过去了). 对于第二类型的中断(不设置标志位的),在AVR执行中断的过程中肯定不不会响应的.当AVR从中断返回后,如果该中断的产生条件还存在,那么AVR执行一条指令后,响应该中断;如果中断产生条件不成立了,AVR就不会响应了(丢失一次中断).
当MCU响应一个中断时,其硬件系统会自动中断返回地址压入系统堆栈,并将关闭全局中断响应(硬件将中断标志I位清0),清除该中断的中断标志位;执行中断返回指令RETI时,硬件会先允许全局中断响应(硬件将中断标志I位置1),然后从系统堆栈中弹出返回地址到PC程序计数器中,继续执行被中断打断的程序。除此之外,MCU的硬件没有对中断保护做其他处理。
我到现在还没明白这位大神为何也挨了群攻,虽然我手都打疼了。。。大概是大家觉得习惯了,就不管对错了。
几天过后一个人手持方天画戟,身披金色战甲,脚踏七彩祥云,在大家在搬另外一批次的砖的时候补充了些内容:
AVR中断嵌套处理是通过软件方式实现的。如在B中断服务中,如需要MCU能及时的响应A中断(不是等本次中断返回后再响应),B中断的服务程序应这样设计:(1)B中断的现场保护;(2)屏蔽除A以外其它的中断允许标志;(3)用指令SEI开放允许全局中断;(4)B中断服务;(5)用指令CLI禁止全局中断(6)恢复在本中断程序被屏蔽的中断允许标志;(7)B中断现场恢复;(8)B中断返回。 用户在编写中断处理服务程序中,应遵循中断服务程序尽量要短的原则
大家都表示了赞同,可是习惯不是那么容易改的。方天画戟?金色战甲?何其惧?
殊不知,砖头与秤砣并存绝世武器,或天外飞沙烧制而成,或上古玄铁铸造而成,算了就不吹牛了,城*管*使用的武器,战斗力不用说了。。。
如何点一盏LED灯图4


Phoebe  高级技匠

发表于 2014-1-15 10:17:44

挺有意思。。。
回复

使用道具 举报

Holiday  初级技匠
 楼主|

发表于 2014-1-15 11:11:34

Phoebe 发表于 2014-1-15 10:17
挺有意思。。。

辣是必须的
回复

使用道具 举报

nemon  中级技匠

发表于 2014-1-16 09:14:48

终于搞明白了……原来搬砖的典故是这么来的
回复

使用道具 举报

fangrong  中级技师

发表于 2014-11-18 20:55:51

那哭闹的娃,是楼主小时候吧~
回复

使用道具 举报

lisper  中级技匠 来自手机

发表于 2014-12-7 17:04:24

好强大~
回复

使用道具 举报

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

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail