单片机
返回首页

MSP430F5529 DriverLib 库函数学习笔记(六)定时器A产生PWM波

2022-07-19 来源:csdn

平台:Code Composer Studio 10.3.1

MSP430F5529 LaunchPad™ Development Kit

(MSP‑EXP430F5529LP)


       

1.通过Timer_A_outputPWM配置产生PWM波

所选输出引脚为P1.2

在这里插入图片描述

初始化函数

#define TIMER_PERIOD 12500

void Timer_A_PWM_Init(void)

{

    Timer_A_outputPWMParam htim = {0};

//P1.2复用输出

    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2);

//时钟源选为SMCLK = 25MHz

    htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;

    //分频系数设为40

    htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_40;

    //装载值设为12500 - 1

    htim.timerPeriod = TIMER_PERIOD - 1;

    //P1.2 对应 TA0.1 故设为TIMER_A_CAPTURECOMPARE_REGISTER_1

    htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;

    htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;

    //初始比较值为装载值的一半 即初始占空比为50%

    htim.dutyCycle = TIMER_PERIOD / 2;

    //P1.2 对应 TA0.1 为TIMER_A0_BASE

    Timer_A_outputPWM(TIMER_A0_BASE, &htim);

}


计算

时钟源为SMCLK = 25MHz

分频系数为40

装载值为12500 - 1

故所得PWM频率为25MHz/40/12500=50Hz


修改占空比的函数

修改占空比即修改比较值,故使用Timer_A_setCompareValue函数


我选择在外部中断服务函数内进行修改,按下一次按钮分别为占空比减少10%和增加10%


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

//

//This is the PORT2_VECTOR interrupt vector service routine

//

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

#pragma vector=PORT2_VECTOR     // P2口中断源

__interrupt

void Port_2 (void)              // 声明一个中断服务程序,名为Port_2()

{

    if(GPIO_getInterruptStatus(GPIO_PORT_P2, GPIO_PIN1))

    {

        delay_ms(20);

        if(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1))

        {

            //P1.0 = toggle

            Timer_A_setCompareValue

            (

                    TIMER_A0_BASE,

                    TIMER_A_CAPTURECOMPARE_REGISTER_1,

                    Timer_A_getCaptureCompareCount(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_1) - TIMER_PERIOD / 10

            );

            while(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1));

        }

        //P2.1 IFG cleared

        GPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN1);

    }

}


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

//

//This is the PORT1_VECTOR interrupt vector service routine

//

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

#pragma vector=PORT1_VECTOR     // P2口中断源

__interrupt

void Port_1 (void)              // 声明一个中断服务程序,名为Port_1()

{

    if(GPIO_getInterruptStatus(GPIO_PORT_P1, GPIO_PIN1))

    {

        delay_ms(20);

        if(!GPIO_getInputPinValue(GPIO_PORT_P1, GPIO_PIN1))

        {

            //P1.0 = toggle

            Timer_A_setCompareValue

            (

                    TIMER_A0_BASE,

                    TIMER_A_CAPTURECOMPARE_REGISTER_1,

                    Timer_A_getCaptureCompareCount(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_1) + TIMER_PERIOD / 10

            );

            while(!GPIO_getInputPinValue(GPIO_PORT_P1, GPIO_PIN1));

        }

        //P2.1 IFG cleared

        GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN1);

    }

}


整体程序

#include 'driverlib.h'


#define MCLK_IN_HZ      25000000


#define delay_us(x)     __delay_cycles((MCLK_IN_HZ/1000000*(x)))

#define delay_ms(x)     __delay_cycles((MCLK_IN_HZ/1000*(x)))


void SystemClock_Init(void)

