[资料分享] MSP430G2553学习笔记

Aguilera   2020-2-4 22:16 楼主

MSP430G2553概述
• 低电源电压范围:1.8V 至 3.6V
• 超低功耗
– 运行模式:230μA(在 1MHz 频率和 2.2V 电压 条件下)
– 待机模式:0.5μA
– 关闭模式(RAM 保持):0.1μ
• 5 种节能模式
• 可在不到 1μs 的时间里超快速地从待机模式唤醒
• 16 位精简指令集 (RISC) 架构,62.5ns 指令周期时间
• 基本时钟模块配置
– 具有四种校准频率并高达 16MHz 的内部频率
– 内部超低功耗低频 (LF) 振荡器
– 32kHz 晶振
– 外部数字时钟源
• 两个 16 位 Timer_A,分别具有三个捕获/比较寄存器
• 多达 24 个支持触摸感测的 I/O 引脚
• 通用串行通信接口 (USCI)
– 支持自动波特率检测的增强型通用异步收发器 (UART)
– IrDA 编码器和解码器
– 同步 SPI
– I2C™
• 用于模拟信号比较功能或者斜率模数 (A/D) 转换的 片载比较器
• 带有内部基准、采样与保持以及自动扫描功能的 10位 200ksps 模数 (A/D) 转换器
• 欠压检测器
• 串行板上编程,无需外部编程电压,利用安全熔丝实现可编程代码保护
• 具有两线制 (Spy-Bi-Wire) 接口的片上仿真逻辑电路

系统时钟
MSP430G2553有三种时钟的功能:
MCLK:
主时钟,专门为CPU运行提供的时钟
SMCLK:
子系统时钟,专为一些需要高速时钟的片内外设提供服务,比如定时器和ADC采样
ACLK:
辅助时钟,供给那些只需要低频时钟的片内外设,比如LCD控制器

//将MSP430G2553的时钟设置为:MCLK和SMCLK均为16MHz,ACLK设为内部低频振荡器
DCOCTL=CALDCO_16MHz;   //调取出厂校准后储存在Flash中的参数
BCSCTL1=CALBC1_16MHz;
BCSCTL3 |=LFXT1S1;      //设为内部低频振荡器
//将ACLK设为使用32.768KHz晶振且4分频
BCSCTL |=DIVA_2;
//将MSP430G2553的时钟设置为:MCLK为4MHz,SMCLK为2MHz,ACLK设为使用32.768KHz晶振 
DCOCTL=CALDCO_8MHz;   //先设置为8MHz 
BCSCTL1=CALBC1_8MHz;
BCSCTL2 |=DIVM_1+DIVS_2;   //再对MCLK2分频,SMCLK4分频 

GPIO与中断功能
I/O口方向寄存器:PxDIR
I/O口输入寄存器:PxIN
I/O口输出寄存器:PxOUT
控制内部上、下拉电阻寄存器:PxREN
MSP430G2553单片机的P1口与P2口带中断
是否允许I/O中断寄存器:PxIE
中断标志位寄存器:PxIFG
中断边沿选择寄存器:PxIES
MSP430G2553单片机是写位操作,例子如下:

//将P1.0置1,P1.1置0,P1.2取反,不影响其他位
P1OUT |=0X01;    //按位"或",相当于置1
P1OUT &=~0x02;   //取反后再按位"与",相当于置0
P1OUT ^=0x04;   //按位"异或",相当于取反
//将P1.0,P1.1,P1.2均置1,不影响其他位
P1OUT |=BIT0+BIT1+BIT2;  //可用加法进行批量设置 

在实际编程中,可以用宏定义来消除“线与”逻辑带来的不便。例如,将P1.0设为“线与”逻辑输出,可以用如下宏定义来描述:

#define P10_ON P1DIR &=~BIT0                 //I/O设为输入, 相当于"线与"输出1
#define P10_OFF P1DIR |=BIT0;P1OUT &=~BITO   //I/O设为输出,输出0 

MSP430G2553使用外部中断步骤如下:
1:通过PxDIR将I/O口方向设为输入
2:写PxIES可决定中断的边沿是上升沿、下降沿或两种情况均中断
3:如果是机械按键输入,可以通过PxREN启用内部上(下)拉电阻,根据按键的接法,设定PxOUT决定最终是上拉电阻还是下拉电阻
4:配置PxIE寄存器可开启I/O中断,“_enable_interrupts();”可开启总中断
5:在中断子函数中,通过if语句查询具体中断的I/O口,如果是机械按键输入,还需要消抖代码
6:根据具体I/O口的输入,编写事件处理函数
7:退出中断前,使用“PxIFG=0;”来清除I/O中断标志位

