【WCH蓝牙系列芯片】-基于CH582开发板—定时器基础使用(定时时间和PWM输出)
-------------------------------------------------------------------------------------------------------------------------------------
在WCH沁恒官方提供的CH583的EVT资源包中,我们可以找到TMR的工程,这是一个定时器功能的例程,其中包含了定时、计数功能、PWM输出功能、捕捉功能。这次先介绍两个功能:
第一就是采用定时器0,设定100ms定时器进行IO口电平翻转,
第二就是采用定时器3,输出占空比任意可调的PWM波形。
第一、采用定时器0,设定100ms定时器进行IO口电平翻转
在CH582芯片中,提供了4个26位的定时器,TMR0、TMR1、TMR2 和 TMR3。
最长的定时时间可达2^26个时钟周期。其中TMR1、TMR2都支持DMA功能,每个定时器都是完全独立的。
具体的参数可至WCH沁恒官方下载CH582的芯片数据手册。
在程序中,设置主频为60MHz,则最长的定时时间可达:(1/60M)*226= 0.0167uS*67108864≈1S
1 SetSysClock(CLK_SOURCE_PLL_60MHz); //主频60M 2 3 /* 配置串口调试 */ 4 DebugInit(); 5 PRINT("Start @ChipID=%02X\n", R8_CHIP_ID); 6 7 #if 1 /* 定时器0,设定100ms定时器进行IO口闪灯, PB15-LED */ 8 9 GPIOB_SetBits(GPIO_Pin_15); 10 GPIOB_ModeCfg(GPIO_Pin_15, GPIO_ModeOut_PP_5mA); //PB15推挽输出 11 12 //定时器0 13 TMR0_TimerInit(FREQ_SYS / 10); // 设置定时时间 100ms 14 15 TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END); // 开启中断 16 PFIC_EnableIRQ(TMR0_IRQn); //使能TMR0的中断,并指定中断号为 TMR0_IRQn 17 #endif
在程序中,首先配置PB15为推挽输出引脚,然后初始化定时器0,设置定时器的定时时间,
开启定时器0的中断,之后使能定时器0的中断,并指定中断号TMR0_IRQn。
1 void TMR0_TimerInit(uint32_t t) //初始化定时器Timer0 2 { 3 R32_TMR0_CNT_END = t; //计数值寄存器 4 R8_TMR0_CTRL_MOD = RB_TMR_ALL_CLEAR; //控制寄存器设置为全部清零,用于清除定时器的计数值、溢出标志和中断标志,以确保计时器从正确的起始点开始计数 5 R8_TMR0_CTRL_MOD = RB_TMR_COUNT_EN; //开启定时器的计数功能 6 }
在定时器0初始化函数中,包含这几个寄存器,
R32_TMR0_CNT_END----计数终值设置寄存器,设置变量为一个定时周期的时钟数,26位有效,最大值为67108863。
R8_TMR0_CTRL_MOD----模式设置寄存器
1、RB_TMR_ALL_CLEAR为定时器的 FIFO/计数器/中断标志清零
2、RB_TMR_COUNT_EN为定时器计数使能位
1 __INTERRUPT 2 __HIGH_CODE 3 void TMR0_IRQHandler(void) // TMR0 定时中断 4 { 5 if(TMR0_GetITFlag(TMR0_3_IT_CYC_END)) 6 { 7 TMR0_ClearITFlag(TMR0_3_IT_CYC_END); // 清除中断标志 8 GPIOB_InverseBits(GPIO_Pin_15); //电平翻转 9 } 10 }
1、在当TMR0 定时器的循环结束中断事件 TMR0_3_IT_CYC_END 触发时,进入中断处理函数。
TMR0_GetITFlag(TMR0_3_IT_CYC_END) 判断是否产生了 TMR0 循环结束中断。其中 TMR0_3_IT_CYC_END 是 TMR0 循环结束中断的标志。
2、TMR0_ClearITFlag(TMR0_3_IT_CYC_END) 清除 TMR0 循环结束中断标志,确保下一次中断可以被正确触发。
3、GPIOB_InverseBits(GPIO_Pin_15)将 GPIOB15实现引脚的翻转功能。
在这里,通过设置的数值计算出定时时间值,在定时器0初始化函数中TMR0_TimerInit(FREQ_SYS / 10);设置的数据是FREQ_SYS / 10,其中FREQ_SYS 宏定义值为 60000000,即系统的时钟频率。
定时时间为:(60000000/10)/60M = 0.1S = 100Ms
通过逻辑分析仪观察出信号,可以看一个脉冲宽度100mS,整个周期是200Ms,当脉冲每次时间到100ms,触发中断信号,IO电平翻转一次。
1 /* 定时器0,设定100ms定时器进行IO口闪灯, PB15-LED */ 2 void Timer0_timerInit(uint32_t t) 3 { 4 uint32_t time_data = t; 5 6 GPIOB_SetBits(GPIO_Pin_15); 7 GPIOB_ModeCfg(GPIO_Pin_15, GPIO_ModeOut_PP_5mA); //PB15推挽输出 8 9 //定时器0 10 TMR0_TimerInit(FREQ_SYS / (1000/time_data)); // time_data为设置定时时间值,设置多少时间就等于多少时间(单位ms) 11 // TMR0_TimerInit(FREQ_SYS / (time_data)); // time_data为设置定时时间值,时间等于1/time_data,(单位s) 12 13 TMR0_ITCfg(ENABLE, TMR0_3_IT_CYC_END); // 开启中断 14 PFIC_EnableIRQ(TMR0_IRQn); //使能TMR0的中断,并指定中断号为 TMR0_IRQn 15 16 }
在例程基础上更改一下程序,为当参数值t设置为多少,定时时间就是多少。单位为mS。
从更改的程序上可以看到,当t为设置为10,则利用逻辑分析仪查看波形,脉冲宽度为10mS,整个周期为20Ms。
第二就是采用定时器3,输出占空比任意可调的PWM波形。
1 GPIOB_ResetBits(GPIO_Pin_22); // 配置PWM口 PB22 2 GPIOB_ModeCfg(GPIO_Pin_22, GPIO_ModeOut_PP_5mA); 3 4 TMR3_PWMInit(High_Level, PWM_Times_1); 5 TMR3_PWMCycleCfg(60 * 100); // 周期 100us 最大67108864 6 TMR3_PWMActDataWidth(5000); // 占空比 50%, 修改占空比必须暂时关闭定时器 7 TMR3_PWMEnable(); 8 TMR3_Enable();
在程序中,采用定时器3配置PWM口,为PB22,初始化PB22为推挽输出。
在PWM初始化中,配置极性设置为高电平输出,PWM输出信号重复1次。利用TMR3_PWMCycleCfg配置输出波形周期:
这里是60*100 = 6000,6000/60000000 = 0.0001S = 100uS,这样频率就是1/0.0001S = 10000Hz = 10KHz
利用TMR3_PWMActDataWidth配置PWM的占空比,设置有效数据脉宽,这里设置参数为3000,3000/6000*100% = 50%
通过TMR3_PWMEnable使能TIMR3 PWM输出、TMR3_Enable开启定时器3。
通过逻辑分析仪观察出PWM波形周期为100uS,频率为10KHz,占空比为50%。
在例程基础上进行更改程序功能,设置两个变量,data_1设置为频率和data_2设置为占空比,
例如,设置data_1为1000, data_2为77,这样输出的PWM波形就是频率为1KHz,占空比为77%。
1 //data_1设置为频率 2 //data_2设置为占空比 3 /* 定时器1,PWM输出 */ //线性控制PWM 4 void Timer1_PWM_2(uint16_t data_1,uint16_t data_2) 5 { 6 GPIOA_ResetBits(GPIO_Pin_10); // 配置PWM口 PA10 7 GPIOA_ModeCfg(GPIO_Pin_10, GPIO_ModeOut_PP_5mA); //PA22推挽输出 8 9 TMR1_PWMInit(Low_Level, PWM_Times_1); //初始化定时器1的PWM,极性设置为低电平输出,PWM输出信号重复1次 10 11 // 设置频率为 10 kHz 12 uint16_t frequency = data_1; // Hz,frequency_data设置所需频率,若设置频率为 10 kHz,frequency_data为10000 13 int cycle = 600000 / frequency; // 计算周期,单位为微秒 14 15 // 设置占空比为 90% 16 int dutyCycle = data_2; // 百分比,dutyCycle_data设置所需占空比,若设置占空比为 90%,dutyCycle_data为90 17 int LowTime = cycle * dutyCycle; // 计算高电平时间,单位为微秒 18 19 TMR1_PWMCycleCfg(cycle * 100); // 配置周期,系统时钟直接做timer时钟,所以记录主频的次数就是1s,即60M为1秒 20 TMR1_PWMActDataWidth(LowTime); // 配置占空比,, 修改占空比必须暂时关闭定时器 21 TMR1_PWMEnable(); //启用TIMR1的PWM功能 22 TMR1_Enable(); //打开定时器1,开始计数 23 }
通过逻辑分析仪可以看出PWM波形的频率为1KHz,占空比为77%。