MSP430G2553与MSP430F5336系列单片机总结[2]

发布者:blazings最新更新时间:2020-04-14 来源: eefocus关键字:MSP430G2553  MSP430F5336系列  单片机总结 手机看文章 扫描二维码
随时随地手机看文章

在研究定时器与捕捉比较器之前,我们可以先讨论一下,他们能做什么?


1.定时,产生固定频率的波形,或者使LED等按照固定时间闪亮


2.产生Timer0定时中断,在一定的时间间隔执行某些功能,例如超声波传感器的使用,可以设置超声波测量距离的测量频率


3.可以测量脉冲或PWM波的的高低电平时间或频率


4.脉冲计数


5.捕捉比较模式可以产生PWM波


6.可以产生PPM波


7.可以测量PPM波的各通道占空比 


所以定时器是单片机中使用频率很高的资源,不要随便使用定时器的IO口直接做输入输出使用,这样有点浪费。


先对MSP430G2553进行分析,通过用户手册和Datasheet,我们可以知道G2553只有定时器A,没有定时器B,并且没有定时器A2,定时器A只有捕捉比较器0(TA0.CCI0A  引脚P1.1),捕捉比较器1(TA0.CCI1A  引脚P1.2)等资源,Timer_A为16为定时器,也就是说最高可以计数到65536,当定时到实践或者满足捕获比较条件时可以出发定时器A中断。


在这里对中断进行一定的介绍,中断使暂停CPU正在运行的程序,转去执行相应的中断服务程序,中断完毕后返回被中断的程序并且继续运行的现象和技术,中断的存在是很必要的,可以很好地处理突发事件,并且不与主程序内容冲突。这些解释或许不便于理解,我现在举一个例子来说明中断的必要性。例如,我现在要用MSP430系列的单片机做飞控控制四轴飞行器,首先他需要不断产生200HZ的四路PWM波,还需要不断的读来自MPU6050传递过来的飞信器加速度角速度等数据,还需要获取超声波返回的距离信息以避障,还需要进行四元素融合计算欧拉角以及进行PID迭代,这么多的操作要同时执行,假如说没有中断,我们产生200HZ的PWM波的方式或许会采用延时,也就是写一些延时程序延时到5ms则取反则能产生200HZ的pwm波,但是这样你的程序需要不断执行延时程序,并且不能被打断,因为一旦被打断,你产生的波形的周期也就变了,这样我们将不能加入MPU6050等传感器。但是使用中断可以很好地解决这一问题。我们的主程序不断执行的就是PID迭代这个操作,然后再5ms的计时周期到了之后,进入定时器中断并且产生pwm波,串口中断到了之后进入串口读MPU6050的数据,echo信号的高电平到了之后进入超声波对应的定时器读高电平,在这些中断结束后继续在主函数进行PID迭代,这样就可以不断地更新信息,产生波形,并且不影响主函数的执行。所以学会使用中断使很重要的。中断的来源有内部中断和外部中断,并且可以设置优先级,要能够进入中断也必须先在相关的寄存器中设置中断使能,这些内容大家可以参照代码和一些资料自己学习,现在我来讲几个定时器中断的典型例子:


#include  


void main(void)

{

  WDTCTL = WDTPW + WDTHOLD;                 // 关闭看门狗定时器

  P1DIR |= 0x01;                            // 设置P1.0为输出

  CCTL0 = CCIE;                             // TA0CCR0定时器使能,这里的CCTL0在宏定义中其实就是TACCTL0

  CCR0 = 1000-1;                            //设置计数为1000

  TACTL = TASSEL_1 + MC_1;                  // 使用ACLK=32768HZ 上数模式


  _BIS_SR(LPM3_bits + GIE);                 // 进入LPM3中断并且中断使能

}


// 定时器A0的捕捉比较器0中断

#pragma vector=TIMER0_A0_VECTOR

__interrupt void Timer_A (void)

{

  P1OUT ^= 0x01;                            // P1.0口取反从而产生方波

}

/*

 * 产生方波的周期为:32768hz/1000*2=16HZ

 */


上面这个例子采用的是捕捉比较器A0的中断,A0和其他捕捉比较器的中断使不同的,A0的中断格式如这个程序所示,其他捕捉比较器的中断我们之后再说,上面的程序基本有注释,很容易看懂,其中要注意的就是定时器计数的四种模式,分别是停止模式(不计数),增计数模式(从0计数到TAxCCR0),连续计数模式(从0计数到0FFFFh),增减计数模式(从0计数到TAxCCR0之后减计数到0循环往复),所以通过增计数或者增减计数模式可以通过改变TAxCCR0改变计数周期,也就是改变要生成的波形周期。此外还有输入输出的模式定义,对应可以生成不同需求的波形,例如pwm波等等,这个可以详细看用户手册了解。接下来看第二个例子:


