电赛MSP430知识小结

2024-05-10 16:58
文章标签 知识 小结 msp430 电赛

本文主要是介绍电赛MSP430知识小结,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

(转)今年的电赛对TI公司生产的MSP430系列的单片机进行了初步的学习,第一次参加电赛,知识量不足,所以在此对资料进行了总结,旨在留存一下知识,以便在今后的学习中,可以有所回忆,减少时间的消耗,算是见见同志第一个菜鸟篇学习日志,菜鸟先飞,也希望能帮助初学MSP430单片机的同学,仅仅适合初学者,且只介绍我涉及到的方面,谢谢大家支持原创。

我使用的是Launchpad MSP430G2553开发板:有14个I/O口和10位A/D

一:编译软件

编译软件可以使用IAR和CCS两种,CCS体积较大,IAR针对性强,见见同志使用的是IAR for MSP430

相关的官方下载链接如下:

http://www.iar.com/en/Service-Center/Downloads/;下载过后使用注册机破解一下,注册机上百度搜索一个适合版本的,找一个就行;具体的IAR操作方法没办法附加在附件中,

给个IAR说明的下载链接:http://download.csdn.net/detail/tushuguan2/3986147 ,名字:《手把手教你使用TI MSP430 LaunchPad》

或者上新浪的下载链接http://ishare.iask.sina.com.cn/f/23840199.html?from=dl,要用Launchpad要设置一下IAR,看链接的说明就行,我就不一一介绍了。

TI公司生产的MSP430系列单片机与普通51单片机没有很大的不同,但是其内部含有大量的寄存器,功能比较细化,可能会造成混乱,与51对比学习,可以加快学习进度;

程序编写的格式:

#include<msp430g2553.h>

Void main()

{

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

**(程序)

}

二:通用I/O方面

P口端口寄存器:

   (1)、PxDIR   输入/输出方向寄存器(0:输入模式    1:输出模式)

   (2)、PxIN    输入寄存器输入寄存器是只读寄存器,用户不能对其写入,只能通过读取该寄存器的内容知道I/O口的输入信号。

   (3)、PxOUT  输出寄存器寄存器内的内容不会受引脚方向改变的影响。

   (4)、PxIFG   中断标志寄存器(0:没有中断请求   1:有中断请求),该寄存器有8个标志位,对应相应的引脚是否有待处理的中断请求;这8个中断标志共用一个中断向量,中断标志不会自动复位,必须软件复位;外部中断事件的时间必须>=1.5倍的MCLK的时间,以保证中断请求被接受;

   (5)、PxIES   中断触发沿选择寄存器(0:上升沿中断       1:下降沿中断)

   (6)、PxSEL   功能选择寄存器(0:选择引脚为I/O端口 1:选择引脚为外围模块功能)

   (7)、PxREN     上拉/下拉电阻使能寄存器(0:禁止  1:使能)

 

基本操作:

(1)、所有P口都可作为通用IO口使用

(2)、所有P口都可进行字节操作和位操作

 

基本操作:

(1)、所有P口都可作为通用IO口使用

(2)、所有P口都可进行字节操作和位操作

   按字节操作:

 

传统51:

P1=0X01;

输入输出直接赋值

 

 



   例 :  P1DIR=0xff;    //将P1口作为输出口                

            PIOUT=0x20;  // P1口输出0x20

            P1DIR=0x00;    //将P1口作为输入口

            data=P1IN           //读取P1口外部输入值

    按位操作:

 

传统51:

sbit P1_0=P1^0;

输入输出直接赋值

 



    例:   P1DIR=BIT0;      //将P1.0作为输出口

 

           P1OUT|=BIT0;   //P1.0输出1

           P1OUT&=~BIT0;   //P1.0输出0

P1DIR&=~BIT0  //将P1.0口作为输入

           data=P1IN&BIT0 //读取P1.0口外部输入值

 

 

举例:闪烁LED。

LaunchPad 上面自带有2 个LED,一个接在P1.0 上,一个接在P1.6 上。

我们用2 个交替闪烁。

#include<msp430g2553.h>

void main();第一个字母小写

{

WDTCTL=WDTPW+WDTHOLD;

P1DIR|=BIT0+BIT6;//设置P1.0 和P1.6 为输出

P1OUT|=BIT0;//线让LED0 亮。

while(1)

{

unsigned int i=50000;

while(i--);

P1OUT^=0x41;//对P1.0 和P1.6 取反,所以LED0 和LED1 会交替闪烁。

}

}

 

