准备电赛——CCSMSP430F5529——定时器A产生PWM

一个定时器产生一个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%

按钮按下为0

//******************************************************************************
//
//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);
    }
}

 

 

 

 一个定时器产生多个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

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
平衡小车的PWM模式GPIO口设置主要包括以下方面: 1. 选择PWM定时器 首先需要确定使用哪一个定时器来控制PWM输出。在STM32系列的单片机中,一般有多个定时器可供选择,每个定时器都有多个PWM输出通道。需要根据实际需要选择合适的定时器和通道。 2. 配置GPIO口 在选择好定时器和通道后,需要根据定时器通道的映射关系,配置相应的GPIO口。这些GPIO口一般称为复用功能的GPIO口,可以通过设置GPIO的模式、速度、复用功能等参数来实现PWM输出。以下是代码示例: ```c // 定义GPIO口结构体 GPIO_InitTypeDef GPIO_InitStruct; // 配置GPIO口为复用功能模式 GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); ``` 以上代码中,`GPIO_PIN_8`表示要配置的GPIO口编号,`GPIO_MODE_AF_PP`表示要将GPIO口设置为复用功能模式并开启推挽输出,`GPIO_NOPULL`表示不开启上下拉电阻,`GPIO_SPEED_FREQ_HIGH`表示GPIO口输出速度为高速,`GPIO_AF1_TIM1`表示将GPIO口复用为定时器1的通道1输出。这里的`HAL_GPIO_Init`函数用于配置GPIO口参数并使能该GPIO口。 3. 配置PWM输出通道 除了配置GPIO口之外,还需要对PWM输出通道进行配置,设置PWM输出的占空比、频率等参数。以下是代码示例: ```c // 定义PWM输出通道结构体 TIM_OC_InitTypeDef sConfigOC; // 配置PWM输出通道 sConfigOC.OCMode = TIM_OCMODE_PWM1; sConfigOC.Pulse = 0; sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim, TIM_CHANNEL_1); ``` 以上代码中,`TIM_OCMODE_PWM1`表示PWM输出模式为PWM1,`TIM_CHANNEL_1`表示要配置的PWM输出通道为通道1,`sConfigOC.Pulse`表示PWM输出的占空比,这里设置为0,`TIM_OCPOLARITY_HIGH`表示输出极性为高电平,`TIM_OCFAST_DISABLE`表示快速输出模式关闭。最后的`HAL_TIM_PWM_ConfigChannel`函数用于配置PWM输出通道参数,`HAL_TIM_PWM_Start`函数用于开启PWM输出。 以上是平衡小车PWM模式GPIO口设置的主要内容,需要根据具体情况进行修改和完善。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值