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波