MSP430不能和51一样直接按位操作,只能通过与、或、非等逻辑运算对寄存器进行操作。这里是最大的不同,用习惯了51,再用MSP430就会感觉特别的麻烦,只要习惯就行了,没什么好办法。

 

二:中断

中断的 一般设置:

 (1)、打开、关闭局部中断:

打开局部中断一般是给想关的特殊功能寄存器相关位置1

  以P1口外部中断为例:

  打开局部中断:

     P1IE|=BIT0;//打开P1.0外部中断 ,BIT0的值为0x01,即把P1IE的第一位置1

关闭局部中断一般是给想关的特殊功能寄存器相关位置0

同样以P1口外部中断为例:

关闭局部中断:

P1IE&=~BIT0;//关闭P1.0外部中断

(2)、打开、关闭全局中断:

        _EINT();//打开总中断,相当于51的EA=1;

           _DINT();//关闭总中断,相当于51的EA=0;

(3)、各中断向量Interrupt Vectors:

#define BASICTIMER_VECTOR   (0 * 2u) /* 0xFFE0 Basic Timer */

#define PORT2_VECTOR        (1 * 2u)  /* 0xFFE2 Port 2 */

#define USART1TX_VECTOR     (2 * 2u) /* 0xFFE4 USART 1 Transmit */

#define USART1RX_VECTOR     (3 * 2u) /* 0xFFE6 USART 1 Receive */

#define PORT1_VECTOR        (4 * 2u)  /* 0xFFE8 Port 1 */

#define TIMERA1_VECTOR      (5 * 2u) /* 0xFFEA Timer A CC1-2, TA */

#define TIMERA0_VECTOR      (6 * 2u) /* 0xFFEC Timer A CC0 */

#define ADC12_VECTOR          (7 * 2u)  /* 0xFFEE ADC */

#define USART0TX_VECTOR     (8 * 2u) /* 0xFFF0 USART 0 Transmit */

#define USART0RX_VECTOR     (9 * 2u) /* 0xFFF2 USART 0 Receive */

#define WDT_VECTOR          (10 * 2u) /* 0xFFF4 Watchdog Timer */

#defineCOMPARATORA_VECTOR  (11 * 2u) /* 0xFFF6Comparator A */

#define TIMERB1_VECTOR      (12 * 2u) /* 0xFFF8 Timer B CC1-6, TB */

#define TIMERB0_VECTOR      (13 * 2u) /* 0xFFFA Timer B CC0 */

#define NMI_VECTOR          (14 * 2u) /* 0xFFFC Non-maskable */

#define RESET_VECTOR        (15 * 2u) /* 0xFFFE Reset [HighestPriority] */

(4)、中断的嵌套:

当同时有多个中断来的时候才有优先级的考虑(优先级顺序可查看向量表)

 

 

实现中断嵌套需要注意以下几点:

1)430默认的是关闭中断嵌套的,一定要中断嵌套的话,就必须在中断服务程序中打开总中断

  msp430的指令中,_DINT()和_EINT()分别指关和开总中断。

2)当进入中断服务程序时,只要不在中断服务程序中再次开中断,则总中断是关闭的,此时来中断不管是比当前中断的优先级高还是低都不执行;

3)若在中断服务程序A中开了总中断,则可以响应后来的中断B(不管B的优先级比A高还是低),B执行完再继续执行A。注意:进入中断服务程序B后总中断同样也会关闭,如 果B中断程序执行时需响应中断C,则此时也要开总中断,若不需响应中断,则不用开中断,B执行完后跳出中断程序进入A程序时,总中断会自动打开;

4)若在中断服务程序中开了总中断,后来的中断同时有多个,则会按优先级来执行,即中断优先级只有在多个中断同时到来时才起做用!中断服务不执行抢先原则。

5)对于单源中断,只要响应中断,系统硬件自动清中断标志位,对于TA/TB定时器的比较/捕获中断,只要访问TAIV/TBIV,标志位倍被自动清除;

    

  对于多源中断要手动清标志位,比如P1/P2口中断,要手工清除相应的标志,如果在这种中断用"EINT();"开中断,而在打开中断前没有清标志,就会 有相同的中断不断嵌入,而导致堆栈溢出引起复位,所以在这类中断中必须先清标志再打开中断开关.

 

举例:1:

中断应用程序举例(外部中断):

 void interrupt_initial()

