单片机用P1.3控制LED灯闪烁
msp430G2553概述
概述各功能模块
1.在MSP430单片机单片机共有三个或四个时钟源:
-LFXT1CLK: 低频/高频时钟源.由外接晶体振荡器,而无需外接两个振荡电容器,常使用的晶-体振荡器是32768HZ。也可以接(400kHz~16Mhz)
-XT2CLK: 高频时钟源.由外接晶体振荡器。需要外接两个振荡电容器,较常的晶体振荡器-是 8MHZ。也可以接(400kHz~16Mhz)
-DCOCLK: 数控振荡器,为内部晶振,由RC震荡回路构成。
-VLOCLK: 内部低频振荡器,12kHz标准振荡器。
2.MCU内需要时钟的单元包括CPU和部分片内外设,三种时钟的功能区别如下:
-MCLK:主时钟(Main system Clock),专为CPU运行提供的时钟。MCLK频率配置的越高,CPU执行的速度越快。虽然CPU速度越快功耗也越高,但高频率的MCLK可以让CPU工作时间更短。所以正确的低功耗设计并不是要尽量降低MCLK,而是在不用CPU时立刻关闭MCLK。在大部分应用中,需要CPU运算的时间都非常短,所以,间歇开启MCLK(唤醒CPU)的方法节能效果非常明显。
-SMCLK:子系统时钟(Sub-main Clock),专为一些需要高速时钟的片内外设提供服务,比如定时器和ADC采样等。当CPU休眠时,只要SMCLK开启,定时器和ADC仍可工作(一般待片内外设完成工作后触发中断,唤醒CPU去做后续工作)。
-ACLK:辅助时钟(Auxillary Clock),辅助时钟的频率很低,所以即使一直开启功耗也不大,当然关掉也是可以的。辅助时钟可以供给那些只需低频时钟的片内外设,比如LCD控制器,还可用于产生节拍时基,与定时器配合间歇唤醒CPU。
3.MSP430 具有一种运行模式及5 种可利用软件来选择的低功耗操作模式。一个中断事件能够将器件从任一低功耗模式唤醒、处理请求、并在接收到来自中断程序的返回信号时恢复至低功耗模式或被激活。
代码参考:
/* * Key_LED_Change_DCO.c * 硬件描述:Launchpad G2553开发板上P1.3接了一个按键,P1.0接了LED(用跳线帽连接)。 * 功能描述:LED依靠长延时闪烁,每次按下按键后,系统时钟按1/8/12/16MHz循环改变,LED闪烁速度变化 */ #include "MSP430G2553.h" //-----在main()函数前提前申明子函数----- void P1_IODect(); //P1口的外部中断事件检测函数 void P13_Onclick(); //P1.3按键的中断事件处理函数 void GPIO_Init(); //GPIO初始化函数 void main(void) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗定时器 GPIO_Init(); //初始化GPIO _enable_interrupts(); //等同_EINT,使能总中断 } /****************************************************************************************************** * 名 称:GPIO_Init() * 功 能:设定按键和LED控制IO的方向,启用按键IO的上拉电阻 * 入口参数:无 * 出口参数:无 * 说 明:无 * 范 例:无 ******************************************************************************************************/ void GPIO_Init() { //-----设定P1.0和P1.6的输出初始值----- P1DIR |= BIT0+BIT6; //设定P1.0为输出 P1OUT &= ~BIT0+BIT6; //设定P1.0初值 //-----配合机械按键,启用内部上拉电阻----- P1REN |= BIT3; //启用P1.3内部上下拉电阻 P1OUT |= BIT3; //将电阻设置为上拉 //-----配置P1.3中断参数----- P1DIR &= ~BIT3; // P1.3设为输入(可省略) P1IES |= BIT3; // P1.3设为下降沿中断 P1IE |= BIT3 ; // 允许P1.3中断 } /****************************************************************************************************** * 名 称:PORT1_ISR() * 功 能:响应P1口的外部中断服务 * 入口参数:无 * 出口参数:无 * 说 明:P1.0~P1.8共用了PORT1中断,所以在PORT1_ISR()中必须查询标志位P1IFG才能知道 * 具体是哪个IO引发了外部中断。P1IFG必须手动清除,否则将持续引发PORT1中断。 * 范 例:无 ******************************************************************************************************/ #pragma vector = PORT1_VECTOR __interrupt void PORT1_ISR(void) { //-----启用Port1事件检测函数----- P1_IODect(); //检测通过,则会调用事件处理函数 P1IFG=0; //退出中断前必须手动清除IO口中断标志 } /****************************************************************************************************** * 名 称:P1_IODect() * 功 能:判断具体引发中断的IO,并调用相应IO的中断事件处理函数 * 入口参数:无 * 出口参数:无 * 说 明:该函数兼容所有8个IO的检测,请根据实际输入IO激活“检测代码”。 * 本例中,仅有P1.3被用作输入IO,所以其他7个IO的“检测代码”没有被“激活”。 * 范 例:无 ******************************************************************************************************/ void P1_IODect() { unsigned int Push_Key=0; //-----排除输出IO的干扰后,锁定唯一被触发的中断标志位----- Push_Key=P1IFG&(~P1DIR); //-----延时一段时间,避开机械抖动区域----- __delay_cycles(10000); //消抖延时 //----判断按键状态是否与延时前一致----- if((P1IN&Push_Key)==0) //如果该次按键确实有效 { //----判断具体哪个IO被按下,调用该IO的事件处理函数----- switch(Push_Key){ // case BIT0: P10_Onclick(); break; // case BIT1: P11_Onclick(); break; // case BIT2: P12_Onclick(); break; case BIT3: P13_Onclick(); break; // case BIT4: P14_Onclick(); break; // case BIT5: P15_Onclick(); break; // case BIT6: P16_Onclick(); break; // case BIT7: P17_Onclick(); break; default: break; //任何情况下均加上default } } } /****************************************************************************************************** * 名 称:P13_Onclick() * 功 能:P1.3的中断事件处理函数,即当P1.3键被按下后,下一步干什么 * 入口参数:无 * 出口参数:无 * 说 明:使用事件处理函数的形式,可以增强代码的移植性和可读性 * 范 例:无 ******************************************************************************************************/ void P13_Onclick() { //-----Freq仅在P13_Onclick()中使用,但是又需要退出函数时不被清除----- static unsigned int Freq=0; // 静态全局变量的典型应用场合 //-----变量从0~3循环移位----- Freq++; if (Freq>3) Freq=0; //-----根据Freq的值,改变DCO设定频率----- switch(Freq){ case 0: DCOCTL = CALDCO_1MHZ; BCSCTL1 = CALBC1_1MHZ; break; //case 1: DCOCTL = CALDCO_8MHZ; BCSCTL1 = CALBC1_8MHZ; break; //case 2: DCOCTL = CALDCO_12MHZ; BCSCTL1 = CALBC1_12MHZ; break; //case 3: DCOCTL = CALDCO_16MHZ; BCSCTL1 = CALBC1_16MHZ; break; default: break; } while(1) { if((P1IN&BIT3)==0) //按键按下 { P1OUT ^=BIT0; //异或,即使LED1由亮变灭,由灭变亮 __delay_cycles(100000); //延时0.1秒 P1OUT ^=BIT0; __delay_cycles(900000); //延时0.9秒 } } }