MSP430F5529实验指导书(V1.0) 下载本文

东北林业大学 “3+1”实验班

MSP430F5529 实验指导书

(V1.0)

2014年10月27日

东北林业大学机电工程学院“3+1”实验室

1

东北林业大学 “3+1”实验班

实验一 基础GPIO实验

实验二 键盘与液晶显示实验

实验三 时钟系统配置实验

实验四

实验五

实验六

实验七

实验八

看门狗与定时器实验 AD/DA实验 比较器实验 Flash实验 串行通信实验 2

东北林业大学 “3+1”实验班

实验一 基础GPIO实验

【实验目的】

1、熟悉CCS的基本使用方法;

2、掌握MSP430系列单片机程序开发的基本步骤; 3、掌握MSP430 IO口的基本功能。

【实验仪器】

1、SEED-EXP430F5529v1.0开发板一套;

2、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

CCS(Code Composer Studio)是 TI 公司研发的一款具有环境配置、源文件编辑、程序调试、跟踪和分析等功能的集成开发环境,能够帮助用户在一个软件环境下完成编辑、编译、链接、调试和数据分析等工作。CCSv5.1 为 CCS 软件的最新版本,功能更强大、性能更稳定、可用性更高,是 MSP430 软件开发的理想工具。

SEED-EXP430F5529v1.0开发板上的有8个可操作的LED灯,与MCU的IO口对应关系如图1-1所示:

图1-1 LED与MCU的IO对应关系电路

3

东北林业大学 “3+1”实验班

我们可以通过控制单片机IO口的输出电平状态来控制各个LED灯的亮灭。 开发板上还有2个可操作的按键S1,S2。如图1-2所示。

图1-2 按键电路

我们可以通过读取与按键相连的IO口的输入电平状态来执行相应的操作。此外,S1,S2还可以作为外部中断源,触发中断。

【实验内容】

1、用调用头文件的方法,使能MSP430F5529开发板上的8个LED灯依次按顺序循环点亮;

2、用按键S1控制开发板上LED1的亮灭状态(查询法); 3、用按键S2控制开发板上跑马灯的循环速度(中断方式)。

【实验步骤】

内容1:使能开发板上的8个LED灯依次按顺序循环点亮

1、打开CCSv5并确定工作区间,然后选择File-->New-->CCS Project 弹出图1-3对话框。

4

东北林业大学 “3+1”实验班

图1-3 新建一个CCS工程

2、在 Project name 中输入新建工程的名称,在此输入 lab1_1。

3、在 Device 部分选择器件的型号:在此Family选择MSP430;Variant选择MSP430X5XX family,芯片选择MSP430F552;其余保持默认。 4、在左下角对话框中,选择Empty Projects下拉菜单下的Empty Project(空工程),单击Finish。

5、在新窗口中输入如下代码:

#include void main(void) {

volatile unsigned int i;

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

P1DIR |= BIT0; //配置P1.0为输出功能

P8DIR |= BIT1 + BIT2; //配置P8.1,P8.2为输出功能 P1DIR |= BIT1 + BIT2 + BIT3 +BIT4 +BIT5; while(1) {

P1OUT = BIT0;

__delay_cycles(500000); //延时 P1OUT &= ~BIT0;

5

东北林业大学 “3+1”实验班

P8OUT = BIT1;

__delay_cycles(500000); //延时 P8OUT = BIT2;

__delay_cycles(500000); //延时 P8OUT &= ~BIT2;

for(i=BIT1;i<=BIT5; i=i<<1) {

P1OUT = i;

__delay_cycles(500000); //延时 } } }

6、保存程序后Bulid(单击菜单中 7、调试程序(单击菜单中 8、运行程序(单击菜单中

,或快捷键Ctrl+B)编译程序。

)自动进入调试界面并下载程序。

)进行

程序的运行、暂停、停止、单步运行等操作。 9、观察实验现象,回顾操作步骤。

内容2:用按键S1控制开发板上LED1的亮灭状态(查询法)

1、关闭上一个工程(在Project Explorer窗口,右键 Close Project)。 2、建立新工程,步骤同上,并命名为lab1_2。 3、在新建工程的编辑窗口输入如下代码:

#include

volatile unsigned int flag=0; //定义按键标志位 void Keyscan(); //申明按键检测函数 void main(void) {

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

P1DIR |= BIT0; //配置P1.0为输出功能 P1OUT &= ~BIT0; //初始化禁止LED0亮 /*按键初始化*/ //P1DIR &= ~BIT7; P1OUT |= BIT7;

P1REN |= BIT7; //设置为内部上拉 while(1) {

Keyscan(); //按键检测 if(flag != 0)

P1OUT |= BIT0; else

P1OUT &= ~BIT0;

6

东北林业大学 “3+1”实验班

} }

void Keyscan() //按键检测函数 {

if((P1IN & BIT7) == 0) {

__delay_cycles(10000); //延时10ms if((P1IN & BIT7) == 0) {

while((P1IN & BIT7) == 0);//等待按键抬起 flag = ~flag; //按键标志位取反 } } }

4、编译、调试并下载程序到开发板。 5、运行程序,观察现象。

内容3:用按键S2控制开发板上跑马灯的循环速度(中断方式)

1、建立新工程,步骤同上,并命名为lab1_3。 2、在新建工程的编辑窗口输入如下代码:

#include

unsigned char flag = 0; //定义按键标志位 void main() {

WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗 P1DIR |= BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5; P1OUT &=~ (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5); P8DIR |= BIT1 + BIT2;

P8OUT &=~ (BIT1 + BIT2); //初始化LED /*按键中断初始化*/

P1DIR &= ~BIT7; //配置P1.7为按键输入 P1OUT |= BIT7;

P1REN |= BIT7; //设置为内部上拉 P1IE |= BIT7; //P1.7中断使能

P1IFG &=~ BIT7; //清除P1.7的中断标志位 P1IES |= BIT7; //置1,设置为下降沿触发 __enable_interrupt();

while (1) {

P1OUT |= BIT0; P1OUT &=~ BIT5; if(flag ==0)

__delay_cycles(1000000);//闪烁

7

东北林业大学 “3+1”实验班

else

__delay_cycles(200000); P8OUT |= BIT1; P1OUT &=~ BIT0; if(flag ==0)

__delay_cycles(1000000);//闪烁 else

__delay_cycles(200000); P8OUT |= BIT2 ; P8OUT &=~ BIT1; if(flag ==0)

__delay_cycles(1000000);//闪烁 else

__delay_cycles(200000); P1OUT |= BIT1; P8OUT &=~ BIT2; if(flag ==0)

__delay_cycles(1000000);//闪烁 else

__delay_cycles(200000); P1OUT |= BIT2; P1OUT &=~ BIT1; if(flag ==0)

__delay_cycles(1000000);//闪烁 else

__delay_cycles(200000); P1OUT |= BIT3; P1OUT &=~ BIT2; if(flag ==0)

__delay_cycles(1000000);//闪烁 else

__delay_cycles(200000); P1OUT |= BIT4; P1OUT &=~ BIT3; if(flag ==0)

__delay_cycles(1000000);//闪烁 else

__delay_cycles(200000); P1OUT |= BIT5; P1OUT &=~ BIT4; if(flag ==0)

__delay_cycles(1000000);//闪烁 else

__delay_cycles(200000);

8

东北林业大学 “3+1”实验班

} }

#pragma vector = PORT1_VECTOR __interrupt void PORT_1(void) {

__delay_cycles(300);

while((P1IE & BIT7) == 0); //等待按键释放 if(flag==1) flag = 0; else

flag = 1;

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

3、编译、调试并下载程序到开发板。 4、运行程序,观察现象。

【思考与分析】

1、在实际应用当中,一般将未用的IO口设置为输出状态,为什么?试查阅资料加以研究。

2、在用查询法检测按键时,为什么要连续检测两次并在此期间加上10ms左右的延时?

3、试编写程序,用开发板上的两个按键及8个LED灯设计一个可控的跑马灯系统。其中,一个按键控制LED灯的流水速度(至少两种流水速度可调),另一个按键控制LED灯的流水方式(至少3种流水方式可调)。

9

东北林业大学 “3+1”实验班

实验二 键盘与液晶显示实验

【实验目的】

1、学习键盘及液晶与MCU硬件电路的连接方法; 2、掌握键盘控制芯片CH452的键盘检测方法; 3、掌握TFT2.2真彩液晶屏的使用方法; 4、了解SPI总线的通信模式和基本特点。

