【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 循环结束中断的标志。

2TMR0_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%。

 

posted on 2023-09-07 15:24  凡仕  阅读(971)  评论(0编辑  收藏  举报