1. 程式人生 > >CC1310生成PWM波

CC1310生成PWM波

開發 void 操作 load 普通 () 中斷 時間 一個

工作中因為時間緊迫,我不得不拋開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波