历史上的今天
返回首页

历史上的今天

今天是:2025年01月23日(星期四)

正在发生

2020年01月23日 | MSP430学习小结2-程序主体结构安排及低功耗

2020-01-23 来源:eefocus

讲解430的书现在也有很多了,不过大多数都是详细说明底层硬件结构的,看了不免有些空洞和枯燥,我认为了解一个MCU的操作首先要对其基础特性有所了解,然后再仔细研究各模块的功能。


  1.首先你要知道msp430的存储器结构。典型微处理器的结构有两种:冯。诺依曼结构——程序存储器和数据存储器统一编码;哈佛结构——程序存储器和数据存储器;msp430系列单片机属于前者,而常用的mcs51系列属于后者。


  0-0xf特殊功能寄存器;0x10-0x1ff外围模块寄存器;0x200-?根据不同型号地址从低向高扩展;0x1000-0x107f seg_b0x1080_0x10ff seg_a 供flash信息存储


  剩下的从0xffff开始向下扩展,根据不同容量,例如149为60KB,0xffff-0x1100


  2.复位信号是MCU工作的起点,430的复位型号有两种:上电复位信号POR和上电清楚信号PUC。POR信号只在上电和RST/NMI复位管脚被设置为复位功能,且低电平时系统复位。而PUC信号是POR信号产生,以及其他如看门狗定时溢出、安全键值出现错误是产生。但是,无论那种信号触发的复位,都会使msp430在地址0xffff处读取复位中断向量,然后程序从中断向量所指的地址开始执行。复位后的状态不写了,详见参考书,嘿嘿。


  3.系统时钟是一个程序运行的指挥官,时序和中断也是整个程序的核心和中轴线。430最多有三个振荡器,DCO内部振荡器;LFXT1外接低频振荡器,常见的32768HZ,不用外接负载电容;也可接高频450KHZ-8M,需接负载电容;XT2接高频450KHZ-8M,加外接电容。


  430有三种时钟信号:MCLK系统主时钟,可分频1 2 4 8,供cpu使用,其他外围模块在有选择情况下也可使用;SMCLK系统子时钟,供外围模块使用,可选则不同振荡器产生的时钟信号;ACLK辅助时钟,只能由LFXT1产生,供外围模块。


  4.中断是430处理器的一大特色,因为几乎每个外围模块都能产生,430可以在没有任务时进入低功耗状态,有事件时中断唤醒cpu,处理完毕再次进入低功耗状态。


  整个中断的响应过程是这样的,当有中断请求时,如果cpu处于活动状态,先完成当前命令;如果处于低功耗,先退出,将下一条指令的pc值压入堆栈;如果有多个中断请求,先响应优先级高的;执行完后,等待中断请求标志位复位,要注意,单中断源的中断请求标志位自动复位,而多中断的标志位需要软件复位;然后系统总中断允许位SR.GIE复位,相应的中断向量值装入pc,程序从这个地址继续执行。


  这里要注意,中断允许位SR.GIE和中断嵌套问题。如果当你执行中断程序过程中,希望可以响应更高级别的中断请求时,必须在进入第一个中断时把SR.GIE置位。


  其实,其他的外围模块时钟沿着时钟和中断这个核心来执行的。具体的结构我也不罗索了,可以参考430系列手册。


  明天开始,讲述msp430单片机C语言编程的故事


  上回把430单片机的基础特性交待了一下,让大家整体有了结构的印象,今天我想在写一下c语言对430编程的整体结构。基本上属于框架结构,即整体的模块化编程,其实这也是硬件编程的基本法则拉(可不是我规定的法则哦)。


  首先是程序的头文件,包括#include ,这是14系列,因为常用149;其他型号可自己修改。还可以包括#include "data.h" 等数据库头文件,或函数变量声明头文件,都是你自己定义的哦。


  接着就是函数和变量的声明 void Init_Sys(void);系统初始化


  系统初始化是个整体的概念,广义上讲包括所有外围模块的初始化,你可以把外围模块初始化的子函数写到Init_Sys()中,也可以分别写各个模块的初始化。但结构的简洁,最好写完系统的时钟初始化后,其他所用到的模块也在这里初始化。


