MSP430FR5969官方例程详解——msp430fr59xx_lpm3_03.c

文章详细解析了如何在MSP430FR59xx微控制器中配置LFXT1低频晶振作为ACLK时钟源进入LPM3低功耗模式,并讨论了LFXT1与VLOCLK的权衡。同时,介绍了中断服务程序的概念,特别是WDT_ISR的定义及其在中断处理中的角色,强调中断是由硬件触发,而非软件调用。
摘要由CSDN通过智能技术生成

废话就不多说啦,上篇文章里已经解释了为什么LPM3模式会有两个官方例程了,这次详解的这个例程是使用(外部)低频晶振LFXT1作为辅助时钟ACLK的时钟源,具体参数配置可以参考例程内容,上篇文章也详细分析了LFXT和VLOCLK的区别和具体使用场景,需要高精度和高稳定的自然就是LFXT,但会增加使用空间和功耗需要低功耗的自然就是VLOCLK,但稳定性和精度会下降;估计我后面会好好研究使用VLOCLK的,因为主要方向还是低功耗。废话就不多说了,直接上代码:

//******************************************************************************
//   MSP430FR59xx Demo - 进入LPM3模式(设置ACLK = LFXT1)
//
//   描述: 配置ACLK = LFXT1并进入LPM3模式
//   ACLK = LFXT1 = 32kHz, MCLK = SMCLK = 1MHz
//   辅助时钟 = (外部)低频振荡器 = 32kHz,主时钟 = 子系统时钟 = 1MHz
//   注意: 在测量功耗之前断开调试器会话
//
//          MSP430FR5969
//         ---------------
//     /|\|            XIN|-
//      | |               |  32KHz Crystal
//      --|RST        XOUT|-
//        |               |
//        |               |
//
//   Built with IAR Embedded Workbench V5.30 & Code Composer Studio V5.5
//******************************************************************************
#include <msp430.h>

int main(void)
{
  /* 停止看门狗定时器
   * 参考自《User's Guide》P641 & msp430fr5969.h
   * WDTCTL->看门狗定时器控制寄存器的名称
   * WDTPW->看门狗定时器控制寄存器WDTCTL的密码
   * WDTHOLD->停止看门狗定时器,当WDT禁止时,WDTHOLD = 1可降低功耗 */
  WDTCTL = WDTPW | WDTHOLD;

  // 配置GPIO
  /* 参考自《User's Guide》P368
   * 配置了所有8个GPIO端口(P1-P4和PJ)的输出模式,使它们都可以用来控制外部设备 */
  P1OUT = 0;
  P1DIR = 0xFF;

  P2OUT = 0;
  P2DIR = 0xFF;

  P3OUT = 0;
  P3DIR = 0xFF;

  P4OUT = 0;
  P4DIR = 0xFF;

  PJOUT = 0;
  PJSEL0 = BIT4 | BIT5;// XT1
  PJDIR = 0xFFFF;
  /* 设置PJ4和PJ5口的功能为外部晶振XT1(PJ.4->LFXOUT - PJ.5->LFIN)的输入端口->line5
   * 参考《Data Sheet》->P7芯片引脚图,if外部高频晶振(HFX)则配置PJ.6&PJ.7*/

  // 关闭GPIO上电默认高阻抗模式激活->设置高阻抗模式禁用引脚以降低功耗
  // 之前配置的端口
  /* 参考自《User's Guide》P92 & msp430fr5969.h
   * PM5CTL0->控制低功耗模式的寄存器 - PMM寄存器 - 电源管理模块
   * LOCKLPM5->(0x0001)->进入/退出LPM5时锁定I/O引脚配置 - PM5CTL0最低位清零*/
  PM5CTL0 &= ~LOCKLPM5;

  // XT1 Setup
  CSCTL0_H = CSKEY >> 8;// CSCTL0->CS控制寄存器0 - CSCTL0-0_H->CS控制寄存器0的高八位 - CSKEY->CS寄存器解锁密码
  CSCTL1 = DCOFSEL_0;// CSCTL1->CS控制寄存器1 - DCOFSEL_0->DCO频率选择:0->1MHz
  CSCTL2 = SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK;// CSCTL2->CS控制寄存器2 - SELA__LFXTCLK | SELS__DCOCLK | SELM__DCOCLK->详情参考《User's Guide》P106
  CSCTL3 = DIVA__1 | DIVS__1 | DIVM__1;// CSCTL3->CS控制寄存器3 - DIVA__1 | DIVS__1 | DIVM__1->详情参考《User's Guide》P107
  CSCTL4 &= ~LFXTOFF;// 使能LFXT1低频振荡器
  do// 循环检测(外部)低频晶振是否正常工作 - 确保MCU正常运行
  {
    CSCTL5 &= ~LFXTOFFG;// 清除XT1默认标志位,详情参考《User's Guide》P110
    SFRIFG1 &= ~OFIFG;// SFRIFG1->中断标志位寄存器,详情参考《User's Guide》P74
  }while (SFRIFG1&OFIFG);// 测试振荡器故障标志位 - OFIFG->振荡器故障中断标志
  CSCTL0_H = 0;// CS寄存器上锁

  /* SR->Status Register->状态寄存器->参考自《User's Guide》P118
   * __bis_SR_register->宏定义,用于设置SR寄存器的值
   * LPM0_bits->LPM0低功耗模式
   * GIE->general Interrupt Enable->全局中断使能标志位,决定是否允许处理器响应中断请求,GIE=1->正常响应中断;GIE=0->忽略任何中断请求 */
  __bis_SR_register(LPM3_bits);
}