【实验仪器】

1、MSP430G2553 Launch Pad一块,MSP430F5529 Mini Board 一块; 2、TFT2.2_and_KEY键盘接口一块,TFT2.2液晶屏一块;

3、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

1、液晶显示的基本原理

TFT-LCD(Thin Film Transistor-Liquid Crystal Display),即薄膜晶体管液晶显示器,也就是大家常说的真彩液晶显示屏。它可以“主动的”对屏幕上的各个独立的像素进行控制。显示屏由许多可以发出任意颜色的光线的像素组成,只要控制各个像素显示相应的颜色就能显示我们想要的色彩斑斓的世界。

本实验所使用的TFT2.2彩色液晶模块是一个2.2寸的TFT模块,内置TFT控制器,对外连接直接通过8位的SPI总线进行指令和数据的传输。TFT2.2有像素点数为240×320,色彩深度为16位色,也就是每一个像素点需要用16位的数据来表示其显示内容。

TFT2.2模块的显示操作非常简便,需要改变某一个像素点的颜色时,只需要对该点所对应的2个字节的显存进行操作即可。而为了便于索引操作,模块将所有的显存地址分为X轴地址(X Address)和Y轴地址(Y Address),分别可以寻址的范围为X Address=0~239,Y Address=0~319,X Address和Y Address交叉对应着一个显存单元(2byte);这样只要索引到了某一个X、Y轴地址时,并对该地址的寄存器进行操作,便可对TFT-LCD显示器上对应的像素点进行操作了。

TFT2.2模块的像素点与显存对应关系如下图所示:

10

东北林业大学 “3+1”实验班

图2-1 显存与像素点对应关系示意图

液晶模块与单片机的连接方式见工程Lcd.c文件中。

2、矩阵键盘检测的基本原理

为了节省单片机的IO口,提高键盘检测的效率和准确性,本实验我们采用键盘控制芯片CH452进行键盘扫描。并采用4线串行接口与单片机交换数据,单片机可以频繁地通过串行接口进行高速操作,而绝对不会降低CH452的工作效率。

在键盘扫描期间, DIG7~DIG0 引脚按照DIG0至DIG7的顺序依次输出高电平,其余7个引脚输出低电平;SEG7~SEG0引脚的输出被禁止,当没有键被按下时, SEG7~SEG0 都被下拉为低电平;当有键被按下时,例如连接 DI G3 与 SEG4 的键被按下,则当DIG3输出高电平时SEG4检测到高电平;为了防止因为按键抖动或者外界干扰而产生误码,CH452实行两次扫描,只有当两次键盘扫描的结果相同时,按键才会被确认有效。如果CH452检测到有效的按键,则记录下该按键代码,并通过4线串行接口中的DOUT引脚或者2线串行接口中的INT#引脚产生低电平有效的键盘中断(当INTM为1时输出低电平脉冲中断), 此时单片机可以通过串行接口读取按键代码; 在没有检测到新的有效按键之前, CH452 不再产生任何键盘中断。CH452不支持组合键,也就是说,同一时刻,不能有两个或者更多的键被按下;如果多个键同时按下,那么按键代码较小的按键优先。

有关键盘检测的详细介绍请参考CH452芯片手册。

【实验内容】

1、练习液晶显示部分基本函数的使用,如:画点,画线,画矩形,显示数字、字符、字符串、显示汉字等;

2、仔细研读键盘检测程序,当有按键按下时,将相应的按键编码显示在液晶屏

11

东北林业大学 “3+1”实验班

的合适位置。如:按下KEY5,将在液晶显示屏上显示“The KEYCODE is KEY01”; 3、自己另编写一个显示汉字的函数,显示你所想要的汉字大小,例如48*48; 4、自己另编写一个显示图片的函数,显示你所想要尺寸的真彩图片;

【实验步骤】

内容1:基本函数的使用

1、打开CCSv5,选择“File>>Import”命令,弹出如图2-2所示对话框,单击展开“Code Composer Studio”选项,选择“Existing CCS/CCE Eclipse Projects”。

图2-2 导入新的CCSv5工程文件

2、单击“Next”按钮,弹出图2-3所示对话框。

图2-2 选择导入工程目录

12

东北林业大学 “3+1”实验班

3、单击“Browse”按钮,选择工程文件目录Lcd_and_Key。单击“Finish”按钮,即可完成已有工程的导入。

4、在此工程下练习一下函数的用法:

/* LCD App */

void LCD_GPIO(void);

//LCD IO初始化

void SPI_Init(void);

//SPI初始化

void LCD_Clear(uint16 Color); //清屏

void LCD_CH(uint16 x,uint16 y,const uint8 index);

//显示汉字

void LCD_Fill(uint16 xsta,uint16 ysta,uint16 xend,uint16 yend,uint16 color);

//颜色填充

void LCD_DrawPoint(uint16 x,uint16 y);

//画点

void LCD_DrawPoint_big(uint16 x,uint16 y);

//画一个大点

void LCD_DrawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2);

//画线

void LCD_DrawRectangle(uint16 x1, uint16 y1, uint16 x2, uint16 y2);

//画矩形

void Draw_Circle(uint16 x0,uint16 y0,uint8 r);

//画圆

void LCD_ShowChar(uint16 x,uint16 y,uint8 num,uint8 mode);

//显示一个字符

void LCD_ShowNum(uint16 x,uint16 y,uint32 num,uint8 len);

//显示数字

void LCD_Show2Num(uint16 x,uint16 y,uint16 num,uint8 len);

//显示2个数字

void LCD_ShowFloatNum(uint16 x,uint16 y,double num);

//显示浮点数

void LCD_ShowString(uint16 x,uint16 y,int8 *p);

//显示字符串

void LCD_ShowPicture();

//显示图片

内容2:按键检测并显示键值

void main(void) {

WDTCTL = WDTPW | WDTHOLD; // 关闭开门狗 PLL_Init(); LCD_GPIO(); SPI_Init();

13

东北林业大学 “3+1”实验班

LCD_Init(); //TFT初始化

/*基本刷屏测试*/ LCD_Clear(RED); LCD_Clear(GREEN); LCD_Clear(YELLOW);

/*清屏,并定义前景色和背景色*/ LCD_Clear(RED); BACK_COLOR=BLACK; POINT_COLOR=WHITE; delayms(100);

Keyscan(); //键盘扫描使能 __bis_SR_register(GIE); while(1) {

if(key_flag == 1) //按键标志位为1,有按键按下 {

if(KEYCODE == 1) //判断是否为KEY1按下 {

KEYCODE = 0;

LCD_ShowString(32,64,\); }

if(KEYCODE == 2) //判断是否为KEY2按下 {

KEYCODE = 0;

LCD_ShowString(32,64,\); } ??

key_flag = 0; //按键标志位清0 } } }

内容3:显示汉字

1、用文字取模软件生成想要显示汉字的字模,并将字模数组写到font.c文件中,在font.h文件中加以声明;

2、在lcd.c文件中改写汉字显示函数,并在lcd.h文件中加以声明;

/****************************************************************************** 函 数 名:LCD_CH48_48

功 能:在指定位置显示一个汉字(48*48大小) 入 口 参 数:dcolor 内容颜色;gbcolor 背景颜色 返 回 值:无

******************************************************************************/ void LCD_CH48_48(uint16 x,uint16 y,const uint8 index)

14

东北林业大学 “3+1”实验班

{

uint16 i,j; //为了防止溢出,i,j必须定义为16为的int型 const uint8 *temp=hanzi48_48;

Address_set(x,y,x+47,y+47); //设置区域 temp+=index*288; /* 减法更高效 */ for(j=288;j>0;j--) {

for(i=8;i>0;i--) {

if((*temp&(1<<(8-i)))!=0) {

LCD_WR_DATA(POINT_COLOR); } else {

LCD_WR_DATA(BACK_COLOR); } }

temp++; } }

3、在main.c文件中调用汉字显示函数。

内容4:显示图片

1、用图片取模软件生成想要显示图片的字模,并将字模数组写到picture.c文件中,在picture.h文件中加以声明;

2、在lcd.c文件中改写图片显示函数,并在lcd.h文件中加以声明;