{

    PMM_setVCore(PMM_CORE_LEVEL_3);     //高主频工作需要较高的核心电压


    //XT1引脚复用

    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN4);

    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN5);


    //起振XT1

    UCS_turnOnLFXT1(UCS_XT1_DRIVE_3,UCS_XCAP_3);


    //XT2引脚复用

    GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN2);

    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P5, GPIO_PIN3);


    //起振XT2

    UCS_turnOnXT2(UCS_XT2_DRIVE_4MHZ_8MHZ);


    //XT2作为FLL参考时钟,先8分频,再50倍频 4MHz / 8 * 50 = 25MHz

    UCS_initClockSignal(UCS_FLLREF, UCS_XT2CLK_SELECT, UCS_CLOCK_DIVIDER_8);

    UCS_initFLLSettle(25000, 50);


    //XT1作为ACLK时钟源 = 32768Hz

    UCS_initClockSignal(UCS_ACLK, UCS_XT1CLK_SELECT, UCS_CLOCK_DIVIDER_1);


    //DCOCLK作为MCLK时钟源 = 25MHz

    UCS_initClockSignal(UCS_MCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);


    //DCOCLK作为SMCLK时钟源 = 25MHz

    UCS_initClockSignal(UCS_SMCLK, UCS_DCOCLK_SELECT, UCS_CLOCK_DIVIDER_1);


    //设置外部时钟源的频率,使得在调用UCS_getMCLK, UCS_getSMCLK 或 UCS_getACLK时可得到正确值

    UCS_setExternalClockSource(32768, 4000000);

}


#define TIMER_PERIOD 12500

void Timer_A_PWM_Init(void)

{

    Timer_A_outputPWMParam htim = {0};


    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2);


    htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;

    htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_40;

    htim.timerPeriod = TIMER_PERIOD - 1;

    htim.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;

    htim.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;

    htim.dutyCycle = TIMER_PERIOD / 2;

    Timer_A_outputPWM(TIMER_A0_BASE, &htim);

}



void KEY_S1_Init(void)

{

    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P2, GPIO_PIN1);

    //P2.1 interrupt enabled

    GPIO_enableInterrupt(GPIO_PORT_P2, GPIO_PIN1);  //使能中断

    //P2.1 Hi/Lo edge

    GPIO_selectInterruptEdge(GPIO_PORT_P2, GPIO_PIN1, GPIO_HIGH_TO_LOW_TRANSITION); //设置中断类型

    //P2.1 IFG cleared

    GPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN1);   //清除中断标志位

}


void KEY_S2_Init(void)

{

    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);

    //P2.1 interrupt enabled

    GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);  //使能中断

    //P2.1 Hi/Lo edge

    GPIO_selectInterruptEdge(GPIO_PORT_P1, GPIO_PIN1, GPIO_HIGH_TO_LOW_TRANSITION); //设置中断类型

    //P2.1 IFG cleared

    GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN1);   //清除中断标志位

}


int main(void)

{

    WDT_A_hold(WDT_A_BASE);

    SystemClock_Init();


    Timer_A_PWM_Init();


    KEY_S1_Init();

    KEY_S2_Init();


    //interrupts enabled

    __bis_SR_register(GIE);


    while(1)

    {


    }

}


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

//

//This is the PORT2_VECTOR interrupt vector service routine

//

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

#pragma vector=PORT2_VECTOR     // P2口中断源

__interrupt

void Port_2 (void)              // 声明一个中断服务程序,名为Port_2()

{

    if(GPIO_getInterruptStatus(GPIO_PORT_P2, GPIO_PIN1))

    {

        delay_ms(20);

        if(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1))

        {

            //P1.0 = toggle

            Timer_A_setCompareValue

            (

                    TIMER_A0_BASE,

                    TIMER_A_CAPTURECOMPARE_REGISTER_1,

                    Timer_A_getCaptureCompareCount(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_1) - TIMER_PERIOD / 10

            );

            while(!GPIO_getInputPinValue(GPIO_PORT_P2, GPIO_PIN1));

        }

        //P2.1 IFG cleared

        GPIO_clearInterrupt(GPIO_PORT_P2, GPIO_PIN1);

    }

}


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

//

//This is the PORT1_VECTOR interrupt vector service routine

//

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

#pragma vector=PORT1_VECTOR     // P2口中断源

__interrupt

void Port_1 (void)              // 声明一个中断服务程序,名为Port_1()

