CC1310生成PWM波
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CC1310生成PWM波相关的知识,希望对你有一定的参考价值。
工作中因为时间紧迫,我不得不抛开TI提供的TI-RTOS、sdk和xdctools等工具,采用ucos + 库函数的方式去开发。最开始一头扎进去,碰见的就PWM的生成。
PWM方面,TI自带封装好了PWM函数进行pwm的生成。
假如:我的需求是PWM的周期是2s,占空比50%,MCU主频是48MHz。于是我直接设置
params.periodUnits = PWM_PERIOD_US;
params.periodValue = pwmPeriod;
params.dutyUnits = PWM_DUTY_US;//PWM_DUTY_US;
params.dutyValue = 0;
但是问题来了,pwmPeriod的值最大不过340000,再往大设置,PWM_Open()就会返回NULL。我也尝试了对GPTimerA0进行分频,也不起任何作用。
后来用库函数开发,直接抛弃了drivers提供的驱动,使用driverlib。
在程序开始初始化时,对定时器进行分频。
PRCMGPTimerClockDivisionSet(PRCM_CLOCK_DIV_16);
以上函数将定时器时钟源主频从48MHz分为3MHz,之后好操作。
先贴程序
void GPTimerA0Prescaler(uint32_t frequence)
{
uint32_t ValuePWMDivFactor ;
uint32_t ValueLoadSetLower ;
uint32_t ValueLoadSetHigher ;
uint32_t ValueLoadMatchLower ;
uint32_t ValueLoadMatchHigher ;
uint32_t ValueTemp ;
IOCPortConfigureSet(LED_GREEN,IOC_PORT_MCU_PORT_EVENT0,IOC_IOMODE_NORMAL | IOC_IOPULL_UP|IOC_STRENGTH_MAX | IOC_INT_DISABLE);
GPIO_setOutputEnableDio(LED_GREEN,GPIO_OUTPUT_ENABLE);
GPIO_writeDio(LED_GREEN,0);
TimerDisable(GPT0_BASE, TIMER_A);
TimerConfigure(GPT0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);
TimerLevelControl(GPT0_BASE, TIMER_A, 0);
TimerPrescaleSet(GPT0_BASE, TIMER_A, 1) ;
TimerPrescaleMatchSet(GPT0_BASE, TIMER_A, 1);
ValuePWMDivFactor = frequence;
ValueTemp = ValuePWMDivFactor - 1 ;
ValueLoadSetLower = ValueTemp & 0xFFFF ;
ValueLoadSetHigher = ValueTemp & 0xFFFF0000 ;
ValueLoadSetHigher = ValueLoadSetHigher >> 16 ;
ValueTemp = ((ValuePWMDivFactor)/2) - 1 ; ;
ValueLoadMatchLower = ValueTemp & 0xFFFF ;
ValueLoadMatchHigher = ValueTemp & 0xFFFF0000 ;
ValueLoadMatchHigher = ValueLoadMatchHigher >> 16 ;
TimerPrescaleSet(GPT0_BASE, TIMER_A, ValueLoadSetHigher);
TimerPrescaleMatchSet(GPT0_BASE, TIMER_A, ValueLoadMatchHigher) ;
TimerLoadSet(GPT0_BASE, TIMER_A, ValueLoadSetLower);
TimerMatchSet(GPT0_BASE, TIMER_A,ValueLoadMatchLower);
TimerEnable(GPT0_BASE, TIMER_A);
}
这是一个让LED闪烁的函数,PWM控制LED,频率可以自己设置。
IOCPortConfigureSet(LED_GREEN,IOC_PORT_MCU_PORT_EVENT0, IOC_IOMODE_NORMAL | IOC_IOPULL_UP | IOC_STRENGTH_MAX | IOC_INT_DISABLE);
GPIO_setOutputEnableDio(LED_GREEN,GPIO_OUTPUT_ENABLE);
GPIO_writeDio(LED_GREEN,0);
这三个函数是LED口初始化。
第一句是配置挂上IOC_PORT_MCU_PORT_EVENT0,普通模式,上拉,最大驱动力,禁止中断;第二句设置输出使能;第三句是输出低电平。
接下来是初始化定时器
TimerDisable(GPT0_BASE, TIMER_A);
TimerConfigure(GPT0_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);
TimerLevelControl(GPT0_BASE, TIMER_A, 0);
TimerPrescaleSet(GPT0_BASE, TIMER_A, 1) ;
TimerPrescaleMatchSet(GPT0_BASE, TIMER_A, 1);
首先禁止定时器A模块,配置GPT0_BASE为两个半宽度定时器和定时器A的PWM模式;其次设置定时器A高电平有效;最后设置定时器A的分频值和分频匹配值为1。
第三是将设置的频率分为高字节和低字节两部分,匹配值设置为频率的一半,即50%的方波,也分成高字节和低字节两部分。
ValuePWMDivFactor = frequence;
ValueTemp = ValuePWMDivFactor - 1 ;
ValueLoadSetLower = ValueTemp & 0xFFFF ;
ValueLoadSetHigher = ValueTemp & 0xFFFF0000 ;
ValueLoadSetHigher = ValueLoadSetHigher >> 16 ;
ValueTemp = ((ValuePWMDivFactor)/2) - 1 ;
ValueLoadMatchLower = ValueTemp & 0xFFFF ;
ValueLoadMatchHigher = ValueTemp & 0xFFFF0000 ;
ValueLoadMatchHigher = ValueLoadMatchHigher >> 16 ;
第四就是要把这些值输入到定时器里去。
TimerPrescaleSet(GPT0_BASE, TIMER_A, ValueLoadSetHigher);
TimerPrescaleMatchSet(GPT0_BASE, TIMER_A, ValueLoadMatchHigher) ;
TimerLoadSet(GPT0_BASE, TIMER_A, ValueLoadSetLower);
TimerMatchSet(GPT0_BASE, TIMER_A,ValueLoadMatchLower);
TimerEnable(GPT0_BASE, TIMER_A);
将高字节的频率值放入定时器分频,将匹配值高字节放入分频匹配设置函数,将低字节的频率值设为定时器载入值,将匹配值低字节设置为定时器匹配载入值。
最后使能定时器。
如果想设置两个IO口相位差为180度的PWM波,则需要先配置一下第二个口
例如 IOCPortConfigureSet(LED_BLUE,IOC_PORT_MCU_PORT_EVENT2,IOC_IOMODE_NORMAL | IOC_IOPULL_UP | IOC_STRENGTH_MAX | IOC_INT_DISABLE);
GPIO_setOutputEnableDio(LED_BLUE,GPIO_OUTPUT_ENABLE);
GPIO_writeDio(LED_BLUE,0);
区别在于挂上的事件为IOC_PORT_MCU_PORT_EVENT2,为什么不是IOC_PORT_MCU_PORT_EVENT1,是因为IOC_PORT_MCU_PORT_EVENT1对应的是TIMER_B。
然后加上
TimerDisable(GPT1_BASE, TIMER_A);
TimerConfigure(GPT1_BASE, TIMER_CFG_SPLIT_PAIR|TIMER_CFG_A_PWM);
TimerLevelControl(GPT1_BASE, TIMER_A, 1);
区别在于TimerLevelControl(GPT1_BASE, TIMER_A, 0),要求低电平有效。
其余的按照GPT1_BASE配置之后的定时器设置,就可以实现两个PWM波相位差180度。
以上是关于CC1310生成PWM波的主要内容,如果未能解决你的问题,请参考以下文章