/****************************************************************************** 函 数 名:LCD_ShowPicture1 功 能:显示自定义大小图片

入口参数:x,y 坐标;wid 图片宽度 high 图片高度 返 回 值:无

******************************************************************************/ void LCD_ShowPicture1(uint16 x,uint16 y,uint16 wid,uint16 high)

//显示自定义大小图片

{

int16 i;

int16 area=wid*high-1; if(wid>239) wid=239; if(high>319) high=319;

Address_set(x,y,x+wid-1,y+high-1); //坐标设置 for(i=area;i>=0;i--) {

15

东北林业大学 “3+1”实验班

LCD_WR_DATA8(image[(area-i)*2+1]); //发送颜色数据 LCD_WR_DATA8(image[(area-i)*2]); } }

3、在main.c文件中调用汉字显示函数。

【思考与分析】

1、在液晶显示程序中能否使用MSP430单片机的低功耗模式?为什么? 2、尝试在TFT2.2真彩液晶屏上编写一个含有两级以上的菜单程序,菜单风格自拟。

16

东北林业大学 “3+1”实验班

实验三 时钟系统配置实验

【实验目的】

1、掌握MSP430的时钟系统结构与工作原理;

2、了解MSP430系列单片机几种时钟信号的基本用途; 3、学会用FLL锁频环配置时钟;

【实验仪器】

1、SEED-EXP430F5529v1.0开发板一套; 2、TDS210双踪示波器一台;

3、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

在MSP430单片机中,时钟系统的主要作用是为CPU工作提供时序,以及为不同的片内外设提供不同频率的时钟。 1、5个时钟输入源

(1)XT1CLK 低频或高频时钟源:可以使用标准晶振,振荡器或者外部时钟源输入4MHz~32MHz。XT1CLK可以作为内部FLL模块的参考时钟。

(2)XT2CLK 高频时钟源:可以使用标准晶振,振荡器或者外部时钟源输入4MHz~32MHz。

(3)VLOCLK 低功耗低频内部时钟源:典型值为10KHZ。

(4)REFOCLK 低频修整内部参考时钟源:典型值为32768Hz,作为FLL基准时钟源。

(5)DCOCLK 片内数字控制时钟源:通过FLL模块来稳定。 2、3个时钟信号 (1)ACLK 辅助时钟:ACLK可由软件选择来自XT1CLK、REFOCLK、VLOCLK、DCOCLK、DCOCLKDIV、XT2CLK(由具体器件决定)这几个时钟源之一。然后经1、2、4、8、16、32分频得到。ACLK可由软件选作各个外设模块的时钟信号,一般用于低速外设模块。

(2)MCLK 系统主时钟: MCLK可由软件选择来自上述5种时钟源,同样可经过分频得到。MCLK主要用于CPU和系统。

(3)SMCLK 子系统时钟:可由软件选择来自上述5种时钟源,同样可经过分频得到。 SMCLK可由软件选作各个外设模块的时钟信号,主要用于高速外设模块。 通过软件配置,可以通过5个时钟输入源来产生特定频率的3个时钟信号供CPU和外设使用。

3、MSP430F5xx/6xx系列单片机的时钟系统结构框图如图3-1所示。

17

东北林业大学 “3+1”实验班

图3-1 MSP430F5xx/6xx系列单片机的时钟系统结构框图

4、MSP430单片机的P1.0、P2.2、P7.7引脚的第二功能可以分别输出ACLK、SMCLK、MCLK,我们可以通过设置相应时钟信号从对应引脚输出,用示波器进行观察。

【实验内容】

1、编写时钟配置程序,设置ACLK=XT1CLK =32768Hz,SMCLK=XT2CLK=4MHz,MCLK=DCO(默认)=32×ACLK=1048576Hz,并将ACLK、SMCLK和MCLK分别通过P1.0、P2.2、P7.7口输出;

2、通过FLL锁频环电路自动校正技术使内部DCO振荡器稳定地运行在2.45MHz。

【实验步骤】

内容1:配置并输出辅助时钟ACLK、子系统时钟SMCLK及主时钟MCLK

1、建立新工程,并命名为lab3_1。

2、在新建工程的编辑窗口输入如下代码:

#include void main(void) {

WDTCTL = WDTPW + WDTHOLD; // Stop WDT

P1DIR |= BIT0; // ACLK set out to pins

18

东北林业大学 “3+1”实验班

P1SEL |= BIT0;

P2DIR |= BIT2; // SMCLK set out to pins P2SEL |= BIT2;

P7DIR |= BIT7; // MCLK set out to pins P7SEL |= BIT7;

P7SEL |= BIT2+BIT3; // Port select XT2 UCSCTL6 &= ~XT2OFF; // Set XT2 On

UCSCTL6 &= ~(XT1OFF); // XT1 On

UCSCTL6 |= XCAP_3; // Internal load cap // Loop until XT1 fault flag is cleared do {

UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);

// Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags

}while (SFRIFG1&OFIFG); // Test oscillator fault flag

UCSCTL6 &= ~XT2DRIVE0; // Decrease XT2 Drive according to // expected frequency

UCSCTL4 |= SELA_0 + SELS_5; // Select SMCLK, ACLK source and DCO source while(1); // Loop in place }

3、编译、调试并下载程序到开发板。

4、运行程序,用示波器观察P1.0、P2.2、P7.7口的输出波形。

内容2:通过FLL锁频环电路自动校正技术使内部DCO振荡器稳定地运行在

2.45MHz。

注意:相互关系式有:ACLK=XT1=32768Hz,MCLK=SMCLK=DCO=(74+1)*REFO= 2457600Hz,这里XT1CLK被选为ACLK,REFO是内部调整过的32768Hz参考时钟,提供一个稳定的参考时钟用作FLLREFCLK。

1、建立新工程,步骤同上,并命名为lab3_2。 2、在新建工程的编辑窗口输入如下代码:

#include void main(void) {

WDTCTL = WDTPW + WDTHOLD; // Stop WDT

P1DIR |= BIT0; // ACLK set out to pins P1SEL |= BIT0;

P2DIR |= BIT2; // SMCLK set out to pins P2SEL |= BIT2;

P7DIR |= BIT7; // MCLK set out to pins

19

东北林业大学 “3+1”实验班

P7SEL |= BIT7;

UCSCTL6 &= ~(XT1OFF); // XT1 On

UCSCTL6 |= XCAP_3; // Internal load cap // Loop until XT1 fault flag is cleared do {

UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);

// Clear XT2,XT1,DCO fault flags SFRIFG1 &= ~OFIFG; // Clear fault flags

}while (SFRIFG1&OFIFG); // Test oscillator fault flag

// Initialize DCO to 2.45MHz

__bis_SR_register(SCG0); // Disable the FLL control loop UCSCTL0 = 0x0000; // Set lowest possible DCOx, MODx UCSCTL1 = DCORSEL_3; // Set RSELx for DCO = 4.9 MHz UCSCTL2 = FLLD_1 + 74; // Set DCO Multiplier for 2.45MHz // (N + 1) * FLLRef = Fdco // (74 + 1) * 32768 = 2.45MHz // Set FLL Div = fDCOCLK/2 __bic_SR_register(SCG0); // Enable the FLL control loop // UG for optimization.

// 32 x 32 x 2.45 MHz / 32,768 Hz = 76563 = MCLK cycles for DCO to settle __delay_cycles(76563);

// Loop until XT1,XT2 & DCO fault flag is cleared do {

UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + 0x0004 + DCOFFG);// Clear XT2,XT1,DCO fault flags

SFRIFG1 &= ~OFIFG; // Clear fault flags

}while (SFRIFG1&OFIFG); // Test oscillator fault flag

while(1); // Loop in place }

3、编译、调试并下载程序到开发板。

4、运行程序,用示波器观察P1.0、P2.2、P7.7口的输出波形。

【思考与分析】

1、在不做任何配置的情况下,MSP430F5529单片机的各个时钟的默认值是多少?试编程加以验证。

2、试编写程序验证MSP430F5529单片机的主时钟频率最大可达到多少?

3、MSP430系列单片机最大的特点是低功耗,低功耗是如何体现的?查阅资料,加以详细论述。

20

东北林业大学 “3+1”实验班

实验四 看门狗与定时器实验

【实验目的】

1、了解看门狗定时器的基本作用;

2、学会使用定时器在MSP430的某一引脚输出特定占空比的方波; 3、掌握MSP430系列单片机定时器的几种工作模式; 4、熟悉MSP430系列单片机定时器的比较/捕获功能。

