msp430f5529产生pwm并且测量pwm-爱代码爱编程
可恶的慕课老师啊,给了一堆毫无逻辑的代码,最后还是我自己整出来。
真是可恶啊!
感谢大佬,王冬冬,一点就通,万分感谢!
msp430代码资料挺少,这不,整出来一个,小细节就不说了,就给各位看看原理。
哈哈,小菜鸡,赶紧那去跑吧--------------------
/******************************************************************************
文件说明:
按下左键:修改频率 50、155、261、366、472、577、683、[788、894、999]
按下右键:修改占空比
******************************************************************************/
/*
利用MSP430内部PWM波发生器产生频率为50~1KHZ,占空比为10%~90%的PWM波,
频率和占空比通过按键设置,
并利用MSP430单片机的捕获/比较器测量该PWM波的频率和占空比,且显示于数码管上
*/
#include <msp430f5529.h>
#include "IIC.h" //包含IIC通信功能与显示函数文件
int Pos_X=50,Pos_Y=2;
int vpp=2500;// 参考电压mv
int ccr0=0;// ccr0的值
int duty_Cilcle=0;// 占空比值
int countP11 =0;// P1.1按下次数
int countP21 =0;// P2.1按下次数
unsigned int Cycle[3];// 用于保存连续2次上升沿捕获的值+1次下降沿捕获的值
int i=0;
int overflow=0;// 溢出次数
unsigned long interval_freq=10555;// 计算频率间隔
int frequency=0;// 频率调整
unsigned long measure_freq=0;//测量频率
unsigned int measure_cycle=0;// 测量占空比
unsigned long cycle0=0,cycle1=0;// 记录捕获次数
void delay()//延时函数
{
unsigned int i;
i = 40000;
do (i--);
while (i != 0);
}
void main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
// 按键IO初始化
P1DIR &= ~BIT1;// 输入方向
P1IE |= BIT1;// 允许中断
P1IES |= BIT1;// 下降沿中断
P1REN |= BIT1;// 上拉使能
P1OUT |= BIT1;
P2DIR &=~BIT1;
P2IE |= BIT1;
P2IES |= BIT1;
P2REN |= BIT1;
P2OUT |= BIT1;
P1DIR |= BIT0; // led初始化
P4DIR |= BIT7;
LCD_Init(); // 初始化显示屏
LCD_ShowString(Pos_X-40,Pos_Y,"Duty",16);
LCD_ShowChar(Pos_X+50,Pos_Y,'%',16);
LCD_ShowString(Pos_X-40,Pos_Y+2,"frequ",16);
LCD_ShowString(Pos_X+60,Pos_Y+2,"Hz",16);
// PWM 配置
P2DIR |= BIT0; // P2.0
P2SEL |= BIT0; // P2.0 and P2.1 options select
ccr0=655;
TA1CCR0 = ccr0-1; // PWM Period 50Hz = 0.02s
TA1CCTL1 = OUTMOD_7; // CCR1 reset/set
duty_Cilcle=65;
TA1CCR1 = duty_Cilcle; // CCR1 PWM duty cycle 10%占空比
TA1CTL = TASSEL_1 + MC_1 + TACLR; // ACLK, up mode, clear TAR
// 捕获模式配置
P1DIR &=~BIT2; // P1.2捕获输入
P1SEL |= BIT2;
TA0CTL=TASSEL_2+TAIE+MC_1+TACLR;// up mode
TA0CCR0=65535-1;
TA0CCTL0 = CCIE;
TA0CCTL1=CAP+CM_1+CCIE+SCS+CCIS_0;// 上升沿捕获
__bis_SR_register(GIE);
while (1){
LCD_ShowNum(Pos_X+10,Pos_Y+2,measure_freq,4,16);// 显示频率
LCD_ShowNum(Pos_X+10,Pos_Y,measure_cycle,2,16);// 显示周期
};
}
// TimeA - 捕获中断函数
#pragma vector=TIMER0_A1_VECTOR //定时器A中断处理
__interrupt void timer_a(void)
{
switch(TA0IV)
{
case 2:
Cycle[i]=TA0CCR1;
++i;
if(i==2) // 捕获了2次上升沿
{
if(overflow>0)
{
cycle0 = 65535-Cycle[0]+(overflow-1)*65535+Cycle[1];
overflow=0;
}
else
cycle0=Cycle[1]-Cycle[0];
measure_freq = 1045000/cycle0;// 求频率
// 修改为下降沿捕获
TA0CCTL1=CAP+CM_2+CCIE+SCS+CCIS_0;
}
// 第3 次计算占空比
if(i==3)
{
if(overflow>0)// 存在定时器溢出次数
{
cycle1 = 65535-Cycle[1]+(overflow-1)*65535+Cycle[2];// 捕获间隔计数值
overflow=0;
}
else
cycle1=Cycle[2]-Cycle[1];
measure_cycle=cycle1*100/cycle0;
TA0CCTL1=CAP+CM_1+CCIE+SCS+CCIS_0;// 改回上升
i=0;
}
TA0CCTL1&=~CCIFG;// 清空捕获标志
break;
default:
break;
}
}
#pragma vector=TIMER0_A0_VECTOR //定时器A中断处理
__interrupt void Overflow(void)
{
if(i==1)
++overflow;
P1OUT ^=BIT0;
P4OUT ^=BIT7;
}
// P1.1中断函数——修改频率50-1KHz
#pragma vector=PORT1_VECTOR
__interrupt void P1_ISR(void)
{
delay();
if(P1IFG&BIT1)
{
while((P1IN&BIT1)==0);
++countP11;
countP11 %=10;
frequency = interval_freq*countP11/100+50;
ccr0 = 32768.0/frequency;
TA1CCR0 = ccr0-1;
duty_Cilcle =ccr0*0.1*(countP21+1);
TA1CCR1=duty_Cilcle;
}
P1IFG &=~BIT1; // 清除标志
}
// P2.1中断函数——修改占空比10%—90%
#pragma vector=PORT2_VECTOR
__interrupt void P2_ISR(void)
{
delay();
if(P2IFG&BIT1)
{
while((P2IN&&BIT1)==0);
++countP21;
countP21 %=9;
duty_Cilcle =ccr0*0.1*(countP21+1);// 占空比+10%
TA1CCR1=duty_Cilcle;
}
P2IFG &=~BIT1; // 清除标志
}