清华大学计算机硬件技术基础实验报告 - 图文

更新时间:2023-12-20 08:45:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验名称:实验8:定时器

姓名:袁鹏 学号:2013011780 实验班号:33 机器号:42

一.实验目的

了解 MSP430 定时器A 工作原理,掌握MSP430 定时器A 的控制方法。 二.实验任务

1. 定时器A的定时功能学习

采用定时器A的增计数方式(Up Mode),每秒产生一次CCR0的TACCR0 CCIFG中断, 计 数秒值,将计数值通过8个发光二极管显示出来,并控制蜂鸣器每5秒发出一警报声。

实现方法:将P1.0~P1.7与LED1~LED7连接起来,P2.0与蜂鸣器连接起来,采用32.768KHz的外部晶振作为ACLK的时钟源,因此P2.6与P2.7要与外部晶振连接而不能作为基本输入输出。选择增计数方式,每隔一秒改变一次发光二极管状态,每隔五秒发出一声警报。具体代码如下: #include \#include %unsigned int count=0,s=0; void delay() //延时函数 { unsigned int i; for(i=0;i<0xffff;i++); } void buzz() //蜂鸣器响一声 { P2OUT&=~BIT0; delay(); P2OUT|=BIT0; delay(); } int main ( void ) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 _DINT(); P1SEL=0; //设置P1.0~P1.7为基本输出 P1SEL2=0; P1OUT=0XFF; P1DIR=0XFF; P2SEL|=BIT6+BIT7; //启用外部晶振 P2SEL2&=~(BIT6+BIT7); P2DIR&=~BIT6; P2DIR|=BIT7; P2SEL&=~BIT0; //设置P2.0为输出 P2SEL&=~BIT0; P2OUT|=BIT0; P2DIR|=BIT0; TA0CTL|=TACLR+TASSEL_1+MC_1; //采用ACLK时钟源,清零计数器,选择增计数方式 TA0CCR0=32767; TA0CCTL0|=CCIE; //打开中断允许 _EINT(); while(1) { if(count==257) //设置LED灯显示 count=1; P1OUT=~count; if(s==5) //控制蜂鸣器鸣叫 { buzz(); s=0; } } } #pragma vector=TIMER0_A0_VECTOR __interrupt void time() //中断程序 { count++; s++; } 思考:当采用外部晶振作为时钟源时,端口P2.6~P2.7只能设置为外部晶振引脚,而不能设置为基本输入输出,这样在整体控制LED灯时不便于布线以及端口之间的连接,十分不方便。因此可以考虑采用SMCLK为时钟信号,并设置SMCLK的时钟源为12KHz的VLOCLK,这时只许再设置一下TAR0CR0的计数值使中断恰好为一秒即可,大大方便布线。

具体改进代码如下: #include \#include %unsigned int count=0,s=0; void delay() //延时函数 { unsigned int i; for(i=0;i<0xffff;i++); } void buzz() //蜂鸣器响一声 { P1OUT&=~BIT7; delay(); P1OUT|=BIT7; delay(); } int main ( void ) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 _DINT(); P2SEL=0; //设置P2.0~P2.7端口为基本输出 P2SEL2=0; P2OUT=0XFF; P2DIR=0XFF; P1SEL&=~BIT7; //设置P1.7端口为基本输出 P1SEL2&=~BIT7; P1OUT|=BIT7; P1DIR|=BIT7; BCSCTL3|=LFXT1S_2; //设置SMCLK为12KHz的VLOCLK TA0CTL|=TACLR+TASSEL_1+MC_1; //采用SMCLK时钟源,清零计数器,选择增计数方式 TA0CCR0=11999; TA0CCTL0|=CCIE; //打开中断允许 _EINT(); while(1) { if(count==257) //设置LED灯显示 count=1; P2OUT=~count; if(s==5) //控制蜂鸣器鸣叫 { buzz(); s=0; }

} } #pragma vector=TIMER0_A0_VECTOR __interrupt void time() //中断程序 { count++; s++; } 思考:采用定时器的计时、实验3 中任务1 延时方式的计时、实验7 中任务6 的计时, 这三种方法CPU 在执行流程上有什么不同?

这三种方法采用了不同的原理来实现一秒的定时,因此CPU在执行流程上也会不同。实验3中的任务的延时方式是让CPU执行无用的计算来获得1S计时,比较不精确而且在计时的同时CPU不能执行其他操作;实验7中的任务6是让CPU接收一个端口发出的3KHz的ACLK信号,每获得一个低电平就执行一次中断,计数加一,因此可以获得较为准确的1S;采用定时器的计时是使用单片机的定时器中的TAxCCR0来记录时钟信号产生的个数,根据时钟信号的周期来确定1S所需记录个数,因此较为精确,CPU只需每秒执行一次中断响应即可。 2. PWM 波形输出