【实验仪器】

1、MSP430G2553 Launch Pad一块,MSP430F5529 Mini Board 一块; 2、TFT2.2_and_KEY键盘接口一块,TFT2.2液晶屏一块; 3、TDS210双踪示波器一台;

4、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

看门狗定时器主要用于在程序跑飞时,则不会在看门狗定时时间到达之前执行看门狗清零指令,看门狗就会溢出,从而使系统产生复位,保证程序的正常运行。

16位定时器的计数值寄存器TAR在每个时钟信号的上升沿进行增加/减少,可利用软件读取TAR寄存器的计数值。此外,当定时时间到,产生溢出时,定时器可产生中断。置位定时器控制寄存器中的TACLR控制位,可自动清除TAR寄存器的计数值,同时,在增/减计数模式下,清除了时钟分频器和计数方向。

Timer_A共有4种工作模式:停止模式、增计数模式、连续计数模式和增/减计数模式,具体工作模式可以通过MC控制位进行选择,具体配置如表4-1所示。

表4-1 Timer_A工作模式配置列表

MC控制位配置值 00 01 10 11 Timer_A工作模式 停止模式 增计数模式 连续计数模式 增/减计数模式 Timer_A停止 Timer_A从0到TAxCCR0重复计数 Timer_A从0到0FFFFh重复计数 Timer_A从0增计数到TAxCCR0之后减计数到0,循环往复 描 述 定时器Timer_A的捕获模式:

当CAP控制位置为1时,捕获/比较模块配置为捕获模式。捕获模式被用于捕获事件发生的时间。捕获输入CCIxA和CCIxB可连接外部引脚或内部信号,这需通过CCIS控制位进行配置。可通过CM控制位将捕获输入信号触发沿配置为上升沿触发、下降沿触发或两者都触发。捕获事件在所选输入信号触发沿产生,如果产生捕获事件,定时器将完成以下工作:

21

东北林业大学 “3+1”实验班

? 主计数器计数值复制到TAxCCRn寄存器中; ? 置位中断标志位CCIFG。

【实验内容】

1、使用看门狗定时功能产生一个方波(周期性的取反P1.0);

2、利用定时器TA0,使其工作在增计数模式下,选择ACLK作为其参考时钟。将P1.2和P1.3引脚配置为定时器输出,且使CCR1和CCR2工作在比较输出模式7下,最终使P1.2引脚输出75%占空比的PWM波形,使P1.3引脚输出25%占空比的PWM波形。

3、选择键盘上的一个按键,当该按键按下一次时,打开定时器开始计时,利用定时器的捕获功能,捕捉该按键再次按下时的精确时间,并将该时间显示在液晶显示屏上。

【实验步骤】

内容1:看门狗定时器产生方波信号

1、建立新工程,并命名为lab4_1。

2、在新建工程的编辑窗口输入如下代码:

#include void main(void) {

WDTCTL = WDTPW+WDTCNTCL+WDTSSEL0+WDTIS_5;

// 看门狗定时器工作在看门狗模式,定时1S,选择ACLK作为参考时钟 P1DIR |= 0x01; // 设置P1.0端口为输出 P1OUT ^= 0x01; // 反转P1.0端口状态

__bis_SR_register(LPM3_bits + GIE); // 进入低功耗模式3,并启用中断 }

3、编译、调试并下载程序到开发板。

4、运行程序,用示波器观察P1.0口的输出波形。

内容2:用定时器产生特定占空比的PWM信号

1、建立新工程,步骤同上,并命名为lab4_2。 2、在新建工程的编辑窗口输入如下代码:

#include void main(void) {

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

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

P1SEL |= BIT2+BIT3; // P1.2和P1.3引脚功能选为定时器输出 TA0CCR0 = 512-1; // PWM周期定义

TA0CCTL1 = OUTMOD_7; // CCR1比较输出模式7:复位/置位 TA0CCR1 = 384; // CCR1 PWM 占空比定义

TA0CCTL2 = OUTMOD_7; // CCR2 比较输出模式7:复位/置位 TA0CCR2 = 128; // CCR2 PWM 占空比定义

22

东北林业大学 “3+1”实验班

TA0CTL = TASSEL_1 + MC_1 + TACLR; // ACLK,增计数模式,清除TAR计数器 __bis_SR_register(LPM3_bits); // 进入LPM3 }

3、编译、调试并下载程序到开发板。

4、运行程序,用示波器观察P1.2、P1.3口的输出波形。

内容3:用定时器的捕获功能捕捉开发板上按键按下的精确时间。

1、将单片机、独立键盘和MSP430G2553 Launch Pad仿真器部分用杜邦线连接起来。

2、导入工程“Lcd_and_Key”,并在此基础上添加Timer的相关文件:Timer.c和Timer.h。 Timer.c文件如下:

