HC32F460 PWM控制

简介

PWM 是 Pulse Width Modulation 的缩写,它的中文名字是脉冲宽度调制,一种说法是它利用微处理器的数字输出来对模拟电路进行控制的一种有效的技术,其实就是使用数字信号达到一个模拟信号的效果。

本文使用输出比较模拟PWN输出。

具体实现

#include "hc32_ddl.h"


/* pwm Port/Pin definition */
#define KEY2_TRIGGER_EVENT              (EVT_PORT_EIRQ3)

/* TIMERA unit and clock definition */
#define TIMERA_UNIT1                    (M4_TMRA3)
#define TIMERA_UNIT1_CLOCK              (PWC_FCG2_PERIPH_TIMA3)
#define TIMERA_UNIT1_OVERFLOW_INT       (INT_TMRA3_OVF)

/* TIMERA channel 1 Port/Pin definition */
#define TIMERA_UNIT1_CH1                (TimeraCh1)
#define TIMERA_UNIT1_CH1_PORT           (PortC)
#define TIMERA_UNIT1_CH1_PIN            (Pin06)
#define TIMERA_UNIT1_CH1_FUNC           (Func_Tima0)

#define TIMERA_COUNT_OVERFLOW           (1953)


static void Port_Init(void)
{
    uint8_t i;
    stc_port_init_t stcPortInit;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcPortInit);
    stcPortInit.enPinMode = Pin_Mode_Out;
		stcPortInit.enPullUp = Disable;
		stcPortInit.enExInt = Enable;
	
    /* Initialize servo motor pin */
		PORT_Init(PortC, Pin06, &stcPortInit);
		PORT_ResetBits(PortC, Pin06);
}

static void TimeraUnit1_IrqCallback(void)
{
    TIMERA_ClearFlag(TIMERA_UNIT1, TimeraFlagOverflow);
}

static void Tim_Config(void)
{
    stc_timera_base_init_t stcTimeraInit;
    stc_timera_compare_init_t stcTimerCompareInit;
    stc_irq_regi_conf_t stcIrqRegiConf;
    stc_timera_hw_startup_config_t stcTimeraHwConfig;

    /* configuration structure initialization */
    MEM_ZERO_STRUCT(stcTimeraInit);
    MEM_ZERO_STRUCT(stcIrqRegiConf);
    MEM_ZERO_STRUCT(stcTimerCompareInit);
    MEM_ZERO_STRUCT(stcTimeraHwConfig);

    /* Configuration peripheral clock */
    PWC_Fcg2PeriphClockCmd(TIMERA_UNIT1_CLOCK, Enable);
    /* Configuration TIMERA compare pin */
    PORT_SetFunc(TIMERA_UNIT1_CH1_PORT, TIMERA_UNIT1_CH1_PIN, TIMERA_UNIT1_CH1_FUNC, Disable);

    /* Configuration timera unit 1 base structure */
    stcTimeraInit.enClkDiv = TimeraPclkDiv512;  //100 000 000 /512    
    stcTimeraInit.enCntMode = TimeraCountModeTriangularWave;


    stcTimeraInit.enCntDir = TimeraCountDirUp;
    stcTimeraInit.enSyncStartupEn = Disable;
		stcTimeraInit.u16PeriodVal = TIMERA_COUNT_OVERFLOW; // //freq: 50Hz -> 100 000 000 /512/50HZ/2 = 1953(period val)
    TIMERA_BaseInit(TIMERA_UNIT1, &stcTimeraInit);
		
    /* Configuration timera unit 1 compare structure */
    stcTimerCompareInit.u16CompareVal = stcTimeraInit.u16PeriodVal/2;   // 50%的占空比
		stcTimerCompareInit.enStartCountOutput = TimeraCountStartOutputHigh;
		stcTimerCompareInit.enStopCountOutput = TimeraCountStopOutputHigh;
    stcTimerCompareInit.enCompareMatchOutput = TimeraCompareMatchOutputReverse;
    stcTimerCompareInit.enPeriodMatchOutput = TimeraPeriodMatchOutputHigh;
    stcTimerCompareInit.enSpecifyOutput = TimeraSpecifyOutputInvalid;
					
    stcTimerCompareInit.enCacheEn = Disable;
    stcTimerCompareInit.enTriangularTroughTransEn = Disable;
    stcTimerCompareInit.enTriangularCrestTransEn = Disable;
    stcTimerCompareInit.u16CompareCacheVal = stcTimerCompareInit.u16CompareVal;
    /* Configure Channel 1 */
    TIMERA_CompareInit(TIMERA_UNIT1, TIMERA_UNIT1_CH1, &stcTimerCompareInit);
    TIMERA_CompareCmd(TIMERA_UNIT1, TIMERA_UNIT1_CH1, Enable);

    /* Enable period count interrupt */
    TIMERA_IrqCmd(TIMERA_UNIT1, TimeraIrqOverflow, Enable);
    /* Interrupt of timera unit 1 */
    stcIrqRegiConf.enIntSrc = TIMERA_UNIT1_OVERFLOW_INT;
    stcIrqRegiConf.enIRQn = IRQ_INDEX_INT_TIMA_CH1;
    stcIrqRegiConf.pfnCallback = &TimeraUnit1_IrqCallback;
    enIrqRegistration(&stcIrqRegiConf);
    NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
    NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
    NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
		

    TIMERA_Cmd(TIMERA_UNIT1,Enable);	
    TIMERA_SetCompareValue( TIMERA_UNIT1,TIMERA_UNIT1_CH1, TIMERA_COUNT_OVERFLOW*0.1);
    TIMERA_SpecifyOutputSta(TIMERA_UNIT1,TIMERA_UNIT1_CH1,TimeraSpecifyOutputInvalid);	
}