采用定时器的比较输出功能, 编程在 P1.6 上输出频率为264Hz、占空比为50%的方波。 (占空比:指高电平占一个周期中的比例)。可用示波器测量该波形。

实现方法:选择ACLK为时钟信号,选择频率为32.768KHz的外部晶振为时钟源。设置P1.6为TA0输出,设置TA0CCR0、TA0CCR1的值来改变脉冲的频率和占空比(TA0CCR0=(1/264)/(1/32768)-1=123,TA0CCR1=(1/264)/(1/32768)*(1-0.5)=62)。 具体代码如下: #include \#include \int main ( void ) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 P2SEL|=BIT6+BIT7; //启用外部晶振 P2SEL2&=~(BIT6+BIT7); P2DIR&=~BIT6; P2DIR|=BIT7; P1SEL|=BIT6; //设置P1.6输出方波 P2SEL2&=~BIT6; P1DIR|=BIT6; TA0CTL=TACLR+TASSEL_1+MC_1; //采用ACLK时钟源,清零计数器,选择增计数方式 TA0CCR0=123; //设置计数频率、占空比和计数模式 TA0CCR1=62; TA0CCTL1|=OUTMOD_2; while(1) { }; } 思考:之所以选择32.768KHz的外部晶振作为时钟源是因为在实验7中由示波器测量发现,外部晶振频率较为精确,而12KHz的VLOCLK和1MHz的DCOCLK都受环境和温度影响较大,因此在精确控制方波频率时不适合作为时钟源。

(选做)如果在P1.6 上分别输出264Hz、297Hz、330Hz、352Hz、396Hz、440Hz、495Hz、 538Hz 的方波信号,并用这个方波信号去控制蜂鸣器,将听到1、2、3、4、5、6、7、! 一个8 度的音乐声。发声原理可参看课外选做趣味实验1 的说明。 注意:PWM 波形的输出与中断无关。

实现方法:选择ACLK为时钟信号,选择频率为32.768KHz的外部晶振为时钟源。设置P1.6为TA0输出,设置TA0CCR0、TA0CCR1的值来改变脉冲的频率和占空比。经实验对比,占空比为百分之八十蜂鸣器发声效果最好,具体代码如下: #include \#include \void buzz(int i) //控制P1.6输出不同频率的方波 { unsigned int m; if(i==1) m=123; //264Hz else if(i==2) m=109; //297Hz else if(i==3) m=98; //330Hz else if(i==4) m=92; //352Hz else if(i==5) m=82; //396Hz else if(i==6) m=73; //440Hz else if(i==7) m=65; //495Hz else if(i==8) m=61; //528Hz TA0CCR0=m; //设置计数频率、占空比和计数模式 TA0CCR1=(m+1)/5; TA0CCTL1|=OUTMOD_2; } int main ( void ) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 P2SEL|=BIT6+BIT7; //启用外部晶振 P2SEL2&=~(BIT6+BIT7); P2DIR&=~BIT6; P2DIR|=BIT7; P1SEL|=BIT6; //设置P1.6输出方波 P2SEL2&=~BIT6; P1DIR|=BIT6; TA0CTL=TACLR+TASSEL_1+MC_1; //采用ACLK时钟源,清零计数器,选择增计数方式 buzz(1); //设置P1.6输出的音调1(可根据需要改) while(1) { }; } 思考:可以反复改变占空比来确定哪个最合适。当使用蜂鸣器发声时,蜂鸣器上有一贴纸会严重阻碍蜂鸣器震动,因此做本次实验前需先揭掉蜂鸣器上贴纸。 3. (选做)定时器A 的定时功能应用

将实验3中的电子表设计,改用定时器来完成1秒的定时。

编程提示:主循环中控制数码管的显示,显示的时间值由定时中断提供。

实现方法:将Sa~Sh与Q0~Q7连接起来,将P1.0~P1.7与S1~BUZZ连接起来,用S1~S4来控制显示的数码管,用DS输入数据、DHCP输入脉冲,STCP输入终止脉冲,利用串并转换芯片来控制数码管。选择SMCLK作为时钟信号,并设置12KHz的VLOCLK作为时钟源,设置TA0CCR0的数值使得一秒钟产生一次中断来计时

