大家好,我是『芯知识学堂』的SingleYork,前一篇文章给大家介绍了“SYK-0806-A2S1 工业自动化控制之【06-输入信号延时控制输出】”,
这一篇中,笔者要给大家介绍如何使用定时器产生我们想要的频率。
首先,我们先来介绍一下本例要实现的功能:
X00由低电平变成高电平时,timer0的输出频率加1000Hz,当频率超过10000Hz时,频率切换为1000Hz;
X01由低电平变成高电平时,timer2的输出频率加1000Hz,当频率超过10000Hz时,频率切换为1000Hz;
在明确了目标后,我们便可以开始手动了。在动手之前,我们先来分析一下,要得到指定的频率,我们要如何配置定时器?
根据STC官方提供的手册我们可以知道:
复制代码
T0如果工作在1T模式,那么
- 输出时钟频率=(SYSclk)/(65536-[RL_TH0,RL_TL0])/2
复制代码
T0如果工作在12T模式,那么
- 输出时钟频率=(SYSclk)/12/(65536-[RL_TH0,RL_TL0])/2
复制代码
由此可知,T0工作在1T模式的时候,定时器的重装值为:
- [RL_TH0,RL_TL0]=65536 -(SYSclk/输出时钟频率/2)
复制代码
T0工作在12T模式的时候,定时器的重装值为:
- [RL_TH0,RL_TL0]=65536 -(SYSclk/12/输出时钟频率/2)
复制代码
那么,我们就可以按照如下方式来配置定时器timer0了:
- void Timer0_config(u32 TIM0_Fre)
- {
- TIM_InitTypeDef TIM_InitStructure; //结构定义
-
- TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
- TIM_InitStructure.TIM_Polity = PolityLow; //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
- TIM_InitStructure.TIM_Interrupt = ENABLE; //中断是否允许, ENABLE或DISABLE
- TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
- TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
- TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / TIM0_Fre/2); //初值,
- TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
- Timer_Inilize(Timer0,&TIM_InitStructure); //初始化Timer0 Timer0,Timer1,Timer2,Timer3,Timer4
- }
复制代码
同理,定时器timer2也可以按照一样的方式来配置:
- void Timer2_config(u32 TIM2_Fre)
- {
- TIM_InitTypeDef TIM_InitStructure; //结构定义
-
- TIM_InitStructure.TIM_Mode = TIM_16BitAutoReload; //指定工作模式, TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload
- TIM_InitStructure.TIM_Polity = PolityLow; //指定中断优先级, PolityHigh,PolityLow
- TIM_InitStructure.TIM_Interrupt = ENABLE; //中断是否允许, ENABLE或DISABLE
- TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T; //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
- TIM_InitStructure.TIM_ClkOut = DISABLE; //是否输出高速脉冲, ENABLE或DISABLE
- TIM_InitStructure.TIM_Value = 65536UL - (MAIN_Fosc / TIM2_Fre/2); //初值,
- TIM_InitStructure.TIM_Run = ENABLE; //是否初始化后启动定时器, ENABLE或DISABLE
- Timer_Inilize(Timer2,&TIM_InitStructure); //初始化Timer1 Timer0,Timer1,Timer2,Timer3,Timer4
- }
复制代码
细心的小伙们可能会发现,笔者在这里将原来的void Timer_config(void)函数做了一下修改,改成了两个带参数的配置函数,这样就可以独立来配置timer0和timer2了。这两个函数同样的放在了bsp_timer.c文件中,同时,如果要在app.c文件中调用者两个函数的话,我们还需要在bsp_timer.h文件中对这两个函数进行声明:
- #ifndef __BSP_TIMER_H
- #define __BSP_TIMER_H
-
- #include "config.h"
- #include "timer.h"
-
- void Timer0_config(u32 TIM0_Fre);
- void Timer2_config(u32 TIM2_Fre);
-
- #endif
复制代码
接下来,我们在app.c文件中定义几个变量:
- bit F_X00_Down = 0;
- bit F_X01_Down = 0;
-
- u32 Timer0_Fre = 1000UL;//timer0频率初值
- u32 Timer2_Fre = 1000UL;//timer2频率初值
复制代码
在app_init()函数中调用timer0_config和timer2_config两个函数,对这两个定时器参数进行初始化:
- void app_init(void)
- {
- GPIO_Config(); //GPIO配置
-
- Timer0_config(Timer0_Fre); //定时器0配置
- Timer2_config(Timer2_Fre); //定时器2配置
-
- EA = 1; //开启总中断
- }
复制代码
同样的,主要的功能代码还是放在app_run()函数中实现:
- void app_run(void)
- {
- /*****************************************
-
- X00由低电平变成高电平时
- timer0的输出频率加 1000Hz
- 当频率超过10000Hz时,频率切换为1000Hz
-
- *****************************************/
-
- if(!F_X00_Down)
- {
- if(!X00) //X00低电平
- {
- delay_ms(10);//10ms消抖
- if(!X00)
- {
- F_X00_Down = 1;//X00低电平标志置“1”
- }
- }
- }
- else
- {
- if(X00) //X00高电平
- {
- delay_ms(10);//10ms消抖
- if(X00)
- {
- F_X00_Down = 0;//X00低电平标志清“0”
-
- Timer0_Fre += 1000UL;
-
- if(Timer0_Fre>10000UL)
- Timer0_Fre = 1000UL;
-
- Timer0_config(Timer0_Fre); //定时器0配置
- }
- }
- }
- /*****************************************
-
- X01由低电平变成高电平时
- timer2的输出频率加 1000Hz
- 当频率超过10000Hz时,频率切换为1000Hz
-
- *****************************************/
- if(!F_X01_Down)
- {
- if(!X01) //X01低电平
- {
- delay_ms(10);//10ms消抖
- if(!X01)
- {
- F_X01_Down = 1;//X01低电平标志置“1”
- }
- }
- }
- else
- {
- if(X01) //X01高电平
- {
- delay_ms(10);//10ms消抖
- if(X01)
- {
- F_X01_Down = 0;//X01低电平标志清“0”
-
- Timer2_Fre += 1000UL;
-
- if(Timer2_Fre>10000UL)
- Timer2_Fre = 1000UL;
-
- Timer2_config(Timer2_Fre); //定时器2配置
- }
- }
- }
- }
复制代码
用于频率输出的GPIO分别放在timer0和timer2的中断函数中:
- /********************* Timer0中断函数************************/
- void timer0_int (void) interrupt TIMER0_VECTOR //频率可变
- {
- Y00 = !Y00;//Y00状态翻转
- }
-
- /********************* Timer0中断函数************************/
- void timer2_int (void) interrupt TIMER2_VECTOR //频率可变
- {
- Y01 = !Y01;//Y01状态翻转
- }
复制代码
程序编译完成后,下载到板子,就可以看到对应的输出频率了:
上图中是用示波器简单的抓取了1K、2K和10K三种频率的输出效果。至此,代码大功告成!
好了,关于使用本节内容笔者就介绍到这里了,有疑问的小伙伴们可以给笔者留言或者直接参与评论,
下一节笔者将给大家介绍“如何利用定时器来控制步进电机”,详见“SYK-0806-A2S1 工业自动化控制之【08-步进电机启动和停止】”感谢大家的支持!
本章附件:
【STC15系列】SYK-0806-A2S1- 07-定时器产生特定频率脉冲.rar
(67.13 KB, 下载次数: 1)
|