#include  

int main(void) {

    WDTCTL = WDTPW | WDTHOLD; // 关闭看门狗计时器

P1DIR|=0X01;

TACTL=TASSEL_2+MC_2+TAIE;    //SMCLK=1.048576Mhz定时器为16位,溢出计数为65536

_BIS_SR(LPM0_bits+GIE);    //f=1.048576MHZ/65536*2=8hz

}

#pragma vector=TIMER0_A1_VECTOR

__interrupt void Timer_A(void)

{

switch(TA0IV)

{

case 2:break;

case 4:break;

case 10:P1OUT^=0x01;

              break;

}

}

/*

 * 定时器A有两个不同的中断向量地址,一个是CCR0的定时器溢出中断,是定时或计数周期时间到了之后进入该中断

 * 程序如下:

 * #pragma vector=TIMER0_A0_VECTOR

 * __interrupt void Timer_A0(void)

 * {

 * }

 * 另一个是CCR1/CCR2以及TAR计数溢出中断

 * 程序如本程序所示

 * 其中case2是CCR1产生的中断,case2是CCR2产生的中断,case10是定时器TAR溢出中断

 */


这个例子使用的是A1的中断,像注释中所说,其中case2是CCR1产生的中断,case4是CCR2产生的下降沿中断,case10是定时器TAR溢出中断,所以你想要在8hz时P1.0取反,则在case10时写这句话,当然你也可以设置在CCR1或者CCR2的计数时间到时取反,如下方代码所示:

#include  

int main(void) {

    WDTCTL = WDTPW +WDTHOLD; // Stop watchdog timer

P1DIR|=0x01;

CCTL1=CCIE;

CCR1=50000;

TACTL=TASSEL_2+MC_2;   //SMCLK=1.048576MHZ 连续计数模式  计数100000个,所以频率为10hz左右

_BIS_SR(LPM0_bits+GIE);

}

#pragma vector=TIMER0_A1_VECTOR

__interrupt void Timer_A(void)

{

switch(TA0IV)

{

case 2:

{

P1OUT^=0x01;   //捕获比较器1触发

CCR1+=50000;

}

    break;

case 4:break;

case 10:break;

}

}

/*

 * f=10.89hz

 * 使用捕获比较器1

 */


#include  

void main(void) {

    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer

P1SEL|=BIT1+BIT2;

P1DIR|=BIT0+BIT1+BIT2;

CCTL0=OUTMOD_4+CCIE;

CCTL1=OUTMOD_4+CCIE;

TACTL=TASSEL_2+MC_2+TAIE;

_BIS_SR(LPM0_bits+GIE);

}

#pragma vector=TIMER0_A0_VECTOR

__interrupt void Timer_A0(void)

{

CCR0+=200;

}

#pragma vector=TIMER0_A1_VECTOR

__interrupt void Timer_A1(void)

{

switch(TA0IV)

{

case 2:CCR1+=1000;

            break;

case 10:P1OUT^=0x01;

            break;

}

}

/*

 * 对于P1.0 f=1M/65536*2=8HZ

 * 对于P1.1即CCR0 f=1M/2*200=2500hz

 * 对于P1.2即CCR1 f=1M/2*1000=500HZ

 */


以上的代码大致是定时器中断的介绍,相信大家不难理解,但是到这里会有一个问题,就是假如不用中断,能不能产生一定周期的信号呢,答案是可以的,可以配置CCR1和CCR0的引脚为比较输出模式,便可以产生一定频率的方波。这里比较简单,不再仔细讲,具体代码和注释如下:

#include  


void main(void)

{

  WDTCTL = WDTPW + WDTHOLD;                 // 关闭看门狗计时器

  P1DIR |= 0x02;                            // P1.1 输出

  P1SEL |= 0x02;                            // P1.1 第二功能选择

  CCTL0 = OUTMOD_4;                         // CCR0 比较输出模式4

  CCR0 = 500-1;                             //计数为500,所以周期为SMCLK/1000

  TACTL = TASSEL_2 + MC_1;                  // SMCLK为时钟,上数模式


  _BIS_SR(CPUOFF);                          // 关闭CPU进入休眠,P1.1频率为SMCLK/1000

}