(TA0CCR0=1/(1/12000)-1=11999),计时结束后清零各端口,并控制蜂鸣器响一声。具体代码如下: #include \#include %unsigned int c=0,s=0,a1,a2,a3,a4; unsigned char LED[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; //LED灯 unsigned char BIT[8]={BIT0,BIT1,BIT2,BIT3,BIT4,BIT5,BIT6,BIT7}; //数字位

void delay() //延时函数1 { unsigned int i; for(i=0;i<0xffff;i++); } void buzz() //蜂鸣器响一声 { P1OUT&=~BIT7; delay(); P1OUT|=BIT7; delay(); } void light(char led) //点灯函数(串行) { unsigned int i; for(i=0;i<8;i++) { if((led&BIT[7-i])==0) P1OUT&=~BIT4; //输出信号 else P1OUT|=BIT4; P1OUT|=BIT5; //SHCP发出脉冲 P1OUT&=~BIT5; } P1OUT|=BIT6; //STCP脉冲 P1OUT&=~BIT6; } int main ( void ) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 _DINT(); P1SEL=0; //设置P1.0~P1.7为基本输出 P1SEL2=0; P1OUT=0xff; P1DIR=0xff; BCSCTL3|=LFXT1S_2; //设置SMCLK为12KHz的VLOCLK TA0CTL|=TACLR+TASSEL_1+MC_1; //采用SMCLK时钟源,清零计数器,选择增计数方式 TA0CCR0=11999; TA0CCTL0|=CCIE; //打开中断允许 _EINT(); while(1) { light(LED[a4]); P1OUT|=BIT0; //置第一位数码管为输出 P1OUT&=~(BIT1+BIT2+BIT3); light(LED[a3]); P1OUT|=BIT1; //置第二位数码管为输出 P1OUT&=~(BIT0+BIT2+BIT3); light(LED[a2]); P1OUT|=BIT2; //置第三位数码管为输出 P1OUT&=~(BIT0+BIT1+BIT3); light(LED[a1]); P1OUT|=BIT3; //置第四位数码管为输出 P1OUT&=~(BIT0+BIT1+BIT2); } } #pragma vector=TIMER0_A0_VECTOR __interrupt void time() //中断程序 { c++; s++; a1=c/600; //计算每位数码管显示的数值 a2=(c-600*a1)/60; a3=(c-600*a1-60*a2)/10; a4=c-600*a1-60*a2-10*a3; if(s==300) //计时到5分钟时蜂鸣器警报并清零重新计时 { buzz(); c=0; s=0; } } 4. (选做) 研究看门狗定时器的定时控制和应用 任务1改用看门狗来完成定时,如何编程?

实现方法:将P1.7与蜂鸣器相连,将P2.0~P2.7与LED1~LED8相连并设置为基本输出。查阅MSP430的头文件中的看门狗内容可以发现,宏定义中已经有关于将看门狗设

置为定时器的宏定义,因此只需设置相应时钟源和看门狗计时周期,然后再编写看门狗中断程序即可实现1S定时,具体代码如下: #include \#include %unsigned int t=0,count=0,s=0; void delay() //延时函数 { unsigned int i; for(i=0;i<0xffff;i++); } void buzz() //蜂鸣器响一声 { P1OUT&=~BIT7; delay(); P1OUT|=BIT7; delay(); } int main ( void ) { _DINT(); P2SEL=0; //设置P2.0~P2.7端口为基本输出 P2SEL2=0; P2OUT=0XFF; P2DIR=0XFF; P1SEL&=~BIT7; //设置P1.7端口为基本输出 P1SEL2&=~BIT7; P1OUT|=BIT7; P1DIR|=BIT7; WDTCTL = WDT_MDLY_8; // 看门狗计时周期 8ms IE1|= WDTIE; // 使能WDT中断 _EINT(); // 使能全局中断 while(1) { if(count==257) //设置LED灯显示 count=1; P2OUT=~count; if(s==5) //控制蜂鸣器鸣叫 { buzz(); s=0; } } } #pragma vector=WDT_VECTOR // 看门狗中断服务子程序 __interrupt void WDT_Timer_ISR(void) { t++; if(t==125) //每隔一秒一次计时 { count++; s++; t=0; } } 附录----有关看门狗的头文件:

//========================================================================================================================== // 相关头文件中的定义 /************************************************************

* WATCHDOG TIMER ************************************************************/ #define __MSP430_HAS_WDT__ /* Definition to show that Module is available */ #define WDTCTL_ (0x0120u) /* Watchdog Timer Control */ DEFW( WDTCTL , WDTCTL_) /* The bit names have been prefixed with \ #define WDTIS0 (0x0001u) #define WDTIS1 (0x0002u) #define WDTSSEL (0x0004u) #define WDTCNTCL (0x0008u) #define WDTTMSEL (0x0010u) #define WDTNMI (0x0020u) #define WDTNMIES (0x0040u) #define WDTHOLD (0x0080u) #define WDTPW (0x5A00u) /* WDT-interval times [1ms] coded with Bits 0-2 */ /* WDT is clocked by fSMCLK (assumed 1MHz) */ #define WDT_MDLY_32 (WDTPW+WDTTMSEL+WDTCNTCL) /* 32ms interval (default) */ #define WDT_MDLY_8 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS0) /* 8ms \ #define WDT_MDLY_0_5 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1) /* 0.5ms \ #define WDT_MDLY_0_064 (WDTPW+WDTTMSEL+WDTCNTCL+WDTIS1+WDTIS0) /* 0.064ms \*/ /* WDT is clocked by fACLK (assumed 32KHz) */ #define WDT_ADLY_1000 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL) /* 1000ms \*/ #define WDT_ADLY_250 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS0) /* 250ms \ #define WDT_ADLY_16 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1) /* 16ms \ #define WDT_ADLY_1_9 (WDTPW+WDTTMSEL+WDTCNTCL+WDTSSEL+WDTIS1+WDTIS0) /* 1.9ms \ /* Watchdog mode -> reset after expired time */ /* WDT is clocked by fSMCLK (assumed 1MHz) */ #define WDT_MRST_32 (WDTPW+WDTCNTCL) /* 32ms interval (default) */ #define WDT_MRST_8 (WDTPW+WDTCNTCL+WDTIS0) /* 8ms \ #define WDT_MRST_0_5 (WDTPW+WDTCNTCL+WDTIS1) /* 0.5ms \ #define WDT_MRST_0_064 (WDTPW+WDTCNTCL+WDTIS1+WDTIS0) /* 0.064ms \ /* WDT is clocked by fACLK (assumed 32KHz) */ #define WDT_ARST_1000 (WDTPW+WDTCNTCL+WDTSSEL) /* 1000ms \ #define WDT_ARST_250 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS0) /* 250ms \ #define WDT_ARST_16 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1) /* 16ms \ #define WDT_ARST_1_9 (WDTPW+WDTCNTCL+WDTSSEL+WDTIS1+WDTIS0) /* 1.9ms \*/ 思考:看门狗定时器是用来防止程序因供电电源、空间电磁干扰或其它原因引起的强烈干扰噪声而跑飞的事故。看门狗本身是一个定时器,当定时器溢出时即进行系统复位,因此需要在程序中对看门狗定时器进行清零,即常说的喂狗。MSP430是默认看门狗是开着的,因此如果不使用看门狗的话要关闭,指令如下:WDTCTL = WDTPW + WDTHOLD。如果打开看门狗则需要在程序中清零,指令如下:

WDTCTL=WDTPW+WDTCNTCL。有关看门狗复位的时间在头文件中已经给出,注意到看门狗复位时间还和所选择的时钟源有关。

从头文件的定义中可以看出主要有两种方式,一种就是当做普通的定时器使用,一种才是作为看门狗,另外就是时钟源可选,选择8M或者32.768K的晶振来获得不同的延时,通过上面可以看出看门狗定时器时间可以到0.064ms~1S,因此在程序中可以灵活的利用看门狗定时器实现想要的功能。

当然我们还是不能忘了看门狗的本能工作是为了维护程序正常运行,但是在程序较为简单时可以考虑使用看门狗定时器来简化程序设计。

5. (课外选做) 趣味实验1 ,音乐播放器和简单电子琴的设计与实现。

蜂鸣器的发声是通过控制与之相连的 I/O 引脚输出方波信号实现的,改变方波的频率,则可以控制蜂鸣器发出的音调;方波输出的个数则可以控制发声的音长。调节音调和音长构成节拍,进而可以设计不同旋律的音乐。

功能一:简单电子琴

实现方法:将P1.0~P1.7与K1~K8连接起来作为基本输入,将P2.1设置为方波输出并于蜂鸣器连接起来,选择ACLK作为时钟信号,并选择32.768KHz的外部晶振作为时钟信号源,按下K1~K8将依次发出Dou,Ruai,Mi,Fa,Sou,La,Xi,!的音调。 具体代码如下: #include \#include \void delay() //延时函数 { unsigned int j; for(j=0;j<0xffff;j++); } void buzz(int i) //控制P2.1输出不同频率的方波 { unsigned int m; if(i==1) m=123; //264Hz else if(i==2) m=109; //297Hz else if(i==3) m=98; //330Hz else if(i==4) m=92; //352Hz else if(i==5) m=82; //396Hz else if(i==6) m=73; //440Hz else if(i==7) m=65; //495Hz else if(i==8) m=61; //528Hz TA1CCR0=m; //设置计数频率、占空比和计数模式 TA1CCR1=(m+1)*2/10; TA1CCTL1|=OUTMOD_2; delay(); //响一段时间停止 TA1CCR1=0; } int main ( void ) { WDTCTL = WDTPW + WDTHOLD; //关闭看门狗 P2SEL|=BIT6+BIT7; //启用外部晶振 P2SEL2&=~(BIT6+BIT7); P2DIR&=~BIT6; P2DIR|=BIT7; P2SEL|=BIT1; //设置P2.1输出方波 P2SEL2&=~BIT1; P2DIR|=BIT1; P1SEL=0; //设置P1.0~P1.7为基本输入 P1SEL2=0; P1OUT=0XFF; P1REN=0XFF; P1DIR=0; TA1CTL=TACLR+TASSEL_1+MC_1; //采用ACLK时钟源,清零计数器,选择增计数方式 while(1) { if((P1IN&BIT0)==0) //根据不同的按键来发出不同的音调 { buzz(1); } else if((P1IN&BIT1)==0) { buzz(2); } else if((P1IN&BIT2)==0) { buzz(3); } else if((P1IN&BIT3)==0)

{ buzz(4); } else if((P1IN&BIT4)==0) { buzz(5); } else if((P1IN&BIT5)==0) { buzz(6); } else if((P1IN&BIT6)==0) { buzz(7); } else if((P1IN&BIT7)==0) { buzz(8); } } } 功能二:音乐播放器

原理:将在 Flash ROM 中以表格形式存放1 个或多个乐谱,含音调和音长信息,编程播放该曲,完成音乐播放功能。

实现方法:将P1.6设置为方波输出并于蜂鸣器连接起来,选择ACLK作为时钟信号,并选择32.768KHz的外部晶振作为时钟信号源,用两个数组存储乐谱,一个存储音调,另一个存储音长,从而实现电子琴功能。下面的代码以两只老虎为例。 具体代码如下: #include \#include \void delay() { unsigned int i; for(i=0;i<0x8fff;i++); } void buzz(int i,int j) //控制P1.6输出不同频率的方波 { unsigned int m,n,o; if(i==0) TA0CCR1=0; else if(i==1) m=123; //264Hz else if(i==2) m=109; //297Hz else if(i==3) m=98; //330Hz else if(i==4) m=92; //352Hz else if(i==5) m=82; //396Hz else if(i==6) m=73; //440Hz else if(i==7) m=65; //495Hz else if(i==8) m=61; //528Hz TA0CCR0=m; //设置计数频率、占空比和计数模式来控制音调 TA0CCR1=m/7; TA0CCTL1|=OUTMOD_2; for(n=0;n

实验名称:实验9:串行通信技术 姓名:袁鹏 学号:2013011780 实验班号:33 机器号:42

一.实验目的

1. 了解异步串行通信原理;

2. 掌握MSP430 异步串行通信模块及其编程方法。 二、实验任务

1. 了解MSP430G2553实验板USB转串口的通信功能,掌握串口助手的使用

MSP430G2553板上的eZ430-FET板载仿真器主要由一片MSP430F1612单片机和一片USB转串口的控制器TUSB 3410芯片组成。除完成目标单片机的程序下载和调试外,F1612单片机还将目标单片机(如G2553)以异步串行方式通信的数据传送给TUSB3410芯片,由TUSB3410将数据转换成USB 传送给PC机的USB接口,在PC机侧对该接口可以用串口助手方式进行控制,支持最高9600波特率的异步串行通信。其中 BRXD、BTXD分别为板载仿真器的串行接收、发送信号,P1.1、P1.2为G2553单片机的串行接收、发送信号。用杜邦线将实验板上BRXD和BTXD连接,利用PC机的串口调试助手程序控制该串口,实现该串口的自发自收功能。 接线如下:

实现效果如下:

思考:异步串行通信接口的收/发双方是怎样建立起通信的?

本文来源:https://www.bwwdw.com/article/piw5.html

Top