void Init_Sys()
{
  unsigned int i;

  BCSCTL1&=~XT2OFF;       //打开XT2振荡器
  do
  {
  IFG1 &= ~OFIFG;             // 清除振荡器失效标志
  for (i = 0xFF; i > 0; i--); // 延时,等待XT2起振
}
while ((IFG1 & OFIFG) != 0);   // 判断XT2是否起振

BCSCTL2 =SELM_2+SELS;   //选择MCLK、SMCLK为XT2

//以下对各种模块、中断、外围设备等进行初始化

                ........................................

  _EINT(); //打开全局中断控制
}


  这里涉及到时钟问题,通常我们选择XT2为8M晶振,也即系统主时钟MCLK为8M,cpu执行命令以此时钟为准;但其他外围模块可以在相应的控制寄存器中选择其他的时钟,ACLK;当你对速度要求很低,定时时间间隔大时,就可以选择ACLK,例如在定时器Timea初始化中设置。

主程序:               void main( void )
                        {

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

                          InitSys();   //初始化

                          //自己任务中的其他功能函数

                            。。。。。。。。。。。。。。。。。。。。。

                        while(1);

                        }

  主程序之后我要讲讲中断函数,中断是你做单片机任务中不可缺少的部分,也可以说是灵魂了(夸张吗)。

              /*****************************************************************************
                各中断函数,可按优先级依次书写
                ***********************************************************************/

举个定时中断的例子:

  初始化             void Init_Timer_A(void)
                      {
                        TACTL = TASSEL0 + TACLR;         // ACLK, clear TAR
                        CCTL0 = CCIE;                 // CCR0 中断使能
                        CCR0=32768;                   //定时1s
                        TACTL|=MC0;                   //增计数模式
                        }

  中断服务           #pragma vector=TIMERA0_VECTOR
                      __interrupt void TimerA0()

                      {

                        // 你自己要求中断执行的任务

                      }

  当然,还有其他的定时,和多种中断,各系列芯片的中断向量个数也不同。


  这就是简单的整体程序框架,写得简单啦,还忘谅解,明天详细了解一下各外围模块的初始化和功能。


  整体的程序设计结构,包括了所有外围模块及内部时钟,中断,定时的初始化。具体情况大家可以根据自己的需要添加或者减少,记住,模块化设计时最有力的武器。


  这可是个人总结的经典阿,谢谢支持。因为经常使用149,所以这是149的结构,其他的再更改,根据个人需要。


/*****************************************************************************/

文件名:main.c

描述:MSP430框架程序。适用于MSP430F149,其他型号需要适当改变。

    不使用的中断函数保留或者删除都可以,但保留时应确保不要打开不需要的中断。

  

/*****************************************************************************/


//头文件

#include


//函数声明

void InitSys();



int main( void )

{


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


InitSys();   //初始化


start:

//以下填充用户代码



LPM3;   //进入低功耗模式n,n:0~4。若不希望进入低功耗模式,屏蔽本句

goto start;


}


/*****************************************************************************

系统初始化

******************************************************************************/

void InitSys()

{

  unsigned int iq0;


//使用XT2振荡器

  BCSCTL1&=~XT2OFF;       //打开XT2振荡器

  do

  {

  IFG1 &= ~OFIFG;   // 清除振荡器失效标志

  for (iq0 = 0xFF; iq0 > 0; iq0--); // 延时,等待XT2起振

}

while ((IFG1 & OFIFG) != 0);   // 判断XT2是否起振


BCSCTL2 =SELM_2+SELS;   //选择MCLK、SMCLK为XT2


//以下填充用户代码,对各种模块、中断、外围设备等进行初始化


  _EINT(); //打开全局中断控制,若不需要打开,可以屏蔽本句

}


/*****************************************************************************

端口2中断函数

******************************************************************************/

#pragma vector=PORT2_VECTOR

__interrupt void Port2()

{

//以下为参考处理程序,不使用的端口应当删除其对于中断源的判断。

if((P2IFG&BIT0) == BIT0)

{

//处理P2IN.0中断

P2IFG &= ~BIT0; //清除中断标志

//以下填充用户代码


}

else if((P2IFG&BIT1) ==BIT1)

{

//处理P2IN.1中断

P2IFG &= ~BIT1; //清除中断标志

//以下填充用户代码


}

else if((P2IFG&BIT2) ==BIT2)

{

//处理P2IN.2中断

P2IFG &= ~BIT2; //清除中断标志

//以下填充用户代码


}

else if((P2IFG&BIT3) ==BIT3)

{

//处理P2IN.3中断

P2IFG &= ~BIT3; //清除中断标志

//以下填充用户代码


}

else if((P2IFG&BIT4) ==BIT4)

{

//处理P2IN.4中断

P2IFG &= ~BIT4; //清除中断标志

//以下填充用户代码


}

else if((P2IFG&BIT5) ==BIT5)

{

//处理P2IN.5中断

P2IFG &= ~BIT5; //清除中断标志

//以下填充用户代码


}

else if((P2IFG&BIT6) ==BIT6)

{

//处理P2IN.6中断

P2IFG &= ~BIT6; //清除中断标志

//以下填充用户代码


}

else

{

//处理P2IN.7中断

P2IFG &= ~BIT7; //清除中断标志

//以下填充用户代码


}


LPM3_EXIT; //退出中断后退出低功耗模式。若退出中断后要保留低功耗模式,将本句屏蔽

}