Timer_A定时器
MSP430G2553单片机的Timer_A模块的整体构造包括1个16位定时器和3个捕获/比较模块。
由于捕获模块Caputre和比较模块Comparator共用了TACCRx寄存器,所以捕获模块Caputre的功能是写TACCRx,而比较模块Comparator的功能是读TACCRx模块,所以捕获和比较不能同时使用。CAP寄存器位用于选择捕获/比较工作模式,CAP=0为比较,CAP=1为捕获。
CCRx可以选择检测上升沿或下降沿,或者都检测。CCRx用于测定信号脉宽时,只需要分别记录上升沿时刻和下降沿时刻,两个时刻相减就是脉宽;而测量频率时,连续记录两次上升时刻,相减就是周期。
51单片机外部中断法与捕获法的区别:
外部中断法:边沿被检测——触发中断——进中断子函数——读取定时器值,这时读取的定时器值和实际边沿的时刻有较大的误差
捕获法:边沿被检测——立刻读取定时器值TAR并锁存到CCRx模块内TACCRx寄存器——触发中断——什么时候读TACCRx都可以。这样的误差延时就仅有10ns级
比较模式用于设定定时器的周期
比较模块的OUTMODx设置。普通PWM时,超前PWM(上升沿在主定时器0位置)配置模式7,滞后PWM配置模式3;带死区PWM时,两路输出都必须开启,并且一路模式为6,另一路必须为2。
注意:虽然每个Timer_A模块有3个捕获/比较模块(CCR0/1/2),但是CCR0的寄存器TACCR0已被用于设定PWM频率,因此用CCR1和CCR2最多能生成2路独立的PWM信号。CCR0的比较值TACCR0用于设定周期,CCR1/2的比较值TACCR1/2用于设定占空比。

WDT定时器
WDT(Watch Dog Timer)俗称看门狗
复位引脚被设置成NMI不可屏蔽中断来使用,这个中断和普通I/O外部中断一样,有中断子函数;其区别是NMI中断不需要开总中断使能(因为不可屏蔽,所以优先级最高),NMI每次中断后会自动关闭NMI中断使能。

//当看门狗被设定为1s定时复位,那么"喂狗"的代码是这样的:
WDTCTL=WDT_ARST_1000;   //该宏定义包含了喂狗,并重新设定看门狗定时值的代码 

变量知识点:
全局变量:
具有全局作用域,全局变量只需在一个源文件中定义,就可以作用于所有的源文件。
静态全局变量:
具有全局作用域,它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被 static 关键字修饰过的变量具有文件作用域。
局部变量:
具有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
静态局部变量:
具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在。

int a = 0; //全局变量
static int b=0;//静态全局变量
main() 

int c; //局部变量
static int d;//静态局部变量 
}

状态机知识点:
状态机也叫有限状态机,简称状态机。状态机的概念来源于时序逻辑电路,又细分为Mealy状态机和Moore状态机,两者的区别在于是否根据状态就能得出输出结果。
单片机中借用了这两种状态机的思想,引申出“状态中判断事件”和“事件中查询状态”两种单片机状态的编程方法。
状态中判断事件:
这种方法类似与Mealy型状态机(不完全等同),即在switch语句中,还需判断Event才能决定输出的结果。

//--------状态中查询事件(Mealy状态机)---------
switch(State)
{
    case 0:  if(Event_0)   Action2();              //路径1
             if(Event_1)   {State=2;  Action0();}  //路径3 
             if(Event_2)   State=2;                //路径4
                break;
    case 1:  if(Event_0)   State2;                 //路径5
             if(Event_2)   {State=0;  Action2();}  //路径2
                break;
    case 2:  if(Event_1)   {State=1;  Action1();}  //路径6
                break;
    default:    break; 
}


事件中查询状态:
这种方法类似于Moore型状态机(不完全等同),在switch语句中,即无需再判断Event,由当前状态就知道结果。

//--------事件中查询状态(Moore状态机)---------
if(Event_0)          //中断或扫描得知Event0事件发生 
 {
     switch(State)
     {
         case 0:    Action2();       break;    //路径1 
         case 1:    State=2;         break;    //路径5
        default:                    break; 
     }
 }
if(Event_1)          //中断或扫描得知Event1事件发生 
 {
     switch(State)
     {
         case 0:    State=2;     Action0();       break;    //路径3
         case 2:    State=1;     Action1();       break;    //路径6
        default:                    break; 
     }
 }
if(Event_2)          //中断或扫描得知Event2事件发生 
 {
     switch(State)
     {
         case 0:    State=2;                    break;    //路径4 
         case 1:    State=0;      Action2();    break;    //路径2
        default:                    break; 
     }
 }  

两种状态机的优缺与区别:
1:如果Event直接由中断引发,不需要if语句轮询就能判断,则用Moore型转态机(事件中查询状态)执行速度快。这是因为,只需执行对应Event的switch(State)语句,而且switch中只需State进行判断就可以输出结果了。
2:如果Event本身就需要轮询才能得出,则使用Mealy型状态机(状态中查询事件)的代码要简单。因为状态中查询事件只有一个switch(State)语句。

回复评论

暂无评论,赶紧抢沙发吧
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 京公网安备 11010802033920号
    写回复