本帖最后由 noctor 于 2018-9-19 11:36 编辑
上回我们说到了MG32F02A的TIM00的使用来进行精准延时1ms的实验,初步的使用了一下我们的定时器,那么我们这次就来学习一下如何使用PWM吧。
上次的TIM精准延时1ms实验帖子链接:https://bbs.21ic.com/icview-2554558-1-1.html
首先,我们的EV板上面是有LED的,那么最直观的观察PWM的方式除了示波器就是看LED灯光亮度了吧,看了一下,我们EV板上的LED是接在PE13、PE14上的,那么看看PE13或者PE14上面是否有PWM的输出呢?
查了一下,PE14和PE15都是有TIM的OC的,那么就可以直接使用了。
对了,前段时间在玩这块板子的时候出现了一些问题,我使用Configure Wizard初始化完成后依然不能输出PWM,查了无数次代码后依旧找不到问题,初始化设置也检查了,自认为没有设置错误,但是PWM死活出不来,后来就尝试自己进行初始化,不使用Configure Wizard,结果PWM就出来了。。所以我现在还是推荐如果要使用的外设比较多,设置比较复杂,那还是自己进行初始化吧,不要使用Configure Wizard了,因此,这次我的代码就不放上使用了Wizard的代码,只放手动初始化的代码,如果嫌麻烦就直接把我CSC_init()和GPIO初始化的内容复制保存起来,以后要用的时候直接贴上去,完了修改你要的参数就好。
程序如下:
#include "MG32x02z_DRV.H"
#include <stdio.h>
typedef uint8_t u8;
typedef uint16_t u16;
typedef uint32_t u32;
typedef uint64_t u64;
//if user wants to set PWM period 1ms and CK_TM00_PR is 12MHz.
//The Total clocks is 12M*1ms = 12000.
//User can set "clock prescaler"=100 and "pulse width"=120 .
#define TM26_PrescalerCounter_Range 120
#define TM26_MainCounter_Range 100
void Sample_TM26_PWM(void)
{
TM_TimeBaseInitTypeDef TM_TimeBase_InitStruct;
// The period = (prescaler*main counter)/12MHz (CK_TM26_PR=12MHz) (s)
// User can update duty cycle by replace CCxB register.
// make sure :
//===Set CSC init====
//MG32x02z_CSC_Init.h(Configuration Wizard)
//Select CK_HS source = CK_IHRCO
//Select IHRCO = 12M
//Select CK_MAIN Source = CK_HS
//Configure PLL->Select APB Prescaler = CK_MAIN/1
//Configure Peripheral On Mode Clock->TM36 = Enable
TM_DeInit(TM26);
// ----------------------------------------------------
// 1.TimeBase structure initial
TM_TimeBaseStruct_Init(&TM_TimeBase_InitStruct);
// modify parameter
TM_TimeBase_InitStruct.TM_MainClockDirection =TM_UpCount;
TM_TimeBase_InitStruct.TM_Period = TM26_MainCounter_Range-1;
TM_TimeBase_InitStruct.TM_Prescaler = TM26_PrescalerCounter_Range-1;
TM_TimeBase_InitStruct.TM_CounterMode = Cascade;
TM_TimeBase_Init(TM26, &TM_TimeBase_InitStruct);
// ----------------------------------------------------
// 2.config TM26 channel 1 function
TM_CH1Function_Config(TM26, TM_16bitPWM);
// ----------------------------------------------------
// 3.Enable TM26 channel 1 Output (just output TM26_OC11)
TM_OC11Output_Cmd(TM26,ENABLE);
TM_InverseOC1z_Cmd(TM26, DISABLE);
TM_OC1zOutputState_Init(TM26, CLR);
// ----------------------------------------------------
// 3.Enable TM26 channel 1 Output (just output TM26_OC12)
TM_OC12Output_Cmd(TM26,ENABLE);
TM_InverseOC1z_Cmd(TM26, DISABLE);
TM_OC1zOutputState_Init(TM26, CLR);
// ----------------------------------------------------
// 4.set match point (Duty cycle %) for PWM channel0.Less value of CCnA/CCnB,more lighten (1~100(decided by MainCounter_Range you set))
TM_SetCC1A(TM26,90);
TM_SetCC1B(TM26,90); // reload value when overflow
// ----------------------------------------------------
// 9.select Edge Align
TM_AlignmentMode_Select(TM26, TM_EdgeAlign);
// ----------------------------------------------------
// 10.clear flag
TM_ClearFlag(TM26, TMx_CF0A | TMx_CF1A | TMx_CF2A);
// ----------------------------------------------------
// 11.Timer enable
TM_Timer_Cmd(TM26,ENABLE);
}
void CSC_Init (void)
{
UnProtectModuleReg(MEMprotect); // Setting flash wait state
MEM_SetFlashWaitState(MEM_FWAIT_ONE); // 50MHz> Sysclk >=25MHz
ProtectModuleReg(MEMprotect);
UnProtectModuleReg(CSCprotect);
CSC_CK_APB_Divider_Select(APB_DIV_1); // Modify CK_APB divider APB=CK_MAIN/1
CSC_CK_AHB_Divider_Select(AHB_DIV_1); // Modify CK_AHB divider AHB=APB/1
/* CK_HS selection */
CSC_IHRCO_Select(IHRCO_12MHz); // IHRCO Sel 12MHz
CSC_IHRCO_Cmd(ENABLE);
while(CSC_GetSingleFlagStatus(CSC_IHRCOF) == DRV_Normal);
CSC_ClearFlag(CSC_IHRCOF);
CSC_CK_HS_Select(HS_CK_IHRCO); // CK_HS select IHRCO
/* CK_MAIN */
CSC_CK_MAIN_Select(MAIN_CK_HS);
/* Configure ICKO function */
/* Configure peripheral clock */
CSC_PeriphOnModeClock_Config(CSC_ON_PortE,ENABLE); // Enable Port E clock
CSC_PeriphProcessClockSource_Config(CSC_TM26_CKS, CK_APB);
CSC_PeriphOnModeClock_Config(CSC_ON_TM26, ENABLE); // Enable TIM26 module clock
ProtectModuleReg(CSCprotect);
}
int main()
{
PIN_InitTypeDef PINX_InitStruct;
CSC_Init();
//==Set GPIO init
PINX_InitStruct.PINX_Mode = PINX_Mode_PushPull_O; // Pin select Push Pull mode
PINX_InitStruct.PINX_PUResistant = PINX_PUResistant_Enable; // Enable pull up resistor
PINX_InitStruct.PINX_Speed = PINX_Speed_Low;
PINX_InitStruct.PINX_OUTDrive = PINX_OUTDrive_Level0; // Pin output driver full strength.
PINX_InitStruct.PINX_FilterDivider = PINX_FilterDivider_Bypass; // Pin input deglitch filter clock divider bypass
PINX_InitStruct.PINX_Inverse = PINX_Inverse_Disable; // Pin input data not inverse
PINX_InitStruct.PINX_Alternate_Function = 7; // Pin AFS = TIM26 OC
GPIO_PinMode_Config(PINE(13),&PINX_InitStruct); // Set PE13 to TIM26 OC11
GPIO_PinMode_Config(PINE(14),&PINX_InitStruct); // Set PE14 to TIM26 OC12
Sample_TM26_PWM();
while(1);
}
OK,这样PWM就出来了,要调节占空比就调节TM_SetCC1A(TM26,x)和TM_SetCC1B(TM26,x)的x值,其中保持A、B的值均一致就行。一样的原理,其他的TIM20、36都是可以输出PWM的,直接自己改就好了。
|