/*****************************************************************************

USART1发送中断函数

******************************************************************************/

#pragma vector=USART1TX_VECTOR

__interrupt void Usart1Tx()

{

//以下填充用户代码



LPM3_EXIT; //退出中断后退出低功耗模式。若退出中断后要保留低功耗模式,将本句屏蔽

}


/*****************************************************************************

USART1接收中断函数

******************************************************************************/

#pragma vector=USART1RX_VECTOR

__interrupt void Ustra1Rx()

{

//以下填充用户代码



LPM3_EXIT; //退出中断后退出低功耗模式。若退出中断后要保留低功耗模式,将本句屏蔽

}


/*****************************************************************************

端口1中断函数

多中断中断源:P1IFG.0~P1IFG7

进入中断后应首先判断中断源,退出中断前应清除中断标志,否则将再次引发中断

******************************************************************************/{{分页}}

#pragma vector=PORT1_VECTOR

__interrupt void Port1()

{

//以下为参考处理程序,不使用的端口应当删除其对于中断源的判断。

if((P1IFG&BIT0) == BIT0)

{

//处理P1IN.0中断

P1IFG &= ~BIT0; //清除中断标志

//以下填充用户代码


}

else if((P1IFG&BIT1) ==BIT1)

{

//处理P1IN.1中断

P1IFG &= ~BIT1; //清除中断标志

//以下填充用户代码


}

else if((P1IFG&BIT2) ==BIT2)

{

//处理P1IN.2中断

P1IFG &= ~BIT2; //清除中断标志

//以下填充用户代码


}

else if((P1IFG&BIT3) ==BIT3)

{

//处理P1IN.3中断

P1IFG &= ~BIT3; //清除中断标志

//以下填充用户代码


}

else if((P1IFG&BIT4) ==BIT4)

{

//处理P1IN.4中断

P1IFG &= ~BIT4; //清除中断标志

//以下填充用户代码


}

else if((P1IFG&BIT5) ==BIT5)

{

//处理P1IN.5中断

P1IFG &= ~BIT5; //清除中断标志

//以下填充用户代码


}

else if((P1IFG&BIT6) ==BIT6)

{

//处理P1IN.6中断

P1IFG &= ~BIT6; //清除中断标志

//以下填充用户代码


}

else

{

//处理P1IN.7中断

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

//以下填充用户代码


}


LPM3_EXIT; //退出中断后退出低功耗模式。若退出中断后要保留低功耗模式,将本句屏蔽

}