/***********************************Copyright(c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

**----------------------------文件信息----------------------------------------- **文 件 名: Timer.c **创 建 人: 刘 毅 **最后修改日期: 2014年11月13日 **描 述:

**---------------------------历史版本信息------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日 ** 描 述: 原始版本

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

#include #include \ #include \ #include

int pressent_time; //定义当前时间

/********************************************************************** 函 数 名:TA1_Init()

功 能:对TimerA1进行初始化 入 口 参 数: 返 回 值:

**********************************************************************/ void TA1_Init() {

P1DIR &= ~BIT7;

P1SEL |= BIT7; //将P1.7引脚配置为定时器捕获输入(TA1.0)

23

东北林业大学 “3+1”实验班

P1OUT |= BIT7;

P1REN |=BIT7; //设置P1.7为内部上拉

TA1CTL = TASSEL_1 + ID_3;//TA1主计数器时钟选择ACLK,8分频 //TA1EX0 = TAIDEX_7; //分频扩展,8分频,timer clock = 32768/8/8=512Hz //最大定时时间:65526/512=128s

TA1CCTL0 = CM1 + SCS + CAP + CCIE;//CCR0工作于捕获模式,下降沿触发 }

/********************************************************************** 函 数 名:TA1_Start() 功 能:启动TimerA1 入 口 参 数: 返 回 值:

**********************************************************************/ void TA1_Start() {

TA1CTL |= MC_2 + TACLR;//清除TAR,选择连续计数模式 }

/********************************************************************** 函 数 名:TimerA1中断服务子程序 功 能:读取捕获值 入 口 参 数: 返 回 值:

**********************************************************************/ #pragma vector = TIMER0_A1_VECTOR __interrupt void TIMER0_A1_ISR(void) {

//char str[80];

pressent_time = (TA1CCR0+1)/512;//捕获当前时间,单位ms LCD_ShowNum(32,16,pressent_time,3);

//sprintf(str,\ //LCD_ShowString(32,16,str); _delay_cycles(300000); }

TA1CCTL0 &= ~CCIFG; //清除中断标志位

Timer.h文件如下:

/***********************************Copyright(c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

**----------------------------文件信息----------------------------------------- **文 件 名: Timer.h **创 建 人: 刘 毅

24

东北林业大学 “3+1”实验班

**最后修改日期: 2014年11月13日 **描 述:

**---------------------------历史版本信息------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日 ** 描 述: 原始版本

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

#ifndef TIMER_H_ #define TIMER_H_

extern void TA1_Init(); extern void TA1_Start();

#endif /* TIMER_H_ */

3、在main.c文件的主函数中调用Timer相关函数。

void main(void) {

WDTCTL = WDTPW + WDTHOLD; // 关闭开门狗 ……

TA1_Init(); TA1_Start();

__bis_SR_register(GIE);

……

while(1) { } }

4、编译、调试并下载程序到开发板。

5、运行程序,按下按键,观察液晶屏上捕获到的时间值。

【思考与分析】

1、利用定时器TA0实现开发板上的第一个LED灯以200ms间隔闪烁,同时利用定时器TA2实现液晶屏上的一个两位数以59s循环计时。 2、试利用MSP430的定时器捕获功能做一个频率计。

25

东北林业大学 “3+1”实验班

实验五 AD/DA实验

【实验目的】

1、了解AD的工作原理;

2、熟悉ADC12的4种转换模式;

3、掌握MSP430F5529的ADC12基本使用方法。 4、掌握MSP430F6638的DAC的基本使用方法。

【实验仪器】

1、SEED-EXP430F5529v1.0开发板一套;

2、TFT2.2_and_KEY键盘接口一块,TFT2.2液晶屏一块;

3、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

模数转换器的作用是把从传感器采集到的连续变化的模拟电压信号转换为单片机可识别的数字信号。在转换的过程中,数字输出代码与模拟输入电压之间的关系如图5-1所示。

图5-1 数字输出代码与模拟输入电压之间的关系

数字量的计算方法:

ADC内核一般要使用两个参考电压VR+和VR-,一般这两个电压可以是用户接入或者是使用内部参考电压。VR+是定义的转换最大值,VR-则是转换的最小值。 以12位分辨率为例。

? Vin> =VR+ ADC12输出满量程值0x0FFF; ? Vin< =VR- ADC12输出0;

? VR-

26

东北林业大学 “3+1”实验班

【实验内容】

1、利用开发板上的齿轮电位器进行采样,并将采样得到的模拟电压转换为数字量,在液晶屏上显示出来,并同时显示所采样的模拟电压值。 2、利用A10通道采样内部温度传感器,并将采样的数值转化为摄氏和华氏温度,分别在液晶屏上显示出来。

3、试编写程序,从MSP430F6638单片机的DA引脚输出一个正弦波。

【实验步骤】

内容1:用电位器采样模拟电压并显示

1、导入工程“Lcd_and_Key”,改写程序,将SEED-EXP430F5529v1.0开发板与键盘接口连接起来,将原程序中的P1口改写为P7口。

2、并在此基础上添加ADC12的相关文件:ADC12.c和ADC12.h。 ADC12.c文件如下:

/***********************************Copyright(c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

**----------------------------文件信息----------------------------------------- **文 件 名: ADC12.c **创 建 人: 刘 毅 **最后修改日期: 2014年11月13日 **描 述:

**---------------------------历史版本信息------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日 ** 描 述: 原始版本

******************************************************************************/ #include \ #include \ #include

#include

/****************************************************************************** 函 数 名:ADC_Init() 功 能:ADC12初始化 入 口参 数: 返 回 值:

******************************************************************************/ void ADC_Init() {

volatile unsigned int i;

P6SEL |= BIT5; // 将P6.5引脚设为ADC输入功能 ADC12CTL0 = ADC12ON+ADC12SHT02+ADC12MSC; // 打开ADC12,设置采样间隔,序列采样

27

东北林业大学 “3+1”实验班

ADC12CTL1 = ADC12SHP+ ADC12CONSEQ_2 + ADC12SSEL_1 + ADC12CSTARTADD_5;

// 采样保持触发信号选择采样定时器,设置单通道多次转换模式,时钟源选择

ACLK,ADC转换开始地址ADC12MEM5

ADC12MCTL5 |= ADC12SREF_0 + ADC12INCH_5; // Vr+=AVcc ,Vr-=AVss,输入通道5 ADC12IE = BIT5; //使能ADC中断

for ( i=0; i<0x30; i++); // 延迟以使参考电压产生稳定

ADC12CTL0 |= ADC12ENC; // 置位ADC12ENC控制位,使能AD转换 }

/****************************************************************************** 函 数 名:ADC_Start() 功 能:启动AD转换 入 口参 数: 返 回 值:

******************************************************************************/ void ADC_Start() {

ADC12CTL0 |= ADC12SC; //启动AD转换 }

/****************************************************************************** 函 数 名:ADC_Stop() 功 能:停止AD转换 入口参数: 返 回 值:

******************************************************************************/ void ADC_Stop() {

ADC12CTL0 &= ~ADC12ON;

//ADC12CTL0 &= ~ADC12SC; // 禁止AD转换 }

/****************************************************************************** 函 数 名:ADC12中断服务程序 功 能: 入口参数: 返 回 值:

******************************************************************************/ #pragma vector = ADC12_VECTOR __interrupt void ADC12_ISR(void) {

float a;

volatile float u;

switch(__even_in_range(ADC12IV,34)) {

case 0: break; // Vector 0: 无中断

case 2: break; // Vector 2: ADC溢出中断

case 4: break; // Vector 4: ADC转换时间溢出中断 case 6: break; // Vector 6: ADC12IFG0 case 8: break; // Vector 8: ADC12IFG1 case 10: break; // Vector 10: ADC12IFG2 case 12: break; // Vector 12: ADC12IFG3 case 14: break; // Vector 14: ADC12IFG4 case 16: // Vector 16: ADC12IFG5

28

东北林业大学 “3+1”实验班

// if (ADC12MEM5 >= 0x7ff) // ADC12MEM = A0 > 0.5AVcc? // P8OUT |= BIT1; // P8.1 = 1 // else

// P8OUT &= ~BIT1; // P8.1 = 0 //

a=ADC12MEM5;

u=(a/4096)*3.3; //计算输出电压公式 LCD_ShowFloatNum(100,100,a); //输出ADC12MEM5的值 LCD_ShowFloatNum(100,150,u); //输出电压值 LCD_ShowChar(200,150,'V',0); //输出单位“V”

case 18: break; // Vector 18: ADC12IFG6 case 20: break; // Vector 20: ADC12IFG7 case 22: break; // Vector 22: ADC12IFG8 case 24: break; // Vector 24: ADC12IFG9 case 26: break; // Vector 26: ADC12IFG10 case 28: break; // Vector 28: ADC12IFG11 case 30: break; // Vector 30: ADC12IFG12 case 32: break; // Vector 32: ADC12IFG13 case 34: break; // Vector 34: ADC12IFG14 default: break; } }

ADC12.h文件如下:

/***********************************Copyright(c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

**----------------------------文件信息----------------------------------------- **文 件 名: ADC12.h **创 建 人: 刘 毅 **最后修改日期: 2014年11月13日 **描 述:

**---------------------------历史版本信息------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日 ** 描 述: 原始版本

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

#ifndef ADC12_H_ #define ADC12_H_

#include \

extern void ADC_Init(); //ADC12初始化 extern void ADC_Start(); //启动AD转换 extern void ADC_Stop(); //停止AD转换 #endif /* ADC_H_ */

29

东北林业大学 “3+1”实验班

3、在main.c文件的主函数中调用AD采样函数,并使能ADC中断。

P8DIR |= BIT0;

P8OUT |= BIT0; //将齿轮电位器的输出端置为高电平 P8DIR |= BIT1; //设置P8.1为输出功能 ??

ADC_Init(); // ADC12初始化 ADC_Start(); // 启动采样转换 __enable_interrupt(); //使能中断

4、编译、调试并下载程序到开发板。

5、运行程序,拨动齿轮电位器,观察液晶屏上显示的电压值的变化。

内容2:对ADC12的通道10进行采样,得到温度传感器的输出值

1、改写内容1的AD采样的通道号,将其设置为采样内部温度传感器,并显示温度值。

ADC12.c文件如下:

/***********************************Copyright(c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

**----------------------------文件信息----------------------------------------- **文 件 名: ADC12.c **创 建 人: 刘 毅 **最后修改日期: 2014年11月13日 **描 述:

**---------------------------历史版本信息------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日 ** 描 述: 原始版本

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

#include \ #include \ #include

#include

/****************************************************************************** 函 数 名:ADC_Init() 功 能:ADC12初始化 入 口参 数: 返 回 值:

******************************************************************************/ void ADC_Init() {

volatile unsigned int i; REFCTL0 &= ~REFMSTR; // 复位REFMSTR控制位以控制ADC12参考电压控制寄存器

30

东北林业大学 “3+1”实验班

ADC12CTL0 = ADC12ON+ADC12SHT0_5+ADC12MSC+ ADC12REFON;

// 打开ADC12,设置采样间隔,序列采样,打开内部参考电压产生器,参考电压设置为1.5V

ADC12CTL1 = ADC12SHP+ADC12CONSEQ_2+ ADC12SSEL_1 ;

// 采样保持触发信号选择采样定时器,设置单通道多次转换模式,时钟源选择ACLK,ADC

ADC12MCTL0 = ADC12SREF_1 + ADC12INCH_10; // A10通道作为输入,采样温度 ADC12IE = 0x001; // 使能ADC12IFG0中断

for ( i=0; i<0x30; i++); // 延迟以使参考电压产生稳定 ADC12CTL0 |= ADC12ENC; // 使能转换 }

/****************************************************************************** 函 数 名:ADC_Start() 功 能:启动AD转换 入 口参 数: 返 回 值:

******************************************************************************/ void ADC_Start() {

ADC12CTL0 |= ADC12SC; //启动AD转换 }

/****************************************************************************** 函 数 名:ADC_Stop() 功 能:停止AD转换 入 口参 数: 返 回 值:

******************************************************************************/ void ADC_Stop() {

ADC12CTL0 &= ~ADC12ON;

//ADC12CTL0 &= ~ADC12SC; // 禁止AD转换 }

/****************************************************************************** 函 数 名:ADC12中断服务程序 功 能: 入 口参 数: 返 回 值:

******************************************************************************/ #pragma vector = ADC12_VECTOR __interrupt void ADC12_ISR(void) {

long temp;

volatile long IntDegF; volatile long IntDegC;

switch(__even_in_range(ADC12IV,34)) {

case 0: break; // Vector 0: 无中断

case 2: break; // Vector 2: ADC溢出中断

case 4: break; // Vector 4: ADC转换时间溢出中断 case 6: // Vector 6: ADC12IFG0

31

东北林业大学 “3+1”实验班

temp = ADC12MEM0;

IntDegC = ((temp - 1855) * 667) / 4096; // 采样结果转化为摄氏温度 IntDegF = ((temp - 1748) * 1200) / 4096;// 采样结果转化为华氏温度 LCD_ShowFloatNum(100,100,IntDegC); //输出摄氏温度 LCD_ShowFloatNum(100,150,IntDegF); //输出华氏温度 default: break; } }

ADC12.h文件如下:

/***********************************Copyright(c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

**----------------------------文件信息----------------------------------------- **文 件 名: ADC12.h **创 建 人: 刘 毅 **最后修改日期: 2014年11月13日 **描 述:

**---------------------------历史版本信息------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日 ** 描 述: 原始版本

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

#ifndef ADC12_H_ #define ADC12_H_

#include \

extern void ADC_Init(); //ADC12初始化 extern void ADC_Start(); //启动AD转换 extern void ADC_Stop(); //停止AD转换 #endif /* ADC_H_ */

2、在main.c文件的主函数中调用AD采样函数,并使能ADC中断。

P8DIR |= BIT0;

P8OUT |= BIT0; //将齿轮电位器的输出端置为高电平 P8DIR |= BIT1; //设置P8.1为输出功能 ??

ADC_Init(); // ADC12初始化 ADC_Start(); // 启动采样转换 __enable_interrupt(); //使能中断

3、编译、调试并下载程序到开发板。

4、运行程序,拨动齿轮电位器,观察液晶屏上显示的温度值的变化。

内容3:从MSP430单片机的DA引脚输出一个正弦波

32

东北林业大学 “3+1”实验班

1、建立新工程,并命名为lab5_3。

2、在新建工程的编辑窗口输入如下代码:

#include #include #define PI 3.14159 void main(void) {

float i; int dacVal;

WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer

DAC12_0CTL0 = DAC12IR + DAC12SREF_1 + DAC12AMP_5 + DAC12CALON; //选择DAC12_0 on P7.6,VCC作为参考电压,初始化偏移量校正 DAC12_0CTL0 |= DAC12ENC; // Enable DAC12 while(1) {

i+=PI/36;

dacVal=(int)((sin(i)+1)*2048);

//每个j对应的sin换算为12位分辨率(0x0000 ~ 0x0FFF)时的数据 DAC12_0DAT=dacVal; //将计算出的值写入DAC12_0DAT } }

3、编译、调试并下载程序到开发板。

4、运行程序,用示波器观察DA输出端口的输出波形。

【思考与分析】

1、MSP430 ADC2有哪些转换方式?各自的特点是是什么?

2、MSP430F5529单片机的ADC12最大转换率是多少?试配置寄存器使ADC12的转换率达到最大。

3、能否用MSP430F6638的DAC功能产生特定频率的正弦波,若能,怎样确定频率?

4、试编写程序,从MSP430F6638单片机的DA引脚输出一个三角波。

33

东北林业大学 “3+1”实验班

实验六 比较器实验

【实验目的】

1、了解MSP430系列单片机比较器B的主要功能; 2、掌握MSP430F5529的比较器B基本使用方法;

3、了解比较器B的简单应用,如测量电阻、电容触摸按键等。

【实验仪器】

1、MSP430G2553 Launch Pad一块,MSP430F5529 Mini Board 一块; 2、LED灯一个,电位器一个;

2、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

比较器B是一个实现模拟电压比较的片内外设,主要用来比较模拟电压“+”输入端和“-”输入端的电压大小,然后设置输出信号CBOUT的值。如果“+”输出端电压高于“-”输出端电压,输出信号CBOUT置高,反之,CBOUT拉低。

通过相应寄存器的配置,比较器B可进行如下模拟电压信号的比较: (1)两个外部输入电压信号的比较;

(2)每个外部输入电压信号与内部基准电压的比较。 我们还可以通过设置,当比较器输出产生上升沿或者下降沿时,触发中断并置位中断标志位。此时如果CBIE(比较器B中断使能)和GIE(CPU中断使能)都被置位,CBIFG将产生中断请求。

【实验内容】

1、比较器B输入通道CB5(P6.5)接外部模拟输入信号(齿轮电位器),并引至比较器“+”输入端。内部参考电压发生器利用共享电压源产生2.0V参考电压,并引至比较器“-”输入端。最终产生以下结果:当CB5输入模拟信号电压高于2.0V时,CBOUT(P1.6)输出高电平;当CB5输入模拟信号电压低于2.0V时,CBOUT输出低电平。将开发板上的LED1引接到P1.6观察现象。 2、在内容1的基础上,利用比较器中断,当CB5输入模拟信号电压高于2.0V时,拉高P1.0引脚;当CB5输入模拟信号电压低于2.0V时,拉低P1.0引脚。

【实验步骤】

内容1:比较模拟输入电压(电位器输入)与参考电压

1、建立新工程,步骤同上,并命名为lab6_1。 2、在新建工程的编辑窗口输入如下代码:

#include void main(void) {

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

34

东北林业大学 “3+1”实验班

}

P1DIR |= BIT6;

P1SEL |= BIT6; // P1.6选择功能为比较器输出CBOUT // 以下步骤设置比较器B

CBCTL0 |= CBIPEN + CBIPSEL_5; // 启用CB5,并将其引至正输入端 CBCTL1 |= CBPWRMD_1; // 正常电源模式

CBCTL2 |= CBRSEL; // 内部参考电压VREF引至负输入端

CBCTL2 |= CBRS_3+CBREFL_2; // 梯形电阻电路禁用,产生2.0V内部共享电压 CBCTL3 |= BIT5; // 启用P6.5/CB5比较器功能 CBCTL1 |= CBON; // 打开比较器B

__delay_cycles(75); // 延迟以待参考电压稳定 __bis_SR_register(LPM4_bits); // 进入LPM4

3、将电位器的3个引脚分别连接VCC、P6.5(中间引脚)、GND,并在P1.6上外接一个LED灯便于观察现象。

4、编译、调试并下载程序到开发板。 5、运行程序,调节电位器,观察现象。

内容2:比较B中断的应用

1、建立新工程,步骤同上,并命名为lab6_2。 2、在新建工程的编辑窗口输入如下代码:

#include void main(void) {

WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗 P1DIR |= BIT0; // 将P1.0设为输出 // 以下步骤设置比较器B

CBCTL0 |= CBIPEN + CBIPSEL_5; // 启用CB5,并将其引至正输入端 CBCTL1 |= CBPWRMD_1; // 正常电源模式

CBCTL2 |= CBRSEL; // 内部参考电压VREF引至负输入端

CBCTL2 |= CBRS_3+CBREFL_2; // 梯形电阻电路禁用,产生2.0V内部共享电压 CBCTL3 |= BIT5; // 启用P6.5/CB5比较器功能 __delay_cycles(75); // 延迟以待参考电压稳定 CBINT &= ~(CBIFG + CBIIFG); // 清除比较器中断标志位

CBINT |= CBIE; // 使能比较器CBIFG上升沿中断(CBIES=0) CBCTL1 |= CBON; // 打开比较器B __bis_SR_register(LPM4_bits+GIE);// 进入LPM4 }

// Comp_B中断服务程序- 反转P1.0口状态 #pragma vector=COMP_B_VECTOR

__interrupt void Comp_B_ISR (void) {

CBCTL1 ^= CBIES; // 切换中断触发方式 CBINT &= ~CBIFG; // 清除中断标志位 P1OUT ^= 0x01; // 反转P1.0口状态

35

东北林业大学 “3+1”实验班

}

3、将LED灯改接到P1.0上。

4、编译、调试并下载程序到开发板。 5、运行程序,调节电位器,观察现象。

【思考与分析】

1、比较器B与模数转换器ADC有什么异同点? 2、如何利用比较器B测量未知电阻?

36

东北林业大学 “3+1”实验班

实验七 Flash实验

【实验目的】

1、了解Flash存储器的分段结构;

2、掌握MSP430单片机对Flash控制器的基本操作,包括数据的写入、数据的读出、数据的擦除,数据的修改等。

【实验仪器】

1、SEED-EXP430F5529v1.0开发板一套;

2、TFT2.2_and_KEY键盘接口一块,TFT2.2液晶屏一块;

3、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

MSP430单片机的Flash存储器是以段为基本结构进行存储的,总体上可分为3部分:128KB的Flash主存储器、2KB的BSL存储器和512B的信息存储器。Flash主要用于存储程序代码,被分割为4个扇区,每个扇区128段,每段256B。Flash控制器可以以位、字节或者字的格式写入Flash主存储器,但Flash主存储器的最小擦出单位是段。BSL存储器为引导加载存储器,可以用来存储引导加载程序,其分为4段,每段512B,并且每段可单独进行擦除。信息存储器主要用来存储需要掉电后永久保存的数据,可分为4段,每段128B,每段也可单独进行擦除。 其存储器的分段结构示意图如图7-1所示。

图7-1 Flash存储器分段结构示意图

MSP430F5529的存储器结构图如图7-2所示:

37

东北林业大学 “3+1”实验班

图7-2 MSP430F552x系列单片机存储结构图

Flash控制器主要用来实现对Flash存储器的烧写程序、写入数据和擦除功能,可对Flash存储器进行字节/字/长字(32位)的寻址和编程。

【实验内容】

1、实现基本的擦出和写入操作,将已设定的数据0x12345678写入InfoD,地址为0x1800。当写入完成时,使能开发板上的LED1闪烁。

2、实现在InfoC中写入递增的自然数数值,并将InfoC的数据拷贝到InfoD, InfoD中的数据也是同样递增的数值。当操作完成时,使能开发板上的LED1闪烁。

【实验步骤】

内容1:基本的擦出和写入操作

1、建立新工程,步骤同上,并命名为lab7_1。

38

东北林业大学 “3+1”实验班

2、在新建工程的编辑窗口输入如下代码:

#include void main(void) {

unsigned long * Flash_ptrD; // Initialize Flash pointer Seg D unsigned long value;

WDTCTL = WDTPW+WDTHOLD; // Stop WDT

P1DIR |=BIT0; // P1.0 set as output

Flash_ptrD = (unsigned long *) 0x1800; // Initialize Flash pointer value = 0x12345678; // Initialize Value FCTL3 = FWKEY; // Clear Lock bit FCTL1 = FWKEY+ERASE; // Set Erase bit

*Flash_ptrD = 0; // Dummy write to erase Flash seg FCTL1 = FWKEY+BLKWRT; // Enable long-word write *Flash_ptrD = value; // Write to Flash FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY+LOCK; // Set LOCK bit

while(1) // Loop forever, SET BREAKPOINT HERE {

P1OUT ^=BIT0; // XOR P1.0 __delay_cycles(500000); // Delay } }

3、编译、调试并下载程序到开发板。 4、运行程序,观察现象。

5、点击view>>Memory Browser,查看地址为0x1800处的值的大小。

内容2:Info之间的数据拷贝操作

1、建立新工程,步骤同上,并命名为lab7_2。 2、在新建工程的编辑窗口输入如下代码:

#include

char value; // 声明一个8位变量 void write_SegC(char value); void copy_C2D(void); void main(void) {

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

value = 0; // 给变量一个初始值 while(1) {

write_SegC(value++); // 写信息段C

copy_C2D(); // 将信息段C的内容复制到信息段D内 }

39

东北林业大学 “3+1”实验班

}

//写信息段C函数

void write_SegC(char value) {

unsigned int i; }

char * Flash_ptr; // Flash指针

Flash_ptr = (char *) 0x1880; // 初始化Flash指针 FCTL3 = FWKEY; // 清除锁定控制位 FCTL1 = FWKEY+ERASE; // 段擦除

_DINT(); // Flash操作期间不允许中断,否则将导致不可预计的错误 *Flash_ptr = 0; // 空写,启动擦除 while(FCTL3 & BUSY); // 等待擦除操作完成 FCTL1 = FWKEY+WRT; // 采用字节/字写入模式 for (i = 0; i < 128; i++) // 循环写信息段C的128字节 {

*Flash_ptr++ = value; // 向信息段C写数据 }

while(FCTL3 & BUSY); // 等待写操作完成 _EINT(); // 启动全局中断

FCTL1 = FWKEY; // Flash退出写模式

FCTL3 = FWKEY+LOCK; // 恢复Flash锁定位,保护数据

//将信息段C的内容复制到信息段D内 void copy_C2D(void) {

unsigned int i; char *Flash_ptrC; char *Flash_ptrD;

Flash_ptrC = (char *) 0x1880; // 初始化信息段C指针 Flash_ptrD = (char *) 0x1800; // 初始化信息段D指针 FCTL3 = FWKEY; // 清除锁定控制位 FCTL1 = FWKEY+ERASE; // 段擦除

_DINT(); // Flash操作期间不允许中断,否则将导致不可预计的错误 *Flash_ptrD = 0; // 空写,启动擦除 while(FCTL3 & BUSY); // 等待擦除操作完成 FCTL1 = FWKEY+WRT; // 采用字节/字写入模式 for (i = 0; i < 128; i++) {

*Flash_ptrD++ = *Flash_ptrC++; // 将信息段C的内容复制到信息段D内 }

while(FCTL3 & BUSY); // 等待写除操作完成 _EINT(); // 启动全局中断

FCTL1 = FWKEY; // Flash退出写模式

FCTL3 = FWKEY+LOCK; // 恢复Flash锁定位,保护数据

40

东北林业大学 “3+1”实验班

}

3、编译、调试并下载程序到开发板。 4、运行程序,观察现象。

5、点击view>>Memory Browser,查看地址为0x1800和0x1880处的值的大小。

【思考与分析】

1、简述Flash存储器的分段结构。并写出各段的起始地址。

2、试编程实现:首先将从0开始的递增数据写入从0x10000到0x10100的扇区内,然后采用扇区擦除方式擦除扇区1,在扇区擦除的过程中,反转P1.0引脚的电平状态,并通过示波器进行观察。

41

东北林业大学 “3+1”实验班

实验八 串行通信实验

【实验目的】

1、理解串行通信的基本原理; 2、掌握UART波特率的设置方法;

3、学会使用MSP430单片机实现串行数据的发送与接收; 4、掌握格式化输出数据的基本方法。

【实验仪器】

1、MSP430G2553 Launch Pad一块,MSP430F5529 Mini Board 一块; 2、TFT2.2_and_KEY键盘接口一块,TFT2.2液晶屏一块; 3、MAX3232/232通信模块一个;

4、PC机操作系统Windows XP或Windows 7,CCSv5.1集成开发环境。

【实验原理】

串口是单片机系统与外界联系的重要接口,在单片机系统的开发与应用中,经常需要利用上位机的串口,通过串行通信技术与单片机系统进行通信。 MSP430单片机设备采用的是TTL电平信号,即+5V等价于逻辑“1”,0V等价于逻辑“0”。而PC串口通信采用的是RS-232电平,即逻辑“1”的电平是﹣3V~﹣15V,逻辑“0”的电平是﹢3V~﹢15V。因此需要用MAX3232芯片把从MSP430单片机中的USCI来的信号进行电平转换后输出到PC,把从PC发过来的信号发送给USCI。电平转换电路如图8-1 所示:

图8-1 RS-232接口电路图

上位机可采用串口调试助手,简单易用,界面清晰。上位机发送的数据还可以回显至上位机,在接收区内显示。调试界面如图8-2所示。

42

东北林业大学 “3+1”实验班

图8-2 串口调试助手上位机界面

【实验内容】

1、向串口发送一个字符串“Computer is foll !”,并间隔向PC发送字符“a”。 MSP430单片机与PC上位机通信波特率设置为9600bps,没有校验位,数据位为8位,停止位为1位。波特率生成采用低频波特率模式。 2、将从串口输入的数据字符反过来打印在终端上。

MSP430单片机与PC上位机通信波特率设置为9600bps,没有校验位,数据位为8位,停止位为1位。波特率生成采用低频波特率模式。

3、回顾按键检测程序,当有按键按下时,将相应的按键编码通过串口发送给计算机,在虚拟终端上显示。如:按下KEY5,将在计算机的虚拟终端上显示“KEY5”(选做)。

【实验步骤】

内容1:向串口发送一个字符串

1、将单片机通过MAX3232/232通信模块与PC机的串口相连。其中P3.3/UCA0TXD连接TX引脚,P3.4/UCA0RXD连接RX引脚。 2、配置电脑串行口 (1)将鼠标移动到电脑桌面的计算机,并单击右键,选择“设备管理器”,弹出图8-3所示窗口;

43

东北林业大学 “3+1”实验班

图8-3 上位机设备管理器界面

(2)展开端口(COM和LPT),右键单击通信端口(COM1),并选择属性,打开通信端口(COM1)属性窗口,选择端口设置选项卡,设置串行通信的相关选项,如图8-4所示;

图8-4 通信端口(COM1)属性窗口

(3)双击打开串口调试助手,并设置相关选项如图8-2所示。 建立新工程,并命名为lab8_1。

3、在新建工程的编辑窗口输入如下代码:

#include

void USCI_A0_Init() //USCI_A0的初始化 {

44

东北林业大学 “3+1”实验班

P3SEL |= BIT3+BIT4; // P3.3和P3.4选择UART通信功能 UCA0CTL1 |= UCSWRST; // 复位寄存器设置 UCA0CTL0 = 0x00;

UCA0CTL1 |= UCSSEL_1; // 波特率发生器参考时钟设置为ACLK,ACLK=32768Hz UCA0BR0 = 0x03; // 波特率设置为9600bps UCA0BR1 = 0x00;

UCA0MCTL |= UCBRS_3 + UCBRF_0; // 调制器设置

UCA0CTL1 &= ~UCSWRST; // 完成USCI_A0初始化设置 }

void USCI_A0_PutChar(char Chr) //单个字符发送函数 {

UCA0TXBUF = Chr;

while (!(UCA0IFG&UCTXIFG)); //等待上一个字节发送完毕 }

void USCI_A0_PutString(const char *s) //字符串发送函数 {

while(*s !='\\0') {

USCI_A0_PutChar(*s++); } }

char USCI_A0_GetChar(void) //单个字符接收函数 {

while(!(UCA0IFG&UCRXIFG)); //等待接收1字节 return (UCA0RXBUF); }

void main(void) { }

WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 USCI_A0_Init(); //USCI_A0初始化 USCI_A0_PutString(\); while(1) {

USCI_A0_PutChar('a'); }

4、编译、调试并下载程序到开发板。 5、运行程序,观察现象。

内容2:将从串口输入的数据字符反过来打印在终端上

#include

45

东北林业大学 “3+1”实验班

void main(void) {

WDTCTL = WDTPW + WDTHOLD; // Stop WDT

P3SEL = BIT3+BIT4; // P3.4,5 = USCI_A0 TXD/RXD

UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL1 |= UCSSEL_1; // CLK = ACLK

UCA0BR0 = 0x03; // 32kHz/9600=3.41 (see User's Guide) UCA0BR1 = 0x00;

UCA0MCTL = UCBRS_3+UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0 UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine** UCA0IE |= UCRXIE; // Enable USCI_A0 RX interrupt

__bis_SR_register(LPM3_bits + GIE); // Enter LPM3, interrupts enabled __no_operation(); // For debugger }

// Echo back RXed character, confirm TX buffer is ready first #pragma vector=USCI_A0_VECTOR

__interrupt void USCI_A0_ISR(void) {

switch(__even_in_range(UCA0IV,4)) {

case 0:break; // Vector 0 - no interrupt case 2: // Vector 2 - RXIFG

while (!(UCA0IFG&UCTXIFG)); // USCI_A0 TX buffer ready? UCA0TXBUF = UCA0RXBUF; // TX -> RXed character break;

case 4:break; // Vector 4 - TXIFG default: break; } }

内容3:在计算机的虚拟终端上打印按键键值

1、将单片机通过MAX3232/232通信模块与PC机的串口相连。其中P4.4/UCA1TXD连接TX引脚,P4.5/UCA1RXD连接RX引脚。并配置好计算机上的串口调试助手。 2、导入工程“Lcd_and_Key”,并在此基础上添加UART的相关文件:uart.c和uart.h。 uart.c文件如下:

/***********************************Copyright(c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

46

东北林业大学 “3+1”实验班

**----------------------------文件信息----------------------------------------- **文 件 名: uart.c **创 建 人: 刘 毅 **最后修改日期: 2014年11月13日 **描 述:

**---------------------------历史版本信息------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日 ** 描 述: 原始版本

******************************************************************************/ #include #include \ //#include \ #include \

//#include \

/****************************************************************************** 函 数 名:AppUart_init(void) 功 能:Uart_A1初始化 入口参数:无 返 回 值:无

******************************************************************************/ void AppUart_init(void) {

// SELECT_ACLK(SELA__XT1CLK); // Source ACLK from LFXT1 P4SEL = BIT5 + BIT4; // P4.4,5 = USCI_A1 TXD/RXD

UCA1CTL1 |= UCSWRST; // **Put state machine in reset** UCA1CTL0 = 0x00;

UCA1CTL1 = UCSSEL_1 + UCSWRST; // Use ACLK, keep RESET

UCA1BR0 = 0x03; // 32kHz/9600=3.41 (see User's Guide) UCA1BR1 = 0x00; //

UCA1MCTL = UCBRS_3 + UCBRF_0; // Modulation UCBRSx=3, UCBRFx=0 UCA1CTL1 &= ~UCSWRST; // **Initialize USCI state machine** }

/****************************************************************************** 函 数 名:AppUart_getChar(void) 功 能:单个字符接收函数 入口参数:无

返 回 值:receiveChar 接收的字符

******************************************************************************/ uint8_t AppUart_getChar(void) {

uint8_t receiveChar;

47

东北林业大学 “3+1”实验班

while (!(UCA1IFG & UCRXIFG)) ; receiveChar = UCA1RXBUF; return receiveChar; }

/****************************************************************************** 函 数 名:AppUart_putChar() 功 能:单个字符发送函数

入口参数:transmitChar 要发送的字符 返 回 值:无

******************************************************************************/ void AppUart_putChar(uint8_t transmitChar) {

while (!(UCA1IFG & UCTXIFG)) ; UCA1TXBUF = transmitChar; }

/****************************************************************************** 函 数 名:AppUart_PutString() 功 能:字符串发送函数 入口参数:s 要发送的字符串 返 回 值:无

******************************************************************************/ void AppUart_PutString(const char *s) {

while(*s !='\\0') {

AppUart_putChar(*s++); } }

uart.h文件如下:

/**********************************Copyright (c)******************************* ** 东北林业大学机电工程学院 ** 3+1 创新实验室 ** www.nefu.edu.cn **

**----------------------------文件信息---------------------------------------- **文 件 名: uart.h **创 建 人: 刘 毅 **最后修改日期: 2014年11月13日 **描 述:

**--------------------------历史版本信息--------------------------------------- ** 创 建 人: 刘 毅 ** 版 本: v1.0

** 日 期: 2014年11月13日

48

东北林业大学 “3+1”实验班

** 描 述: 原始版本

******************************************************************************/ #ifndef HAL_APPUART_H #define HAL_APPUART_H

#include

extern void AppUart_init(void); //Uart_A1初始化 extern uint8_t AppUart_getChar(void); //单个字符接收函数 extern void AppUart_putChar(uint8_t transmitChar);//单个字符发送函数 extern void AppUart_PutString(const char *s); //字符串发送函数 #endif /* HAL_APPUART_H */

3、在main.c文件的键盘检测程序中调用字符串发送函数,将按键编码发送到PC机上。

【思考与分析】

1、MSP430F5529的串口波特率如何计算?怎样配置寄存器来改变串口的波特率?

2、修改代码,使串口能够格式化输出数值到虚拟终端。

49