最后再拓展一下上篇文章中的一个细节:

__interrupt宏定义(参考自ChatGPT,大家也知道ChatGPT有时候会说胡话,所以仅供参考)

__interrupt是一个宏定义,用于告诉编译器某个函数是一个中断服务程序。具体来说,当使用__interrupt修饰符定义函数时,编译器会为该函数自动添加中断向量表(IVT)和中断服务程序(ISR)等必要的代码,示例如下:

__interrupt void WDT_ISR(void)
{
    // 在此处理WDT中断事件
}

这段代码使用__interrupt修饰符定义了一个WDT中断服务程序函数WDT_ISR,并在函数体内编写了中断服务程序的具体代码。当WDT计数器达到最大值时,MCU将跳转到WDT_ISR函数并执行其中的代码。

需要注意的是,在使用__interrupt修饰符定义中断服务程序时,函数的返回类型必须为void,不能有参数传递。因为中断服务程序是在硬件中断触发后自动调用的,由硬件负责将中断产生时的上下文信息(状态寄存器、PC等)压入堆栈,同时也会自动从堆栈中弹出相应的信息。因此,中断服务程序不能被显式地调用,参数传递也不适用。

重点来了!!!(因为我之前一直不理解这个点,所以这是我以为的重点,大神勿喷)

为什么没有在main函数中调用这个中断函数,但__interrupt宏定义的中断函数也会执行?

答:在MCU中,中断是由硬件触发的,而不是由软件调用的。当MCU的某个外设出现中断事件时,将产生一个中断请求,此时CPU会自动跳转到对应的中断服务程序(ISR)开始执行其中的代码。因此,在main函数中不需要显式地调用中断函数,只需要在程序中定义好中断函数,并使用__interrupt修饰符进行声明即可。当中断事件发生时,CPU将自动跳转到中断向量表(IVT)中对应的ISR并开始执行其中的代码。

这是MCU专属的一种触发中断的方式。在MCU中,中断通常由硬件触发,而不是由软件调用。当某个外设出现中断事件时(例如定时器溢出、IO口电平变化等),该外设会向CPU发送中断请求,此时CPU将暂停当前任务并跳转到相应的中断服务程序(ISR)中执行其中的代码。这个过程是自动完成的,不需要用户调用中断函数。当ISR执行完毕后,CPU将恢复之前的任务继续执行。

就到这里吧,下篇文章应该就是要开始详解LPMx.5模式的例程了

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值