下面这个例子是不用中断生成pwm波波形的例子,用中断生成pwm波的例子我之后会专门写文章说明

#include  


void main(void)

{

  WDTCTL = WDTPW + WDTHOLD;                 // 关狗

  P1DIR |= 0x0C;                            // P1.2 P1.3 设置为输出

  P1SEL |= 0x0C;                            // P1.2 P1.3 选择TA1/2 功能

  CCR0 = 512-1;                             // 设置PWM波周期 

  CCTL1 = OUTMOD_7;                         // CCR1 模式7

  CCR1 = 384;                               // 设置CCR1占空比75%

  TACTL = TASSEL_2 + MC_1;                  // SMCLK为时钟,上数模式


  _BIS_SR(CPUOFF);                          // 进入休眠

}


以上基本是MSP430G2553的定时器A的说明,还有一些其他的例程可能配置时钟为ACLK,或者产生不同的占空比,或者使用不同的引脚,不过原理都大同小异,大家要注意的就是选择哪个时钟,哪种计数模式,便能很好地运用定时器A。


同样我们来看一下MSP430F5336的定时器使用,F5336的定时器资源相对来说就丰富的多,定时器有定时器A0,定时器A1,定时器A2,定时器B四个不同的定时器模块,定时器A0有CCI0-CCI4五个捕捉比较器,还有CCI1B和CCI2B做为选择,是管教P1.1-P1.7的第二功能;定时器A1和定时器A2都是分别有CCI0-CCI2三个捕捉比较器,在引脚P3上;定时器B有CCI0-CCI6七个捕捉比较器,在引脚P4上;具体的原理和G2553差不多,不过寄存器略有区别,我不详细讲了,直接贴代码:


定时器A:

#include 

/*

 * 定时器A的寄存器情况基本与G2553一致,可以参考中文资料

 * P1频率为10hz,所以48ms发生一次中断

 * SMCLK为1M左右,所以为50000us相当于50ms

 */

void main(void)

{

  WDTCTL = WDTPW + WDTHOLD;                // 关闭看门狗

  P1DIR |= 0x01;                            // P1.0设为输出

  TA0CCTL0 = CCIE;                          // CCR0中断使能

  TA0CCR0 = 50000;

  TA0CTL = TASSEL_2 + MC_1 + TACLR;  // SMCLK, 增计数模式, 清除TAR计数器

  __bis_SR_register(LPM0_bits + GIE);  // 进入LPM0,使能中断

}

// TA0中断服务程序

#pragma vector=TIMER0_A0_VECTOR

__interrupt void TIMER0_A0_ISR(void)

{

  P1OUT ^= 0x01;                            // 反转P1.0口输出状态

}


#include 

/*

 * 定时器A的寄存器情况基本与G2553一致,可以参考中文资料

 * 65536一次溢出

 * SMCLK为1M左右,所以为65535us相当于65ms

 */

void main(void)

{

  WDTCTL = WDTPW + WDTHOLD;              // 关闭看门狗

  P1DIR |= 0x01;                           // P1.0设为输出

  TA1CTL = TASSEL_2 + MC_2 + TACLR + TAIE;

// SMCLK,连续计数模式,清除TAR,并使能TAIFG中断

  __bis_SR_register(LPM0_bits + GIE); // 进入LPM0, 并启动中断

}

// TA1中断服务程序

#pragma vector=TIMER1_A1_VECTOR

__interrupt void TIMER1_A1_ISR(void)

{

  switch(__even_in_range(TA1IV,14))

  {

    case  0: break;                          // 无中断

    case  2: break;                          // TA1CCR1 CCIFG中断

    case  4: break;                          // TA1CCR2 CCIFG中断

    case  6: break;                        // TA1CCR3 CCIFG中断

    case  8: break;                        // TA1CCR4 CCIFG中断

    case 10: break;                        // TA1CCR5 CCIFG中断

    case 12: break;                      // TA1CCR6 CCIFG中断

    case 14: P1OUT ^= 0x01;              // TAIFG中断

             break;

    default: break;

  }

}


#include 

/*

 * 使得P1.2(TA0CCR1)和P1.3(TA0CCR2)和P1.4(TA0CCR3)和P1.5(TA0CCR4)分别输出占空比为20和%40和%60和%80的波形

 * 频率为980000/TA0CCR0=400hz

 * 可以用作操控电机

 */

void main(void)

