我居然没有找到Atmega328p的中文资料,这让我做每个实验都要自己去查下英文资料,比较麻烦。这里再多费话一句,为什么我要用Atmega328p做实验,因为这是arduino uno的mcu,代码可以直接移植到arduino上去。在做了arduino实验后,再看看Atmega328p数据手册、avr单片机、电路原理图,可以从底层深刻理解程序。真希望有更多的同学一起来追问和回答这些底层技术问题。好了,废话完毕,开始讲中断。
我用的参考书是《AVR单片机入门与速成攻略》这本书,这是一本入门的好书,可惜的是书中代码不是基于Atmega328p(arduino)的。但基本思想可以从这里学得,再结合Atmel官方数据手册,就可以做实验了。有需要完整源码的同学请联系我。
中断的概念很简单,比如:我一直在写程序,突然手机响了,我拿起手机看一下,完事继续写程序。那么在程序中如何体现呢?假如主程序是while(true){dosomething...},我想要中断一下它,让它干点别的事,这就可以用中断来处理。Java中没有中断,不过可以用多线程,另一线程来设置标识的方法来解决。而在avr中,就不需那么麻烦,直接操作几个寄存器就能实现。看代码:
这是前面的声明与主函数,nixieVal是数码管的0-3的四个值。主函数中前面还是DDR寄存器的设置,int0_init是设置寄存器使能中断。这个函数代码《AVR单片机入门与速成攻略》不一样,我是从数据手册里找到正确的设置方法的,不知有没有更方便的办法。如下图:
Atmega328p里有四个寄存器需要设置:
1.SREG 状态寄存器(全局使能)
2.EIMSK 外部中断掩码寄存器(External Interrupt Mask Register)
3.MCUCR MCU控制寄存器
4.EICRA 外部中断控制寄存器(External Interrupt Control Register A)
我也不知道为什么要设置4个才能打开中断,但人家Atmel就这么规定了,不这么玩就打不开人家的硬件。
中断函数也是有固定格式的,我们用的INT0这个引脚,所以函数名里有INT0,如下:
数码管显示函数(display)在上文已经介绍过,这里就不重复了。看一下我们要连接的硬件引脚图:
比较简单,只需一根线。操作与EICRA设置有关,如下图:
然后我们插拔一次,去观察数码管的变化。发现一个问题,并不是插拔一次变化一次,有时候变化一次,有时候变化两次,有时候变化3次。我们怎么让它有规则的变化?这就引出了第二个知识,软件中断,我们还是以上面的代码为基础做一些修改,让软件自动的改变数码管(INPUTNUM)。
先把声明一个全局int变量n,然后在显示的时候对INT0(PD2)这个引脚切换1和0的取值,1秒钟切换1次,如下代码:
好了,我们通过这个代码测试出来软件中断的方法。同时这不就是定时器的效果么?之后我再学习定时器来看看这个与定时器有什么区别。实物图: