一、实验室名称:MSP430 单片机实验室
二、实验项目名称:PWM 波发生器及 PWM 波频率及占空比测量
三、实验原理:
(1)PWM 信号的产生
PWM 信号是一种具有固定周期不定占空比的数字信号,如下图 4-1 所示:
图 4-1 PWM 信号波形
如果 Timer_A 定时器的计数器工作在增计数方式,输出采用输出模式 7(复位/置位模
式),则可利用寄存器 TAxCCR0 控制 PWM 波形的周期,用某个寄存器 TAxCCRx 控制占空
比。这样 Timer_A 就可以产生出任意占空比的 PWM 波形。如图 4-2 所示。
图 4-2 利用 Timer_A 产生任意占空比的 PWM 信号
可以随时间变化任意改变 PWM 信号的频率和占空比,具体做法:改变 CCR0 值(改变
周期),改变 CCRx 值(改变占空比)。如图 4-3 所示。
图 4-3 通过配置 CCR0 和 CCRx 值调整 PWM 信号的占空比
PWM 不需要修改频率和占空比时,CPU 在做完 Timer_A 初始化工作之后,Timer_A 就
1
能自动输出 PWM,而不需利用中断维持 PWM 输出,此时 CPU 就可以进入低功耗状态。
(2)捕获/比较器
Timer_A 有多个相同的捕获/比较模块,为实时处理提供灵活的手段,每个模块都可用
于捕获事件发生的时间或产生定时间隔。通过 TACCTLx 中的 CAP 位选择模式,该模块既
可用于捕获模式,也可用于比较模式。当发生捕获事件或定时时间到都将引起中断。捕获/
比较模块的结构如图 4-4 所示。
图 4-4 捕获/比较模块的逻辑结构
捕获模式
当 TACCTLx 中的 CAP = 1,该模块工作在捕获模式。每个捕获/比较寄存器可以用来记
录时间事件,例如:
▲ 测量软件程序所用时间
▲ 测量硬件事件之间的时间
▲ 测量系统频率
用 CM1 和 CM0 位选择捕获条件,可以选择禁止捕获、上升沿捕获、下降沿捕获或者
上升沿下降沿都捕获。当捕获完成后,定时器的值被复制到 TAxCCRn 寄存器,并且中断
标志 CCIFG 置位。如果总的中断允许位 GIE 允许,相应的中断允许位 CCIE 也允许,则将
产生中断请求。
比较模式
2
当 TACCTLx 中的 CAP = 0,该模块工作在比较模式。比较方式主要用于为软件或应用
硬件产生定时,还可为 D/A 转换功能或者马达控制等各种用途产生脉宽调制(PWM)输出
信号。
在计数器 TAxR 计数到 TAxCCRn(n 代表具体的捕获比较寄存器)的值时:
▲ 中断标志 CCIFG 置位
▲ 内部信号 EQUx=1
▲ EQUx 根据输出模式影响输出
▲ 输入信号 CCI 被锁存在 SCCI
(3)独立按键
参见实验一中相关原理介绍。
(4)OLED 显示屏
参见实验一中相关原理介绍
四、实验目的:
要求学习 MSP430 单片机内部 PWM 波发生器和内部捕获/比较器的操作,实验板上附
带的独立按键及 OLED 的使用。学习基于 430 单片机集成编译仿真环境的代码调试。
五、实验内容:
利用 MSP430 内部 PWM 波发生器产生频率为 50Hz~1kHz,占空比为 10%~90%的 PWM
波,频率和占空比通过按键 S1 和 S2 分别往复设置(频率按 50Hz 步进,占空比按 5%步进),
并利用 MSP430 单片机的捕获/比较器测量该 PWM 波的频率和占空比,且显示于 OLED 上。
扩展要求:(1)在 OLED 上显示出你所产生的 PWM 波图形(2)产生两路刚好反相的 PWM
波,显示于 OLED 上。
六、实验器材(设备、元器件):
MSP430F5529 开发板,OLED 显示屏,个人电脑(运行 IAR 软件),下载线,示波器。
七、实验步骤及实验数据结果分析:
(1)实验的程序流程框图:
3
(2)实验的程序代码(含注释):
#include "msp430f5529.h"
#include "IIC.c"
#include "math.h"
unsigned int index1;
unsigned int index2;
int hz[20]={50};
int duty[17]={10};
unsigned int num[3];
unsigned int T,TP,D,flag;
//定义频率数组
//定义占空比数组
int wave_B[120];
int wave_S[120];
int point_num_T[20];
4
unsigned int wave_T;
unsigned int wave_D;
unsigned int a=0;
unsigned int change=1;
void turn_w(int wave_B[120]);
void display_w(int wave_B[120]);
int main( void )
{
// Stop watchdog timer to prevent time out reset
WDTCTL = WDTPW + WDTHOLD;
for(unsigned int i=1;i<20;i++)
hz[i]=hz[i-1]+50;
for(unsigned int i=1;i<17;i++)
duty[i]=duty[i-1]+5;
index1=0;
index2=0;
UCSCTL4|=SELA_2; //
//PWM 波产生
P1DIR|=BIT2;
P1SEL|=BIT2;
ACLK:32768HZ
////P1.2 为 PWM 输出口
TA0CCR0=(int)(32768/hz[index1]);
TA0CCR1=(int)(TA0CCR0*(100-duty[index2])/100);
TA0CCTL1|=OUTMOD_3;
TA0CTL|=TASSEL_1+MC_1+TACLR;
//置位/复位模式
//开始
//依频率计算 TA0CCR0
////依占空比计算 TA0CCR1
//按键设置
P2DIR&=~BIT1;
P2IFG=0x00;
P2IE|=BIT1;
P2IES|=BIT1;
P2REN|=BIT1;
P2OUT|=BIT1;
P1DIR&=~BIT1;
P1IFG=0x00;
P1IE|=BIT1;
P1IES|=BIT1;
P1REN|=BIT1;
5
P1OUT|=BIT1;
//捕获模式测瞬时频率及占空比
P2DIR&=~BIT4;
P2SEL|=BIT4;
//用 TIMER 2,上升沿捕获+同步捕获+捕获模式+开中断
TA2CCTL1|=CM_1+SCS+CAP+CCIE+CCIS_0;
//选 SMCLK+连续计数+8 分频
TA2CTL|=TASSEL_2+MC_2+TACLR+ID_3;
LCD_Init();
__enable_interrupt();
while(1)
{
if(change==1)
{
for(unsigned int i=0;i<20;i++)
{
point_num_T[i]=(int)(ceil(120/(i+1)));
}
wave_T=point_num_T[hz[index1]/50-1];
wave_D=(int)(ceil(wave_T*duty[index2]/100));
for(unsigned int i=0;i
LCD_ShowChar(32,4,':',16);
LCD_ShowNum(40,4,T,4,16);
LCD_ShowChar(16,6,'D',16);
LCD_ShowChar(24,6,'U',16);
LCD_ShowChar(32,6,'T',16);
LCD_ShowChar(40,6,'Y',16);
LCD_ShowChar(48,6,':',16);
LCD_ShowNum(56,6,TP,4,16);
LCD_CLS();
}
}
#pragma vector=TIMER2_A1_VECTOR
__interrupt void timer2()
{
num[flag]=TA2CCR1;
flag++;
if(flag==1)
{
TA2CCTL1&=~CM_1;
TA2CCTL1|=CM_2;
}
if(flag==2)
{
TA2CCTL1&=~CM_2;
TA2CCTL1|=CM_1;
}
if(flag==3)
{
flag=0;
T=num[2]-num[0];
TP=num[1]-num[0];
TA2CTL|=TACLR;
}
TA2CCTL1&=~CCIFG;
}
//周期时间
//高电平持续时间
#pragma vector=PORT2_VECTOR
__interrupt void Port2_1()
{
if(P2IFG&BIT1)
{
7
TA1CCR0=0xffff;
TA1CTL|=TASSEL_1+MC_1+TACLR;
while(TA1R<=655);
if((P2IN&BIT1)==0)
{
//利用 timer1 延时 20ms
index2++;
if(index2==17)
index2=0;
}
}
TA0CCR0=(int)(32768/hz[index1]);
TA0CCR1=(int)(TA0CCR0*(100-duty[index2])/100); //更改占空比
change=1;
P2IFG&=~BIT1;
}
#pragma vector=PORT1_VECTOR
__interrupt void Port1_1()
{
if(P1IFG&BIT1)
{
TA1CCR0=0xffff;
TA1CTL|=TASSEL_1+MC_1+TACLR;
while(TA1R<=655);
if((P1IN&BIT1)==0)
{
index1++;
if(index1==20)
index1=0;
}
}
TA0CCR0=(int)(32768/hz[index1]);
TA0CCR1=(int)(TA0CCR0*(100-duty[index2])/100); //更改频率
change=1;
P1IFG&=~BIT1;
}
//波形显示函数
void display_w(int wave_B[120])
{
for(unsigned int i=0;i<120;i++)
{
if((wave_B[i]==1)&&(wave_B[i+1]!=0))
8