/*****************************************************************************

推荐阅读

史海拾趣

Eby Company公司的发展小趣事

1995年,皮埃尔·奥米迪亚(Pierre Omidyar)以AuctionWeb的名字推出了eBay,最初只是一个在线拍卖个人物品的平台。随着互联网的普及和用户对在线交易需求的增长,eBay迅速吸引了大量用户。其独特的商业模式和用户友好的界面使eBay成为在线拍卖市场的领军者。1998年,eBay成功上市,成为当时最成功的互联网公司之一。

明波通信(BWAVE)公司的发展小趣事

在2002年,一群从海外归来的留学生和技术专家,怀揣着对通信技术的热情与梦想,在上海创立了明波通信技术股份有限公司。他们深知国内在通信领域的技术与海外相比还有较大差距,因此决心将自己在海外学到的先进知识和经验,应用到国内的市场和技术创新中。明波通信从创立之初就致力于数字电视芯片的研究与开发,并逐渐在行业中崭露头角。

Cedrat Technologies公司的发展小趣事

海洋勘探、水下通信和声学测量等领域对精准探测和数据采集有着极高的要求。Cedrat Technologies凭借其高性能压电陶瓷传感器技术,成功开发出用于声纳阵列系统的探测和成像设备。这些设备能够精确接收和分析水下环境中的声波,实现目标探测和数据采集。这一创新应用不仅拓展了电子行业的应用范围,也为海洋科学研究和工程实践提供了有力的技术支持。

BH Electronics公司的发展小趣事

BH Electronics的创立源于创始人李明对电子技术的深厚兴趣和敏锐洞察。在20世纪90年代初,电子市场刚刚起步,李明凭借对市场的精准判断,决定投身于这一新兴行业。他带领一支小团队,在简陋的办公室中开始了艰苦的创业历程。他们昼夜兼程,研发出了一款具有竞争力的电子元件,成功打开了市场的大门。虽然初期资金匮乏,市场认可度低,但李明和他的团队凭借坚韧不拔的精神,逐步在市场中站稳了脚跟。

DLP Design公司的发展小趣事

DLP科技,一家以DLP技术为核心的创新设计公司,在电子行业的快速发展中崭露头角。公司创始人李博士,凭借对DLP技术的深入研究和独到见解,带领团队开发出了一系列具有革命性的产品。从最初的DLP投影机到后来的无屏电视,DLP科技不断突破技术瓶颈,引领市场潮流。通过持续的创新和研发,DLP科技在电子行业树立了技术领先的地位。

ALLIED [Allied Electronics]公司的发展小趣事

DLP联合科技公司,通过与国内外知名企业的技术合作,实现了技术的快速迭代和产品的升级换代。公司积极寻求与产业链上下游企业的合作机会,共同研发新技术、新产品。通过与合作伙伴的紧密合作,DLP联合科技在DLP技术领域取得了显著成果,为电子行业的发展做出了积极贡献。

问答坊 | AI 解惑

请大家帮忙看看程序和对应的电路是否可以实现

感谢大家的热情帮忙,按上次各位的指教对程序做了修改,大家再帮忙看看 单片机控制继电器的电路省略,程序在附件 //晶振12MHZ 功能: 1.外中断INT1产生后,M1启动,延时3秒后,M2也启动 2.定时器T0,每50ms发送一次脉冲 3.按钮控制电机正反 ...…

查看全部问答>

基于586-Engine的无人机飞行控制器设计

在无人机飞行控制系统中,飞行控制器是其核心部件,它负责飞行控制系统信号的采集、控制律的解算、飞机的姿态和速度,以及与地面设备的通讯等工作。随着无人机越来越广泛的应用,它所完成的任务也越来越复杂,对无人机的机动性要求也越来越高,这就 ...…

查看全部问答>

Windows Embedded Compact 7安装手记

新一代的Windows CE被命名为Windows Embedded Compact 7,发布于2010年6月1日的COMPUTEX TAIPEI国际电脑展。在微软内部的代号是Chelan,微软早在2008年就开始在北京招兵买马,2010年终于公开了一个Release : Public Community Technology Preview ...…

查看全部问答>

DMA可以使用带cache的内存吗?

    为了分配一块内存给DMA使用,一般用这两个函数分配内存 HalAllocateCommonBuffer,AllocPhysMem。这两个都函数可同时返回物理地址和虚拟地址。但这两个函数分配的内存都是uncached。     DMA应该是不使用cache的吧。如果 ...…

查看全部问答>

vxWorks 系统时钟使用问题

在vxWorks系统中,我想使用定时器实现200us到1ms的定时器,就是说定时器的时间间隔可变,从200us到1ms可设置,使用辅助时钟只有几个时间间隔可选,不能实现200us到1ms的可变范围,不知还有什么好的办法没有?        &nbs ...…

查看全部问答>

如何读写oneNand flash

是否要通过寄存器命令来控制FLASH? oneNand flah的寄存器是怎么分布的?比如说base_address是0x00,地址寄存器是0x00+4这样的。 另外,我看了DATASHEET,里面指示了寄存器地址,比如manufacturer ID寄存器地址是0xf000,这是个什么地址?…

查看全部问答>

在pb里面添加了usb鼠标,光电鼠标能亮,但是不能移动。。。

我用的是WinCE 4.2,如下操作Core OS -> Display based devices -> Core OS Services -> USB Host Support -> USB Human Input Device (HID) Class Driver添加了usb鼠标的驱动,重新定制平台,生成镜像,烧到板子里重启后,光电鼠标能亮,但是不能移 ...…

查看全部问答>

请教如何解决多源驱动

如题,谢谢,请高手赐教,感激不尽,另外,在锁存时,用上升沿锁存或者电平来锁存时如何解决锁存信号的初始值赋值。…

查看全部问答>

用ADC12做三相电表

有谁用ADC12做过电力监测方面的产品?或三相电表?…

查看全部问答>

小弟求一个简单点的LC振荡电路

想用LC振荡原理来做个测电容的 LC振荡电路设计不出来…

查看全部问答>