{

    if(GPIO_getInterruptStatus(GPIO_PORT_P1, GPIO_PIN1))

    {

        delay_ms(20);

        if(!GPIO_getInputPinValue(GPIO_PORT_P1, GPIO_PIN1))

        {

            //P1.0 = toggle

            Timer_A_setCompareValue

            (

                    TIMER_A0_BASE,

                    TIMER_A_CAPTURECOMPARE_REGISTER_1,

                    Timer_A_getCaptureCompareCount(TIMER_A0_BASE, TIMER_A_CAPTURECOMPARE_REGISTER_1) + TIMER_PERIOD / 10

            );

            while(!GPIO_getInputPinValue(GPIO_PORT_P1, GPIO_PIN1));

        }

        //P2.1 IFG cleared

        GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN1);

    }

}


效果

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.单定时器产生多路PWM信号

在这里插入图片描述

初始化函数

#define TIMER_PERIOD 12500

void Timer_A_PWM_Init(void)

{

//复用P1.2、P1.3、P1.4、P1.5输出

    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5);


    Timer_A_initUpModeParam htim = {0};

    htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;

    htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_40;

    htim.timerPeriod = TIMER_PERIOD - 1;

    htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;

    htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;

    htim.timerClear = TIMER_A_DO_CLEAR;

    htim.startTimer = true;

    Timer_A_initUpMode(TIMER_A0_BASE, &htim);



    Timer_A_initCompareModeParam htim_PWM = {0};

    htim_PWM.compareInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE;

    htim_PWM.compareOutputMode = TIMER_A_OUTPUTMODE_RESET_SET;


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.2);

    //Initialize compare mode to generate PWM1

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.4);

    //Initialize compare mode to generate PWM2

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_3;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.6);

    //Initialize compare mode to generate PWM3

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_4;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.8);

    //Initialize compare mode to generate PWM4

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);


}


依次将TA0.1、TA0.2、TA0.3、TA0.4初始化为占空比20%、40%、60%、80%,

时钟源为SMCLK = 25MHz

分频系数为40

装载值为12500 - 1

故所得PWM频率为25MHz/40/12500=50Hz


实验结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.对称PWM信号的产生

初始化程序

将上一个程稍作修改,即可产生对称PWM信号

其中compareOutputMode值的效果参考下图

在这里插入图片描述

时钟源为SMCLK = 25MHz

分频系数为40

装载值为12500 - 1

因采用增减计数模式

故所得PWM频率为25MHz/40/12500/2=25Hz


#define TIMER_PERIOD 12500

void Timer_A_PWM_Init(void)

{

    GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P1, GPIO_PIN2|GPIO_PIN3|GPIO_PIN4|GPIO_PIN5);


    Timer_A_initUpDownModeParam htim = {0};

    htim.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;

    htim.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_40;

    htim.timerPeriod = TIMER_PERIOD - 1;

    htim.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_DISABLE;

    htim.captureCompareInterruptEnable_CCR0_CCIE = TIMER_A_CCIE_CCR0_INTERRUPT_DISABLE;

    htim.timerClear = TIMER_A_DO_CLEAR;

    htim.startTimer = true;

    Timer_A_initUpDownMode(TIMER_A0_BASE, &htim);



    Timer_A_initCompareModeParam htim_PWM = {0};

    htim_PWM.compareInterruptEnable = TIMER_A_CAPTURECOMPARE_INTERRUPT_DISABLE;

    htim_PWM.compareOutputMode = TIMER_A_OUTPUTMODE_TOGGLE_RESET;


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.2);

    //Initialize compare mode to generate PWM1

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_2;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.4);

    //Initialize compare mode to generate PWM2

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_3;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.6);

    //Initialize compare mode to generate PWM3

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);


    htim_PWM.compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_4;

    htim_PWM.compareValue = (int)(TIMER_PERIOD * 0.8);

    //Initialize compare mode to generate PWM4

    Timer_A_initCompareMode(TIMER_A0_BASE, &htim_PWM);

}


实验结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • 短波AM发射器电路设计图

  • 带有短路保护系统的5V直流稳压电源电路图

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章