void set_duty_cycle(uint16_t duty)
{
		if(duty == 0)
		{
        TIMERA_SpecifyOutputSta(TIMERA_UNIT1, TIMERA_UNIT1_CH1, TimeraSpecifyOutputLow);
				TIMERA_Cmd(TIMERA_UNIT1,Enable);
		}
    else if(duty >= TIMERA_COUNT_OVERFLOW)
		{
        TIMERA_SpecifyOutputSta(TIMERA_UNIT1, TIMERA_UNIT1_CH1, TimeraSpecifyOutputHigh);
				TIMERA_Cmd(TIMERA_UNIT1,Enable);
		}
    else
		{
				stc_timera_compare_init_t stcTimerCompareInit;
				MEM_ZERO_STRUCT(stcTimerCompareInit);
			
				 /* Configuration timera unit 1 compare structure */
				stcTimerCompareInit.u16CompareVal = duty;   //500		
				stcTimerCompareInit.enStartCountOutput = TimeraCountStartOutputHigh;
				stcTimerCompareInit.enStopCountOutput = TimeraCountStopOutputHigh;
			
				stcTimerCompareInit.enCompareMatchOutput = TimeraCompareMatchOutputReverse;
				stcTimerCompareInit.enPeriodMatchOutput = TimeraPeriodMatchOutputHigh;
				stcTimerCompareInit.enSpecifyOutput = TimeraSpecifyOutputInvalid;
				
				stcTimerCompareInit.enCacheEn = Disable;
				stcTimerCompareInit.enTriangularTroughTransEn = Disable;
				stcTimerCompareInit.enTriangularCrestTransEn = Disable;
				stcTimerCompareInit.u16CompareCacheVal = stcTimerCompareInit.u16CompareVal;
				/* Configure Channel 1 */
				TIMERA_CompareInit(TIMERA_UNIT1, TIMERA_UNIT1_CH1, &stcTimerCompareInit);
				TIMERA_CompareCmd(TIMERA_UNIT1, TIMERA_UNIT1_CH1, Enable);
			  TIMERA_Cmd(TIMERA_UNIT1,Enable);
		}
		
}

void set_steering_gear_dutyfactor(uint16_t dutyfactor)
{

	/* 对超过范围的占空比进行边界处理 */
	dutyfactor = 0.5/20.0*TIMERA_COUNT_OVERFLOW > dutyfactor ? 0.5/20.0*TIMERA_COUNT_OVERFLOW : dutyfactor;
	dutyfactor = 2.5/20.0*TIMERA_COUNT_OVERFLOW < dutyfactor ? 2.5/20.0*TIMERA_COUNT_OVERFLOW : dutyfactor;

  set_duty_cycle(dutyfactor);
}

void set_angle(uint16_t angle_temp)
{
  angle_temp = (0.5 + angle_temp / 180.0 * (2.5 - 0.5)) / 20.0 * TIMERA_COUNT_OVERFLOW;    // 计算角度对应的占空比

  set_steering_gear_dutyfactor(angle_temp);    // 设置占空比
}

void pwm_init()
{
		Port_Init();
		Tim_Config();	
}
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

路过的小熊~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值