MSP430F5529通过定时器A产生两个反相频率占空比可调PWM波
MSP430F5529的定时器还是挺好用的,具有定时计数和捕获的功能,具有高达7个捕获比较寄存器,支持多路捕获/比较。这里我用到了两个定时器产生两个反相的PWM波并通过一个捕获比较器捕获其中一个PWM波,显示在OLED12864显示屏上(本实验使用的是MSP-EXP430F5529LP开发板,使用的软件是IAR)。
实现的功能为:
1、利用MSP430内部PWM波发生器产生两路反相频率为 50Hz到1KHz,占空比为10%到90%的PWM波。
2、要求频率和占空比通过按键S1和S2分别设置。频率按50Hz步进,占空比按10%步进。
3、利用MSP430单片机的捕获/比较器测量该PWM波 的频率和占空比,且显示于oled屏幕上。
(这里使用的显示屏是四针的oled12864)
连接方式为SDA口连接P6.5
SCL口连接P6.0
同时使用的VCC是3V
P1.2口和P1.4口输出反相的可调频率和周期的PWM波
P2.0为捕获输入,所以需要连接P1.2口和P2.0口
连接图如下:
上代码
定时器设置:
/************************************************************
文件名称: timer.c
文件概述: 对TA0输出PWM波 TA1进行输入捕获的配置工作
包含的头文件及概述: timer.h :函数声明及部分宏定义
引脚声明:
TA0 PWM波输出口 :P1.2 P1.4
TA1 输入捕获输入口:P2.0
*************************************************************/
#include "msp430f5529.h"
#include "timer.h"
char flag=0; //用于标记当前捕获状态 0:就绪 1:捕获到一个上升沿 2:捕获到一个下降沿
unsigned int pos_time=0; //用于记录正脉宽
unsigned int period =0; //用于记录周期
unsigned int start =0; //开始测量上升沿
unsigned int pause =0;
unsigned int num[3];
unsigned int T,TP,D;
/******************
PWM波初始化
输出两种反相的PWM波
********************/
void PWM_Init( void )
{
P1DIR |= BIT2; //配置P1.2复用为定时器TA0.1
P1SEL |= BIT2; //配置P1.2为输出
P1DIR |= BIT4; //配置P1.4复用为定时器TA0.3
P1SEL |= BIT4; //配置P1.4为输出
TA0CTL = TASSEL_2 + MC_1 + TACLR + ID_3;//使用SMCLK为时钟源 增计数模式 8分频
TA0CCTL1 = OUTMOD_7 ; //TA0输出模式7
TA0CCTL3 = OUTMOD_3 ; //TA3输出模式3
TA0CCR0 = 10000 ; //初始化频率50赫兹
TA0CCR1 = 1000 ; //初始化占空比为10%
}
/******************
捕捉器初始化
Capture 函数
********************/
void Capture_Init(void)
{
P2DIR &= ~BIT0 ; //配置P2.0复用为定时器TA1.1
P2SEL |= BIT0 ; //配置P2.0为输入
TA1CTL = TASSEL_2 + MC_2 + TACLR + ID_3 ; //使用SMCLK为时钟源 连续计数模式 8分频
TA1CCTL1 = CM0 + SCS + CAP + CCIE +CCIS_0; //捕获模式 上升沿捕获 同步 中断使能 CCI1A(P 2.0)
_BIS_SR( GIE ); //使能系统总中断
}
/*中断子函数*/
#pragma vector = TIMER1_A1_VECTOR
__interrupt void Timer_A1 ( void )
{
if(TA1IV==2)
{
if(P2IN&BIT0)
{
if(flag==0)
{
start = TA1CCR1;
flag = 1;
}
if(flag==2)
{
period = TA1CCR1-start;
flag=3;
TA1CCR1 = 0;
TA1CCTL1&=~CCIE;
}
else
{
if(flag==1)
{
pos_time = TA1CCR1-start;
flag = 2;
}
}
}
}
}
按键设置:
/*********************************************************************************
*Copyright(C),UESTC
*FileName: 独立按键配置
*Author: Tonge
*Version: 1.0
*Date: 2016.12.2
*Description: 配置msp430f5529的独立按键
MSP430F5529
-----------------
/|\| |
| | |
---|RST |
| P2.1|-->KEYLEFT
| P1.1|-->KEYRIGHT
*Others: None
*Function List:
1.void KeyInit(void) 独立按键配置初始化,上电调用一次即可。
2.enum key_type KeyScan(void)按键扫描程序返回枚举型键值
其中key_type{NOKEY,KEYLEFT,KEYRIGHT};
**********************************************************************************/
#include "msp430f5529.h"
#include "key.h"
static enum key_type key_value = NOKEY;
static int key_down_flag = 0;
enum key_type KeyScan(void)
{
if( KEY_L )
key_value = KEYLEFT;
else if( KEY_R )
key_value = KEYRIGHT;
else
key_value = NOKEY;
//防止一次按下多次响应,不等待按键抬起,不过多占用CPU
if (key_down_flag == 0 && key_value != NOKEY)
{
key_down_flag = 1;//第一次监测到按键,按下标志置位,返回此时键值
}
else if (key_down_flag == 1 && key_value != NOKEY)
{
key_value = NOKEY;//第一次之后检测按键按下,返回空值
}
else
{
key_down_flag = 0;//检测按键抬起,按下标识复位,为下一次按下准备
}
return key_value;
}
void KeyInit(void)
{
P1DIR &= ~BIT1; //设置按键IO为输入模式
P2DIR &= ~BIT1;
P1REN |= BIT1; //使能按键上、下拉电阻
P2REN |= BIT1;
P1OUT |= BIT1; //设置按键IO为上拉电阻模式
P2OUT |= BIT1;
}
主函数:
/***************************************************
采用TI公司的MSP430F5529芯片
使用MSP-EXP430F5529LP开发板
实现的功能为:
1、利用MSP430内部PWM波发生器产生频率为 50~1kHz,占空比为10%~90%的PWM波。
2、要求频率和占空比通过按键S1和S2分别设置。频 率按50Hz步进,占空比按10%步进。
3、利用MSP430单片机的捕获/比较器测量该PWM波 的频率和占空比,且显示于oled屏幕上。
(这里使用的显示屏是四针的oled12864)
连接方式为SDA口连接P6.5
SCL口连接P6.0
同时使用的VCC是3V
P1.2口和P1.4口输出反相的可调频率和周期的PWM波
P2.0为捕获输入,所以需要连接P1.2口和P2.0口
***************************************************/
#include "MSP430F5529.h"
#include "clk.h"
#include "key.h"
#include "timer.h"
#include "IIC.h"
/****************需要显示的一系列字符串***************/
unsigned char string1[]={"PWM&Capture"};
unsigned char string2[]={"Frequency:"};
unsigned char string3[]={"post_duty:"};
unsigned char string4[]={"Hz"};
unsigned char string5[]={"%"};
void main( )
{
enum key_type key;
unsigned int duty_num=10; //用于控制占空比的变量
unsigned int fre_num=100; //用于控制频率的变量
float duty=0; //用于计算占空比
float fre=0; //用于计算频率
WDTCTL = WDTPW+WDTHOLD; // 关闭看门狗
ClkInit(); //时钟初始化
KeyInit(); //独立按键初始化
LCD_Init(); //显示屏初始化
PWM_Init(); //PWM波输出初始化
Capture_Init(); //输入捕获初始化
/*初始化界面*/
//LCD_ShowString(0,0,string1,16);
LCD_ShowString(0,0,string2,12);
LCD_ShowString(0,2,string3,12);
LCD_ShowString(112,0,string4,12);
LCD_ShowString(112,2,string5,12);
while(1)
{
key = KeyScan();
if( key != NOKEY )
{
switch(key)
{
case KEYLEFT :
{
duty_num+=10;
if(duty_num>90) //防止占空比超出范围
{
duty_num=10;
}
break;
}
case KEYRIGHT :
{
fre_num+=100;
if(fre_num>2000) //防止频率超出范围
{
fre_num=100;
}
break;
}
}
TA0CCR0=1000000/fre_num ;
TA0CCR1=(int)(TA0CCR0*(((float)duty_num)/100));
TA0CCR2=TA0CCR0;
TA0CCR3=TA0CCR1;
}
if(flag==3)
{
duty = 100*(((float)pos_time)/((float)period))+1; //计算占空比
fre=500000/(float)period+1; //计算频率
LCD_ShowNum(87,0,(unsigned long)fre,3,12); //显示占空比和频率
LCD_ShowNum(87,2,duty_num,3,12);
flag=0;
TA1CCTL1|=CCIE;
}
}
}
大概的设置就是这样了,放上几张演示图
我也是初学,很多地方都不太懂,错误的地方还请大家斧正。
也欢迎大家和我交流!
另外需要源码的童鞋,我把代码放在下面的链接里了,免费下载。
链接: link.