{

 P1DIR&=~BIT7;      //P1.7为输入

 P1IE|=0x80;      //P1.7中断允许

 P1IES|=0x00;     //P1.7上升沿触发

 P1IFG=0;      //P1.7中断标志清除,对于多源中断必须先清中断标志再打开中断

 _EINT();       //总中断允许

}

#pragmavector=PORT1_VECTOR

__interruptvoid Port_1(void)

{

  P1IFG&=~BIT7;  //P1.7中断标志清除

/*在此写中断服务子程序*/

}

如果想写中断的嵌套,或者几个中断一起作用,我电赛就是写的按键中断、定时器中断:

举例2:(部分)

//------------------------按键初始化-----------------------------------------------------------------

 

 voidKey_init(void)

      {

          P1REN |= BIT3;        //打开上拉,电路板上没有上拉电阻,触发边沿是从高电平到低电平

          P1IES |= BIT3;       //选择触发边沿,从高电平到低电平

 

          P1IFG &= ~BIT3;      //清除P1.3的中断标志位(可以不清除,为了确保初始化之后为标志位不会触发中断)

          P1IE  |= BIT3;       //打开P1的中断

          

          P1REN |= BIT2;        //打开上拉,电路板上没有上拉电阻,触发边沿是从高电平到低电平

          P1IES |= BIT2;       //选择触发边沿,从高电平到低电平

 

          P1IFG &= ~BIT2;      //清除P1.2的中断标志位(可以不清除,为了确保初始化之后为标志位不会触发中断)

          P1IE  |= BIT2;       //打开P1的中断 

      }

 

 

//函数名称:main()

//功    能:主函数

//-----------------------------------------------------------------------------------------

void main(void)

{

//uchar i,j,t;

   Initial(); //初始化子程序

   Ht1621_Init(); //上电初始化LCD

   Key_init();  //调用IO中断初始化函数

   init_ADC10();

   TACTL=TASSEL1+MC1+TACLR;//定时器时钟源为SMCLK,up,不分频,清零

   CCTL0|=CCIE;//使能比较器中断

   CCR0=50000;// 计数器终值

   __enable_interrupt();//使能全局中断,C编译器中的内部函数

   _EINT();

      start_ADC10();     

          display_jiaodu();

       

   LPM1;            //进入低功耗模式1

}

 

void init_ADC10()

{

         //P1SEL|= 0xFF;

         ADC10AE0|= 0x70;//使用P1.0,1.1,1,2  AD转换

         ADC10CTL0= ADC10ON + MSC + SREF_0 + REFON;

         //开AD内核,选择电源为参考电压

         ADC10CTL1= ADC10SSEL_0 + CONSEQ_0; //采用单通道多次采用

       _EINT(); //使能中断

      

}

 

 

void start_ADC10()

{

        

         ADC10CTL0&= ~(ADC10SC + ENC);

         ADC10CTL1&= ~INCH_3;

         ADC10CTL1|= INCH_4;

         ADC10CTL0|= ADC10SC + ENC;

         while(ADC10CTL1 & ADC10BUSY != 0)

                   ;

         result[0]= ADC10MEM;

         ADC10CTL0&= ~(ADC10SC + ENC);

         ADC10CTL1&= ~INCH_4;

         ADC10CTL1|= INCH_5;

         ADC10CTL0|= ADC10SC + ENC;

         while(ADC10CTL1 & ADC10BUSY != 0)

                   ;

         result[1]= ADC10MEM;

         ADC10CTL0&= ~(ADC10SC + ENC);

         ADC10CTL1&= ~INCH_5;

         ADC10CTL1|= INCH_6;

         ADC10CTL0|= ADC10SC + ENC;

         while(ADC10CTL1 & ADC10BUSY != 0)

                   ;

         result[2]= ADC10MEM;

         ADC10CTL0&= ~(ADC10SC + ENC);

         ADC10CTL1&= ~INCH_6;

         ADC10CTL1|= INCH_7;

         ADC10CTL0|= ADC10SC + ENC;

         while(ADC10CTL1 & ADC10BUSY != 0)

                   ;

     if (result[0]<=483)

          {

              result[0]=483;

         }

       if (result[0]>=738)

         {

              result[0]=738;

         }

      if (result[1]<=530)

         {

              result[1]=530;

         }

       if (result[1]>=776)

         {

              result[1]=776;

         }

       if (result[2]>=698)

         {

              result[2]=698;

         }

       if (result[2]<=458)

         {

              result[2]=458;

         }

}

 

#pragma vector=TIMER0_A0_VECTOR

__interrupt void Timer(void)

{

 

   //PushKey=P1IFG&BIT3;

   if(flag==0)

    {

       i++;   

       if(i==100)//定时5s

       {

          i=0;

          start_ADC10();     

          display_jiaodu();

       }

       

    }

   

   

}

#pragma vector = PORT1_VECTOR                //中断向量声明

__interrupt void Key_interrput(void)

 

 if(P1IFG&(BIT2+BIT3))                //判断是不是P1.3这个IO口产生了中断

 {   

       if(P1IFG&BIT3)

       {

 

       start_ADC10();

 

       display_jiaodu();

       P1IFG&=~BIT3;                                           

       P1IFG &= ~BIT3;//清除中断标志位,这一步一定要有。

       }

       if(P1IFG&BIT2)

       {

 

       start_ADC10();

 

       display();

       P1IFG&=~BIT2;                                           

       P1IFG &= ~BIT2;//清除中断标志位,这一步一定要有。

       }

  }

 else

 {

  P1IFG = 0x00;

 }

}

 

提到中断,就不得不提到MSP430的五种低功耗模式:   LPM0、LPM1,LPM2,LMP3,LMP4

MSP430 具有一种运行模式及5 种可利用软件来选择的低功耗操作模式。一个中断事件能够将器件从任一低功耗模式唤醒、处理请求、并在接收到来自中断程序的返回信号时恢复至低功耗模式。

以下6 种操作模式可利用软件来配置:

1、激活模式(AM)

– 所有时钟处于激活状态

2、低功耗模式0 (LPM0)

– CPU 被禁用

– ACLK 和SMCLK 仍然有效,MCLK 被禁用

3、低功耗模式1 (LPM1)

– CPU 被禁用

– ACLK 和SMCLK 仍然有效,MCLK 被禁用

– 如果DCO 不是在激活模式下被使用,则DCO 的dc 生成器被禁用

3、低功耗模式2 (LPM2)

– CPU 被禁用

– MCLK 和SMCLK 被禁用

– DCO 的dc 生成器保持启用

– ACLK 保持激活

4、低功耗模式3 (LPM3)

– CPU 被禁用

– MCLK 和SMCLK 被禁用

– DCO 的dc 生成器保持启用

– ACLK 保持激活

5、低功耗模式4 (LPM4)

– CPU 被禁用

– ACLK 被禁用

– MCLK 和SMCLK 被禁用

– DCO 的dc 生成器保持启用

– 晶体振荡器被停止

有两篇博文写的特别好,我把链接发一下,强烈推荐大家看一下,比看我这个强多了:一个是对低功耗与中断的总结,一个是全面总结

1:http://blog.sina.com.cn/s/blog_6cd2030b01017x71.html(这个还有背景音乐)

2:http://blog.sina.com.cn/s/blog_76790d7d01012tir.html

  

三:10位AD

MSP430G2553可以8路采集AD后的电压信号,采集端口是P1.0~P1.7;

粘贴一下10位AD  8路采样模块化程序8路AD的结果存储在result[]数组里;然后根据自己的程序对result[]进行计算或者显示,这个程序是从坛友幻灵那里弄来的,留给读者自己研究吧:

 

voidinit_ADC10()

{

    P1SEL |= 0xFF;

    ADC10AE0 |= 0xF0;

    ADC10CTL0 = ADC10ON + MSC + SREF_0 + REFON;

    //开AD内核,选择电源为参考电压

    ADC10CTL1 = ADC10SSEL_0 + CONSEQ_0; //采用单通道多次采用

 

}

 

 

voidstart_ADC10()

