电赛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判断多个时间段是否重合的方法小结

《Java判断多个时间段是否重合的方法小结》这篇文章主要为大家详细介绍了Java中判断多个时间段是否重合的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录判断多个时间段是否有间隔判断时间段集合是否与某时间段重合判断多个时间段是否有间隔实体类内容public class D

SpringBoot中使用 ThreadLocal 进行多线程上下文管理及注意事项小结

《SpringBoot中使用ThreadLocal进行多线程上下文管理及注意事项小结》本文详细介绍了ThreadLocal的原理、使用场景和示例代码,并在SpringBoot中使用ThreadLo... 目录前言技术积累1.什么是 ThreadLocal2. ThreadLocal 的原理2.1 线程隔离2

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

JS 实现复制到剪贴板的几种方式小结

《JS实现复制到剪贴板的几种方式小结》本文主要介绍了JS实现复制到剪贴板的几种方式小结,包括ClipboardAPI和document.execCommand这两种方法,具有一定的参考价值,感兴趣的... 目录一、Clipboard API相关属性方法二、document.execCommand优点:缺点:

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

MyBatis-Flex BaseMapper的接口基本用法小结

《MyBatis-FlexBaseMapper的接口基本用法小结》本文主要介绍了MyBatis-FlexBaseMapper的接口基本用法小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具... 目录MyBATis-Flex简单介绍特性基础方法INSERT① insert② insertSelec

Java通过反射获取方法参数名的方式小结

《Java通过反射获取方法参数名的方式小结》这篇文章主要为大家详细介绍了Java如何通过反射获取方法参数名的方式,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、前言2、解决方式方式2.1: 添加编译参数配置 -parameters方式2.2: 使用Spring的内部工具类 -

Python给Excel写入数据的四种方法小结

《Python给Excel写入数据的四种方法小结》本文主要介绍了Python给Excel写入数据的四种方法小结,包含openpyxl库、xlsxwriter库、pandas库和win32com库,具有... 目录1. 使用 openpyxl 库2. 使用 xlsxwriter 库3. 使用 pandas 库

java中不同版本JSONObject区别小结

《java中不同版本JSONObject区别小结》本文主要介绍了java中不同版本JSONObject区别小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们... 目录1. FastjsON2. Jackson3. Gson4. org.json6. 总结在Jav

Python中操作Redis的常用方法小结

《Python中操作Redis的常用方法小结》这篇文章主要为大家详细介绍了Python中操作Redis的常用方法,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解一下... 目录安装Redis开启、关闭Redisredis数据结构redis-cli操作安装redis-py数据库连接和释放增