MSP430提供了很好的低功耗能力,但是很多时候,一个外围电路就花费了很多额外的电力,造成低功耗无法彻底实现。
现在很多电子设备都是使用电子开关控制设备是否工作的,大多教材上都是使用IO中断来实现,并且占用两个IO口,一个是电源开关钮,另一个是用来控制电源的,通过电阻接一个三极管。
个人认为,对于MCU来说,节省IO口对功能实现很有意义,只有这样才能在有限的IO口上设计更多的功能,特别是像F20XX的那种只有10个IO的片子,更是如此。
所以我设计了一个利用NMI/RST来实现电源控制的方法。由于这个脚本来就是独立的,所以用它实现功能时就不会占用IO了。
要运行以下程序,只需要板子上有一个标准的带RESET钮的上电复位电路即可。
以下程序在MSP430F135上运行通过,原理简单,就不多说了,大家看程序:
#include "msp430x13x.h"
volatile unsigned short AFlag; // Active Flag
void main(void)
{
WDTCTL = WDTPW + WDTHOLD + WDTNMI; // Stop watchdog timer
P1DIR = 0xFF; // P1置为输出方式
P1OUT = 0xFF; // P1输出全置为1
P1SEL = 0x00; // P1上的复用功能全部关闭
//其它IO没有使用到的也要这样初始化,不用的IO电路上应该悬空,不要接地。
_EINT();
AFlag = 0;
IE1 |= NMIIE; // Enable WDT interrupt
while(1)
{
if(AFlag==1)
{
WDTCTL = WDTPW + WDTNMI + WDTTMSEL + WDTSSEL + WDTCNTCL; // Start watchdog timer
IE1 |= WDTIE; // Enable WDT interrupt
//这里写自己的程序,把程序做在一个有限的循环里,这样做完之后就可以自动结束并关机。
LPM3;
//如需定时,上边这个LPM3要被包括在那个有循环的循环体中,这样才能实现类似便携式仪表5分钟自动关机的效果。如果不使用定时也可以不要LPM3这句话。
WDTCTL = WDTPW + WDTHOLD + WDTNMI; // Stop watchdog timer
AFlag=0;
}
else
{
//如果周边设备在关机时有需要复位的或是关闭的在这里处理
}
LPM4;
}
}
#pragma vector=WDT_VECTOR //看门狗定时中断服务
__interrupt void wdt_timer(void)
{
LPM3_EXIT; // Cleat LPM3 bits from 0(SR)
}
#pragma vector=NMI_VECTOR //非屏蔽中断服务
__interrupt void nmi_button(void)
{
if(AFlag==1)
{
//AFlag=0;
WDTCTL = 0x5B00;
//以上两种写法都可以实现关机功能,但是第二个会引起复位,第一个不会,对要求现场一直保留的系统建议第一个语句写法。
}
else
{
AFlag=1;
}
IFG1 &= ~NMIIFG;
IE1 |= NMIIE;
LPM4_EXIT;
}
另外,如果希望保留复位功能的话,其实可以在标志为1时就把NMI还回RST的,这样按下去就复位,系统一启动就直接睡着,又会变成关机状态了,功能是一样的。不过这种方法不能保留现场了,所以我才写成现在的样子。
|