{

    ADC10CTL1 |= INCH_0;

    ADC10CTL0 |= ADC10SC + ENC; // 开始转换  开转换允许

    while (ADC10CTL1 & ADC10BUSY != 0)

              ; //判断是否转换完毕

    result[0] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC); //关转换允许才能选择通道

    ADC10CTL1 &= ~INCH_0; //通道清0

    ADC10CTL1 |= INCH_1;

    ADC10CTL0 |= ADC10SC + ENC;

    while (ADC10CTL1 & ADC10BUSY != 0)

              ;

    result[1] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC);

    ADC10CTL1 &= ~INCH_1;

    ADC10CTL1 |= INCH_2;

    ADC10CTL0 |= ADC10SC + ENC;

    while (ADC10CTL1 & ADC10BUSY != 0)

              ;

    result[2] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC);

    ADC10CTL1 &= ~INCH_2;

    ADC10CTL1 |= INCH_3;

    ADC10CTL0 |= ADC10SC + ENC;

    while (ADC10CTL1 & ADC10BUSY != 0)

              ;

    /*result[3] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC);

    ADC10CTL1 &= ~INCH_3;

    ADC10CTL1 |= INCH_4;

    ADC10CTL0 |= ADC10SC + ENC;

    while (ADC10CTL1 & ADC10BUSY != 0)

              ;

    result[4] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC);

    ADC10CTL1 &= ~INCH_4;

    ADC10CTL1 |= INCH_5;

    ADC10CTL0 |= ADC10SC + ENC;

    while (ADC10CTL1 & ADC10BUSY != 0)

              ;

    result[5] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC);

    ADC10CTL1 &= ~INCH_5;

    ADC10CTL1 |= INCH_6;

    ADC10CTL0 |= ADC10SC + ENC;

    while (ADC10CTL1 & ADC10BUSY != 0)

              ;

    result[6] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC);

    ADC10CTL1 &= ~INCH_6;

    ADC10CTL1 |= INCH_7;

    ADC10CTL0 |= ADC10SC + ENC;

    while (ADC10CTL1 & ADC10BUSY != 0)

              ;

    result[7] = ADC10MEM;

    ADC10CTL0 &= ~(ADC10SC + ENC);

    ADC10CTL1 &= ~INCH_7;*/

 

}

这篇关于电赛MSP430知识小结的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/977028

相关文章

Java调用Python代码的几种方法小结

《Java调用Python代码的几种方法小结》Python语言有丰富的系统管理、数据处理、统计类软件包,因此从java应用中调用Python代码的需求很常见、实用,本文介绍几种方法从java调用Pyt... 目录引言Java core使用ProcessBuilder使用Java脚本引擎总结引言python

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

Redis的Hash类型及相关命令小结

《Redis的Hash类型及相关命令小结》edisHash是一种数据结构,用于存储字段和值的映射关系,本文就来介绍一下Redis的Hash类型及相关命令小结,具有一定的参考价值,感兴趣的可以了解一下... 目录HSETHGETHEXISTSHDELHKEYSHVALSHGETALLHMGETHLENHSET

python中cv2.imdecode()与cv2.imencode()的使用小结

《python中cv2.imdecode()与cv2.imencode()的使用小结》本文介绍了cv2.imencode()和cv2.imdecode()函数的使用,文中通过示例代码介绍的非常详细,对... 目录1、图片路径带中文的读取和写入1.1 读取1.2 写入2、在网络中传输图片cv2.imencod

Java将时间戳转换为Date对象的方法小结

《Java将时间戳转换为Date对象的方法小结》在Java编程中,处理日期和时间是一个常见需求,特别是在处理网络通信或者数据库操作时,本文主要为大家整理了Java中将时间戳转换为Date对象的方法... 目录1. 理解时间戳2. Date 类的构造函数3. 转换示例4. 处理可能的异常5. 考虑时区问题6.

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

sqlite3 相关知识

WAL 模式 VS 回滚模式 特性WAL 模式回滚模式(Rollback Journal)定义使用写前日志来记录变更。使用回滚日志来记录事务的所有修改。特点更高的并发性和性能;支持多读者和单写者。支持安全的事务回滚,但并发性较低。性能写入性能更好,尤其是读多写少的场景。写操作会造成较大的性能开销,尤其是在事务开始时。写入流程数据首先写入 WAL 文件,然后才从 WAL 刷新到主数据库。数据在开始

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

分布式系统的个人理解小结

分布式系统:分的微小服务,以小而独立的业务为单位,形成子系统。 然后分布式系统中需要有统一的调用,形成大的聚合服务。 同时,微服务群,需要有交流(通讯,注册中心,同步,异步),有管理(监控,调度)。 对外服务,需要有控制的对外开发,安全网关。

【Python知识宝库】上下文管理器与with语句:资源管理的优雅方式

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、什么是上下文管理器?二、上下文管理器的实现三、使用内置上下文管理器四、使用`contextlib`模块五、总结 前言 在Python编程中,资源管理是一个重要的主题,尤其是在处理文件、网络连接和数据库