{

  WDTCTL = WDTPW + WDTHOLD;            // 关闭看门狗

  P1DIR |= BIT2+BIT3+BIT4+BIT5;        // P1.2和P1.3设为输出

  P1SEL |= BIT2+BIT3+BIT4+BIT5;        // P1.2和P1.3引脚功能选为定时器输出

[1] [2]
关键字:MSP430G2553  MSP430F5336系列  单片机总结 引用地址:MSP430G2553与MSP430F5336系列单片机总结[2]

上一篇:MSP430实现800Hz蜂鸣器和秒表
下一篇:MSP430比较器小结

推荐阅读最新更新时间:2024-11-17 06:28

MSP430单片机各种寄存器总结(2)——UCS
第二章 UCS寄存器 2.1 UCSCTL0 上述的两个区域并不需要设置,在配置FFL的时候直接设置成0即可,FLL配置完成后会自动被设置。 2.2 UCSCTL1 DCORSEL,DCOCLK的频率范围设置参数,通过它来设置DCOCLK的频率范围,比如:设置DCOCLK的输出频率范围为0.64~14.0MHz 如下图所示,可知设置频率为0.64~14.0MHz的DCO需要将DCORSEL的值设置为3. UCSCTL1 = DCORSEL_3; //DCORSEL_3是宏定义,为0x0030 2.3 UCSCTL2 & UCSCTL3 2.3.1 寄存器示意图 2.3.2 锁频环FLL 上述两个是
[单片机]
MSP430<font color='red'>单片机</font>各种寄存器<font color='red'>总结</font>(2)——UCS
单片机驱动LED数码管显示总结
用单片机驱动LED数码管有很多方法,按显示方式分,有静态显示和动态(扫描)显示,按译码方式可分硬件译码和软件译码之分。   静态显示就是显示驱动电路具有输出锁存功能,单片机将所要显示的数据送出后就不再管,直到下一次显示数据需要更新时再传送一次新数据,显示数据稳定,占用很少的CPU时间。动态显示需要CPU时刻对显示器件进行数据刷新,显示数据有闪烁感,占用的CPU时间多。这两种显示方式各有利弊;静态显示虽然数据稳定,占用很少的CPU时间,但每个显示单元都需要单独的显示驱动电路,使用的硬件较多;动态显示虽然有闪烁感,占用的CPU时间多,但使用的硬件少,能节省线路板空间。   硬件译码就是显示的段码完全由硬件完成,CPU只要送出标准的BC
[单片机]
STM8单片机学习总结05-蓝牙模块
本次操作使用的“蓝牙模块”为“HC-06”,主要注意以下几点: 01)、“HC-06”(蓝牙模块)而言,其与“HC-05”一样,均采样“AT指令”控制,但需注意: i)、“HC-06”为“串口”连接,电压为“+5.0V”,“波特率”默认“9600”,“设备名称”默认“HC-06”,“配对密码”默认“1234”; ii)、“HC-06”发送“AT指令”时,末尾不需加“\r\n”(Enter键); iii)、需与“手机app”配合使用,推荐“蓝牙串口助手 Pro”; 02)、“HC-06”对应“AT指令”主要操作为以下4项: i)、“测试通信”:发送“AT”,返回“OK”; ii)、修改“波特率”:发送“AT+BAUDx”,“x”为“
[单片机]
AVR单片机c程序设计编程时常见的问题总结分析
这两天在用AVR单片机做项目,这次是边做边深入学,尽量将以前忽略的知识用上,比如指针、文件包含、条件编译、变量作用域等一一调研清楚。收获不少,再次体会到学习的过程中没有无用的地方。用的越深入,才发现学时以为没用的东西都是最有用的,因为都被忽略了。幸亏学习时候的最重要的《c程序设计》如果不能解决,就找编译器的问题。这是这段时间总结的经验。 一、函数指针 1.int (*func)(void)--基本函数指针变量定义方式,变量func是一个指向返回值为int,没有参数的函数指针,这与其他变量定义有点区别,一般是把变量名放最后,如int a,而函数指针比较不直观, 2.typedef int(*ftype)(void); fty
[单片机]
AVR<font color='red'>单片机</font>c程序设计编程时常见的问题<font color='red'>总结</font>分析
msp430g2553硬件IIC
#include msp430g2553.h #include uart.h unsigned char RX_Data; void I2C_Init(unsigned char SA);//I2C初始化,SA为从器件地址 void I2C_ReadData(unsigned char address);//I2C读出某一地址的数据 unsigned char I2C_WriteData(unsigned char address,unsigned char data);//I2C向某一地址写入数据 void delay(void); void I2C_Init(unsigned char SA) { P1SEL |=
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多每日新闻

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved