430G2231实验辅导.docx
《430G2231实验辅导.docx》由会员分享,可在线阅读,更多相关《430G2231实验辅导.docx(19页珍藏版)》请在冰豆网上搜索。
430G2231实验辅导
实验1
∙实验1的代码较长,一开始不需要全部弄懂
∙该实验的目的是熟悉项目的建立、编译和下载
∙修改好代码之后,进行以下操作
oProject-BuildAll,编译代码
oRun-Debug,下载代码,此时编译好的二进制代码下载到芯片内部,处理器Halt在main()函数的入口。
oRun-Resume,运行代码,此时会看到电路板上有一个红色和一个绿色的LED灯交替闪烁。
实验2
简介
∙实验2的目的是设定时钟。
为了低功耗,MSP430可以使用不同速率的时钟源,在计算任务密集时用高速时钟,在空闲时用低速时钟。
∙通过设定寄存器的值来设定选择哪个时钟源作为处理器的工作时钟。
∙MSP430片内自带有一个RC振荡器,称为DCO,由于集成电路工艺的精度限制,每个430芯片中,该振荡器的震荡频率不一致。
所以每个430芯片的FLASH存储器中固化了两个校正数据,分别存放于CALBC1_1MHZ和CALDCO_1MHZ两个位置。
这两个位置的数据在出厂的时候被写成校准值,但是如果用户把它们清除了(通常FLASH的擦除会把内容置为0xff),那么这颗芯片就无法再得到准确的时钟频率了。
∙为了做到低功耗,所以无法设计出
实验现象
∙该代码正常运行后,可以看到一个绿色LED以较快的频率不停的闪烁
代码
//******************************************************************************
//LaunchPadLab2-SoftwareToggleP1.0,
//
//MSP430G2xx2
//-----------------
///|\|XIN|-
//|||
//--|RSTXOUT|-
//||
//|P1.0|-->LED
//
//******************************************************************************
#include
voidmain(void)
{
WDTCTL=WDTPW+WDTHOLD;//Stopwatchdogtimer
if(CALBC1_1MHZ==0xFF||CALDCO_1MHZ==0xFF)
{
while
(1);//Ifcalibrationconstantserased,trapCPU!
!
}
//ConfigureBasicClock
BCSCTL1=____________;//Setrange
DCOCTL=_____________;//SetDCOstep+modulation
BCSCTL3|=LFXT1S_2;//SetLFXT1
P1DIR=BIT6;//P1.6output(greenLED)
P1OUT=0;//LEDoff
IFG1&=~OFIFG;//ClearOSCFaultflag
BCSCTL2|=________+DIVM_3;//SetMCLK
for(;;)
{
P1OUT=BIT6;//P1.6on(greenLED)
_delay_cycles(100);
P1OUT=0;//greenLEDoff
_delay_cycles(5000);
}
}
关于设定C语言变量特定比特位
∙对于一个寄存器,它的某个特定的比特位都是有具体的意义,需要单独进行设定。
∙一般来说,寄存器会被映射成C程序的变量,我们通过设定这些变量的具体内容来配置寄存器。
∙在阅读代码时,请注意代码中预先定义的宏的值,某些数值是有特别的作用。
例如0x04可以把比特2置为1(最低位是比特0),0x08可以把比特3置1,而0x04+0x08可以把比特2、3一起置为1.。
关于存储器映射寄存器的访问
∙首先,CPU中的寄存器都要进行编址,即所有的寄存器都要有个地址
∙读写这些编址的寄存器就像读写一个内存地址的内容
∙这种寄存器叫做存储器映射寄存器
∙如何在C语言中对这样的寄存器读/写呢?
以Lab2中的BCSCTL2寄存器为例,下面来探究一下
∙Lab2.c文件中:
BCSCTL2|=SELM_1+DIVM_3
∙msp430g2231.h文件中:
SFR_8BIT(BCSCTL2);/*BasicClockSystemControl2*/
o#defineSFR_8BIT(address)externvolatileunsignedcharaddress
o#defineSELM_1(0x40)/*MCLKSourceSelect1:
DCOCLK*/
o#defineDIVM_3(0x30)/*MCLKDivider3:
/8*/
o从中可以看到SELM_1和DIVM_3是两个常量,而BCSCTL2的具体值没有看到
∙关键字释义
oextern表示在外部定义的变量,通常是在其他的*.obj和*.lib文件中
ovolatile:
表示不允许编译器优化这个变量,例如以下代码:
▪inta;intb;b=a+1;b=b-a;
▪编译器扫描代码之后会发现实际上b=1。
如果声明了a是volatile类型,会告知编译器不要随意对a的值进行假设,则a不会被优化掉。
volatile关键字通常用来声明某些外设或特殊的寄存器,通常不用来声明普通变量
▪比如在上面的代码中,如果a代表一个通用管脚上的电平值。
那么在b=a+1;和b=b-a之间的时刻,a的值可能会改变,所以b变量未必恒定为1,所以要声明a变量为volatileinta;
∙手册MSP430x2xxFamilyUser'sGuide
o5.3BasicClockModule+Registers
oTable5-1.BasicClockModule+Registers
Register
ShortForm
RegisterType
Address
InitialState
Basicclocksystemcontrol2
BCSCTL2
Read/write
058h
ResetwithPUC
∙编译后在Debug目录中的.map文件,描述编译之后的内存布局情况
∙仔细观察,可以发现map文件主要描述
o内存分成几个部分(MEMORYCONFIGURATION),起始位置和大小
o区段的映射(SECTIONALLOCATIONMAP)
o全局的符号表(GLOBALSYMBOLS),名字和地址,其中有这一行:
00000058BCSCTL2
o看到这里,应当知道了,BCSCTL2是一个地址为0x58的全局符号,请思考这对应C语言里面的什么语法元素呢?
∙编译后在Debug目录中的.objects.mk文件,有这一行LIBS:
=$(GEN_CMDS__FLAG)-l"libc.a",这是C语言的支持库(之一)
∙在ti\ccsv5\tools\compiler\msp430\lib中可以发现libc.a文件
∙cmd文件探索
ocmd文件是linkcommandfile的缩写,link是从源代码向二进制代码转换过程中的一个环节
olink前面的过程是compile,该过程把各个源代码生成obj文件,每个obj文件描述了一些逻辑,比如根据一部分变量的值来计算
o项目的cmd文件lnk_msp430g2231.cmd中,没有关于BCSCTL2的描述,但是在最后一行里面有一行-lmsp430g2231.cmd,这说明当前cmd文件还要引用其他的cmd文件。
o搜索,发现msp430g2231.cmd文件位于ti\ccsv5\ccs_base\msp430\include目录中
omsp430g2231.cmd中有一行:
BCSCTL2=0x0058;
∙关于MSP430编译器的工作原理,详细的说明在以下两个文档里面
oMSP430AssemblyLanguageToolsv4.0User'sGuide
oMSP430OptimizingC/C++Compilerv4.0User'sGuide
o注意:
如果为了快速的掌握处理器的应用开发,然后去参加比赛,你不需要过早的仔细阅读以上两个文档,因为如果不做东西,看过了也会忘记。
o知识是慢慢积累的,为了完成任务够用就好。
∙那么为什么还要写这个文字?
o为了展示如何深入的探究一个问题?
o给出需要查阅哪些资料以及如何查阅这些资料的一个示范。
o要善于用于搜索的功能(Ctrl+F)
实验3
简介
∙实验3的目的是中断响应。
关于中断
∙回忆51单片机的中断,并且在430上找到类似的情况,(其他的处理器诸如各种DSP,ARM的各个系列对中断服务的设计也是类似,没有本质区别)关于处理器的中断通常有以下的情况
∙会有多个中断源,分别表示不同的事件发生
∙中断可以使电平(信号的值)的触发,也可以是边沿(信号值的改变情况)的触发
∙要有中断向量表,不同的中断产生的时候,处理器会进入相应的中断地址。
∙有些中断时可以被屏蔽(不响应它),有些中断是不可以屏蔽的,比如复位或掉电。
∙会有一个全局的中断使能,这个是响应中断的总开关。
∙每个可屏蔽的中断应当有自己的使能寄存器,这个是每个中断独立的开关。
∙通常每个中断信号会有自己的中断向量地址,如果中断信号很多,对于一些优先级较低的中断信号,可以共享一个中断地址,那么当处理器从这个地址执行时,如何分辨到底是哪个中断信号有效了呢,可以在给这个中断地址配一个状态寄存器,这个寄存器的值由中断的硬件电路根据中断产生的情况写入,CPU读取这个寄存器的值就可以知道哪个中断产生了。
∙通常工具链(编译器、连接器)会提供某种方法,比如扩展C语言的关键字,或是使用编译伪指令(#pragma)
关于看门狗WatchDog
∙为了防止系统死机或者是由于各种干扰造成的程序跑飞,某些单片机带有看门狗的功能,这种功能是可以启用或关闭的,但是需要注意的是系统复位后看门狗的默认状态,如果默认是开启,你必须做出相应的配置,否则它可能会将系统复位。
∙看门狗是这样一种电路,通常它有一个定时器,一个中断源,另外它还有连接系统复位信号的电路。
∙如果启用了看门狗电路,则它的计时器会进行计数,如果计时器溢出了,则会触发一个中断。
∙用户可以在看门狗的中断复位例程里面执行一些操作,比如把看门狗定时器清零,让它重新计数(称作喂狗),或是干脆关闭看门狗。
∙如果看门狗的定时器溢出了,而用户在一定的时间里没有喂狗,这时看门狗会认为系统跑飞了,于是会把系统复位。
实验现象
本实验正确完成后,按下开发板的P1.3按键,有一个LED灯会点亮,再次按下会熄灭。
代码
注意:
以一个或两个下划线开头的变量或函数名称表示工具链内建的符号,通常不要自行定义这种以下划线开头的变量或函数
//******************************************************************************
//LaunchPadLab3-SoftwarePortInterruptService
//
//MSP430G2xx2
//-----------------
///|\|XIN|-
//|||
//--|RSTXOUT|-
///|\||
//--o--|P1.3P1.0|-->LED
//\|/
//
//******************************************************************************
#include
voidmain(void)
{
WDTCTL=WDTPW+WDTHOLD;//Stopwatchdogtimer
P1DIR|=BIT0;//SetP1.0tooutputdirection
P1IES|=BIT3;//P1.3Hi/loedge
_____&=~BIT3;//P1.3IFGcleared
_____|=BIT3;//P1.3interruptenabled
_BIS_SR(LPM4_bits+GIE);//EnterLPM4w/interrupt
}
//Port1interruptserviceroutine
#pragmavector=_____________
__interruptvoidPort_1(void)
{
if(P1IFG&BIT3)
{
P1OUT^=BIT0;//P1.0=toggle
______&=~BIT3;//P1.3IFGcleared
}
}
实验4
简介
本实验训练定时器的应用
关于定时器的工作模式
∙如果我们用硬件描述语言自己做一个计数器,我们可以有如下的功能,增加计数,减少计数,当定时器完成一次计数周期后,可以自动装载,也可保持不动,如果有多个定时器,还可能存在一个定时器的计数值需要另一个定时器的溢出事件来触发其改变(本质上是2个级联的计数器)。
∙处理器的定时器通常是支持上面说的所有功能,但是需要用户通过配置寄存器来选择启用那一种。
∙另外,对于常见的情况,有时还会使用定时间对输入信号进行比较和捕获
比较模式
∙最普通的定时器的工作方式就是周期性的溢出。
∙思考如下的工作场景
o在定时器的一个计数周期里面,例如从0计数到MAX
o我们需要在计数值为MAX/8的时候,执行某个代码段A
o我们需要在计数值为MAX/6的时候,执行某个代码段B
o我们需要在计数值为MAX/2的时候,执行某个代码段C
o我们需要在计数值为XXX时候,执行某个代码段XXX
∙如果定时器没有比较功能,则需要CPU一直不停的查询计数器的值,然后做出判断,实际上这是一种软件形式的比较,但是这样很费电。
∙如果定时器有比较功能,则只需要设定合适的比较值,在满足比较条件的时刻触发中断,然后再让CPU来执行相应的代码段就好了,剩下的时间CPU可以休眠。
捕获模式
∙思考如下的工作场景
o在定时器的一个计数周期里面,例如从0计数到MAX
o当某个事件第1次发生的时候,计数值为V1
o当某个事件第2次发生的时候,计数值为V2
o当某个事件......
∙用户对事件发生的时间间隔感兴趣
∙于是希望硬件电路可以自动的把事件发生时刻的计数值保存到某个寄存器里面,然后触发一次中断让CPU过来处理。
∙当然,也可以这样做,直接让这个事件触发一次中断,CPU响应这个中断,然后读取定时器的计数值。
但是这样做的缺点是从这个事件发生到CPU读取到计数值的过程中,需要执行很多条CPU的指令,此时计数器又已经计了若干的数,所以CPU读到的计数值并不是事件发生那个时刻的,而是滞后了一些,也就是说不准确。
实验现象
∙该代码正常运行后,可以看到一个绿色LED以较慢的频率不停的闪烁,并且在一个周期里面,亮的时间短,暗的时间长。
代码
//******************************************************************************
//LaunchPadLab4-TimerToggleP1.6,
//
//MSP430G2452
//-----------------
///|\|XIN|-
//|||
//--|RSTXOUT|-
//||
//|P1.6|-->LED
//
//******************************************************************************
#include
voidmain(void)
{
WDTCTL=WDTPW+WDTHOLD;//Stopwatchdogtimer
if(CALBC1_1MHZ==0xFF||CALDCO_1MHZ==0xFF)
{
while
(1);//Ifcalibrationconstantserased,trapCPU!
!
}
BCSCTL1=CALBC1_1MHZ;//Setrange
DCOCTL=CALDCO_1MHZ;//SetDCOstep+modulation
BCSCTL3|=LFXT1S_2;//LFXT1=VLO
P1DIR=0x40;//P1.6output(greenLED)
P1OUT=0;//LEDoff
IFG1&=~OFIFG;//ClearOSCFaultflag
BCSCTL1|=DIVA_3;//ACLK=VLO/8
BCSCTL2|=SELM_3+DIVM_3+DIVS_3;//MCLK=DCO/8,SMCLK=DCO/8
//ConfigureTimerA
TACTL=__________________;//Source:
ACLK,UPmode
CCR0=5100;//Timercount5100
CCR1=100;//Timercount100
CCTL0=CCIE;//CCR0interruptenabled
CCTL1=CCIE;//CCR1interruptenabled
_BIS_SR(GIE);
for(;;);
}
//TimerA0interruptserviceroutine
#pragmavector=________________
__interruptvoidTimer_A0(void)
{
P1OUT|=BIT6;//P1.6outputHigh
}
//TimerA1InterruptVector(TA0IV)handler
#pragmavector=_______________
__interruptvoidTimer_A1(void)
{
switch(TA0IV)
{
case2:
P1OUT&=~BIT6;//P1.6outputLow
break;
case10:
break;
}
}
实验5
简介
实验5关于处理器的低功耗模式
关于低功耗的数字电路
∙数字电路的功耗中存在两种来源,分别成为静态功耗和动态功耗
∙动态功耗是指当一个逻辑门的输出值发生反转时(从0到1从1到0)会消耗能量
o究其原因是因为逻辑门等效的阻容电路的充放电。
电容发生充放电就会有电荷流动
o电阻上有电荷流过就会释放热量。
o动态功耗与
成正比,其中f是数字电路的工作频率,C是整个电路等效出来的电容,V是供电电压。
o从中可以看到,低功耗的数字电路应当工作在低频率、低电压下,电路的等效电容由集成电路工艺和电路尺寸决定,一旦芯片生产出来之后就无法再改变了。
o为了降低动态功耗,现代数字电路的供电电压日益降低,为了降低等效电容,采用低介电常数(low-k)的工艺。
为了让芯片在待机的情况下不费电,可以把电路的时钟关闭(clock-gating技术)使得所有的信号逻辑都保持原值。
∙静态功耗是指,即使电路所有的门都不发生反转,只要接上了电压和地线,那么还是会有电流从芯片的VCC和GND之间通过(称作漏电流),从而费电发热。
o为了降低静态功耗,现代集成电路采用了电源关闭(powergating)技术和多电压技术,即当电路进入待机模式后,把电源和地线之间的通道关闭,并且把电路切换到一个较低的电压,使得电路能够保持所有信号的状态值即可,等电路进入工作模式后再打开电源通路并且切换到较高的工作电压。
CPU应用开发的低功耗策略
∙总的原则是,能不动就不动,能慢动就慢动
∙处理器会支持多种工作速率的模式,在不同的处理任务时使用不同的时钟频率
∙需要硬件电路支持多个不同速率的时钟,或者支持动态改变主时钟的速率
∙例如:
配置CPU的默认状态是休眠,当某个信号触发时,CPU唤醒进入低速率工作的检测状态,当监测到外部条件达到某个条件是,切换到高速时钟进入高速计算和控制的状态。
∙需要CPU能够快速的在不同的模式之间切换。
∙一个处理器芯片内部有不同的部件构成,通常可以有选择的把某些模块休眠(通过配置寄存器),从而省电。
∙为了方便开发者,编译工具会定义若干模式,从最省电的模式到最费电的模式,被开启的模块逐渐增多,这样开发者只需要使用工具链提供的函数,加以模式配置的参数,就可以一次性的配置好当前模式所有需要配置的寄存器。
∙需要通过阅读手册明确不同的模式中,哪些模块是被开启或关闭的,否则会得不到正确的结果。
实验现象
∙该代码正常运行后,可以看到一个绿色LED反复闪烁。
代码
//******************************************************************************
//LaunchPadLab5-TimerToggleP1.6withLowPowerMode
//
//MSP430G2452
//-----------------
///|\|XIN|-
//|||
//--|RSTXOUT|-
//||
//|P1.6|-->LED
//
//******************************************************************************
#include
voidmain(void)
{
WDTCTL=WDTPW+WDTHOLD;//Stopwatchdogtimer
if(CALBC1_1MHZ==0xFF||CALDCO_1MH