找回密码
 立即注册
查看: 68|回复: 1

【15系列】SYK-0806-A2S1 工业自动化控制之【07-定时器产生特定频率脉冲】

[复制链接]
  • 打卡等级:偶尔看看I
  • 打卡总天数:15
  • 最近打卡:2025-04-21 13:00:02

19

主题

9

回帖

217

积分

中级会员

积分
217
发表于 2025-4-17 09:40:17 | 显示全部楼层 |阅读模式
大家好,我是『芯知识学堂』的SingleYork,前一篇文章给大家介绍了“SYK-0806-A2S1 工业自动化控制之【06-输入信号延时控制输出】”,

这一篇中,笔者要给大家介绍如何使用定时器产生我们想要的频率。

首先,我们先来介绍一下本例要实现的功能:

X00由低电平变成高电平时,timer0的输出频率加1000Hz,当频率超过10000Hz时,频率切换为1000Hz;

X01由低电平变成高电平时,timer2的输出频率加1000Hz,当频率超过10000Hz时,频率切换为1000Hz;

在明确了目标后,我们便可以开始手动了。在动手之前,我们先来分析一下,要得到指定的频率,我们要如何配置定时器?

根据STC官方提供的手册我们可以知道:

  1. 输出时钟频率=T0溢出率/2
复制代码

T0如果工作在1T模式,那么

  1. 输出时钟频率=(SYSclk)/(65536-[RL_TH0,RL_TL0])/2
复制代码

T0如果工作在12T模式,那么

  1. 输出时钟频率=(SYSclk)/12/(65536-[RL_TH0,RL_TL0])/2
复制代码

由此可知,T0工作在1T模式的时候,定时器的重装值为:

  1. [RL_TH0,RL_TL0]=65536 -(SYSclk/输出时钟频率/2)
复制代码

T0工作在12T模式的时候,定时器的重装值为:

  1. [RL_TH0,RL_TL0]=65536 -(SYSclk/12/输出时钟频率/2)
复制代码

那么,我们就可以按照如下方式来配置定时器timer0了:

  1. void        Timer0_config(u32 TIM0_Fre)
  2. {
  3.         TIM_InitTypeDef                TIM_InitStructure;                                                //结构定义
  4.    
  5.         TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;            //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload,TIM_16BitAutoReloadNoMask
  6.         TIM_InitStructure.TIM_Polity    = PolityLow;                            //指定中断优先级(低到高) Polity_0,Polity_1,Polity_2,Polity_3
  7.         TIM_InitStructure.TIM_Interrupt = ENABLE;                                        //中断是否允许,   ENABLE或DISABLE
  8.         TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                        //指定时钟源,     TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
  9.         TIM_InitStructure.TIM_ClkOut    = DISABLE;                                    //是否输出高速脉冲, ENABLE或DISABLE
  10.         TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / TIM0_Fre/2);                //初值,
  11.         TIM_InitStructure.TIM_Run       = ENABLE;                                        //是否初始化后启动定时器, ENABLE或DISABLE
  12.         Timer_Inilize(Timer0,&TIM_InitStructure);                                        //初始化Timer0          Timer0,Timer1,Timer2,Timer3,Timer4
  13. }
复制代码

同理,定时器timer2也可以按照一样的方式来配置:

  1. void        Timer2_config(u32 TIM2_Fre)
  2. {
  3.         TIM_InitTypeDef                TIM_InitStructure;                                                //结构定义
  4.         TIM_InitStructure.TIM_Mode      = TIM_16BitAutoReload;            //指定工作模式,   TIM_16BitAutoReload,TIM_16Bit,TIM_8BitAutoReload
  5.         TIM_InitStructure.TIM_Polity    = PolityLow;                            //指定中断优先级, PolityHigh,PolityLow
  6.         TIM_InitStructure.TIM_Interrupt = ENABLE;                                    //中断是否允许,   ENABLE或DISABLE
  7.         TIM_InitStructure.TIM_ClkSource = TIM_CLOCK_1T;                            //指定时钟源, TIM_CLOCK_1T,TIM_CLOCK_12T,TIM_CLOCK_Ext
  8.         TIM_InitStructure.TIM_ClkOut    = DISABLE;                                    //是否输出高速脉冲, ENABLE或DISABLE
  9.         TIM_InitStructure.TIM_Value     = 65536UL - (MAIN_Fosc / TIM2_Fre/2);                //初值,
  10.         TIM_InitStructure.TIM_Run       = ENABLE;                                    //是否初始化后启动定时器, ENABLE或DISABLE
  11.         Timer_Inilize(Timer2,&TIM_InitStructure);                                    //初始化Timer1          Timer0,Timer1,Timer2,Timer3,Timer4
  12. }
复制代码

细心的小伙们可能会发现,笔者在这里将原来的void Timer_config(void)函数做了一下修改,改成了两个带参数的配置函数,这样就可以独立来配置timer0和timer2了。这两个函数同样的放在了bsp_timer.c文件中,同时,如果要在app.c文件中调用者两个函数的话,我们还需要在bsp_timer.h文件中对这两个函数进行声明:

  1. #ifndef        __BSP_TIMER_H
  2. #define        __BSP_TIMER_H
  3. #include        "config.h"
  4. #include        "timer.h"
  5. void        Timer0_config(u32 TIM0_Fre);
  6. void        Timer2_config(u32 TIM2_Fre);
  7. #endif
复制代码

接下来,我们在app.c文件中定义几个变量:

  1. bit F_X00_Down = 0;
  2. bit F_X01_Down = 0;
  3. u32 Timer0_Fre = 1000UL;//timer0频率初值
  4. u32 Timer2_Fre = 1000UL;//timer2频率初值
复制代码

在app_init()函数中调用timer0_config和timer2_config两个函数,对这两个定时器参数进行初始化:

  1. void app_init(void)
  2. {
  3.         GPIO_Config();      //GPIO配置
  4.    
  5.     Timer0_config(Timer0_Fre);     //定时器0配置
  6.     Timer2_config(Timer2_Fre);     //定时器2配置
  7.    
  8.     EA = 1;                            //开启总中断
  9. }
复制代码

同样的,主要的功能代码还是放在app_run()函数中实现:

  1. void app_run(void)
  2. {
  3.     /*****************************************
  4.    
  5.              X00由低电平变成高电平时
  6.             timer0的输出频率加 1000Hz
  7.        当频率超过10000Hz时,频率切换为1000Hz
  8.    
  9.     *****************************************/
  10.    
  11.     if(!F_X00_Down)
  12.     {
  13.         if(!X00)         //X00低电平
  14.         {
  15.             delay_ms(10);//10ms消抖
  16.             if(!X00)
  17.             {
  18.                 F_X00_Down = 1;//X00低电平标志置“1”
  19.             }
  20.         }
  21.     }
  22.     else
  23.     {
  24.         if(X00)         //X00高电平
  25.         {
  26.             delay_ms(10);//10ms消抖
  27.             if(X00)
  28.             {
  29.                 F_X00_Down = 0;//X00低电平标志清“0”
  30.                
  31.                 Timer0_Fre += 1000UL;
  32.                
  33.                 if(Timer0_Fre>10000UL)
  34.                     Timer0_Fre = 1000UL;
  35.                
  36.                 Timer0_config(Timer0_Fre);     //定时器0配置
  37.             }
  38.         }
  39.     }
  40.     /*****************************************
  41.    
  42.              X01由低电平变成高电平时
  43.             timer2的输出频率加 1000Hz
  44.        当频率超过10000Hz时,频率切换为1000Hz
  45.    
  46.     *****************************************/
  47.     if(!F_X01_Down)
  48.     {
  49.         if(!X01)         //X01低电平
  50.         {
  51.             delay_ms(10);//10ms消抖
  52.             if(!X01)
  53.             {
  54.                 F_X01_Down = 1;//X01低电平标志置“1”
  55.             }
  56.         }
  57.     }
  58.     else
  59.     {
  60.         if(X01)         //X01高电平
  61.         {
  62.             delay_ms(10);//10ms消抖
  63.             if(X01)
  64.             {
  65.                 F_X01_Down = 0;//X01低电平标志清“0”
  66.                
  67.                 Timer2_Fre += 1000UL;
  68.                
  69.                 if(Timer2_Fre>10000UL)
  70.                     Timer2_Fre = 1000UL;
  71.                
  72.                 Timer2_config(Timer2_Fre);     //定时器2配置
  73.             }
  74.         }
  75.     }
  76. }
复制代码

用于频率输出的GPIO分别放在timer0和timer2的中断函数中:

  1. /********************* Timer0中断函数************************/
  2. void timer0_int (void) interrupt TIMER0_VECTOR //频率可变
  3. {
  4.     Y00 = !Y00;//Y00状态翻转
  5. }
  6. /********************* Timer0中断函数************************/
  7. void timer2_int (void) interrupt TIMER2_VECTOR //频率可变
  8. {
  9.     Y01 = !Y01;//Y01状态翻转
  10. }
复制代码

程序编译完成后,下载到板子,就可以看到对应的输出频率了:

01.gif

02.gif

03.gif

上图中是用示波器简单的抓取了1K、2K和10K三种频率的输出效果。至此,代码大功告成!

好了,关于使用本节内容笔者就介绍到这里了,有疑问的小伙伴们可以给笔者留言或者直接参与评论,

下一节笔者将给大家介绍“如何利用定时器来控制步进电机”,详见“SYK-0806-A2S1 工业自动化控制之【08-步进电机启动和停止】”感谢大家的支持!


本章附件:

【STC15系列】SYK-0806-A2S1- 07-定时器产生特定频率脉冲.rar (67.13 KB, 下载次数: 1)




本帖被以下淘专辑推荐:

回复

使用道具 举报 送花

3

主题

1160

回帖

1031

积分

等待验证会员

积分
1031
发表于 2025-4-17 09:43:00 | 显示全部楼层
大家好,我是『芯知识学堂』的SingleYork,今天我们将继续探讨SYK-0806-A2S1在工业自动化控制中的应用,具体来说是如何使用定时器产生特定频率的脉冲信号。在前一篇文章中,我们介绍了输入信号延时控制输出的实现方法,本文将深入讲解定时器的配置与应用。

功能概述

在本例中,我们希望通过外部输入信号的变化来动态调整定时器的输出频率。具体功能如下:

1. 当X00由低电平变为高电平时,Timer0的输出频率增加1000Hz。若频率超过10000Hz,则频率重置为1000Hz。
2. 当X01由低电平变为高电平时,Timer2的输出频率增加1000Hz。若频率超过10000Hz,则频率重置为1000Hz。

定时器频率计算

要生成特定频率的脉冲信号,首先需要了解定时器的工作原理及其频率计算公式。根据官方手册,定时器的输出频率与系统时钟(SYSclk)及定时器的重装值密切相关。

定时器工作模式

定时器可以工作在1T模式或12T模式,不同模式下输出频率的计算公式如下:

1. 1T模式:
   \[
   \text{输出时钟频率} = \frac{\text{SYSclk}}{65536 - [RL\TH0, RL\TL0]} / 2
   \]
   其中,\([RL\TH0, RL\TL0]\)为定时器的重装值。

2. 12T模式:
   \[
   \text{输出时钟频率} = \frac{\text{SYSclk}}{12 \times (65536 - [RL\TH0, RL\TL0])} / 2
   \]

重装值计算

根据上述公式,我们可以推导出定时器重装值的计算公式:

1. 1T模式:
   \[
   [RL\TH0, RL\TL0] = 65536 - \left(\frac{\text{SYSclk}}{\text{输出时钟频率} \times 2}\right)
   \]

2. 12T模式:
   \[
   [RL\TH0, RL\TL0] = 65536 - \left(\frac{\text{SYSclk}}{12 \times \text{输出时钟频率} \times 2}\right)
   \]

定时器配置

基于上述公式,我们可以编写定时器的配置函数。以下是一个示例代码,展示了如何配置Timer0以生成特定频率的脉冲信号:
  1. c
  2. void Timer0configure(uint16t frequency) {
  3.     uint16t reloadvalue;
  4.     // 假设系统时钟为12MHz,定时器工作在1T模式
  5.     reloadvalue = 65536 - (12000000 / (frequency  2));
  6.     // 配置Timer0
  7.     TH0 = (reloadvalue >> 8) & 0xFF;  // 高字节
  8.     TL0 = reloadvalue & 0xFF;         // 低字节
  9.     // 设置定时器模式
  10.     TMOD &= 0xF0;  // 清除Timer0的模式位
  11.     TMOD |= 0x01;  // 设置为16位定时器模式
  12.     // 启动定时器
  13.     TR0 = 1;
  14. }
复制代码

频率调整逻辑

为了实现频率的动态调整,我们需要在外部输入信号变化时调用上述配置函数,并更新定时器的重装值。以下是一个简单的逻辑示例:
  1. c
  2. void handleinputs() {
  3.     static uint16t timer0frequency = 1000;
  4.     static uint16t timer2frequency = 1000;
  5.     if (X00risingedge()) {
  6.         timer0frequency += 1000;
  7.         if (timer0frequency > 10000) {
  8.             timer0frequency = 1000;
  9.         }
  10.         Timer0configure(timer0frequency);
  11.     }
  12.     if (X01risingedge()) {
  13.         timer2frequency += 1000;
  14.         if (timer2frequency > 10000) {
  15.             timer2frequency = 1000;
  16.         }
  17.         Timer2configure(timer2frequency);
  18.     }
  19. }
复制代码

总结

通过合理配置定时器,我们可以轻松生成特定频率的脉冲信号,并实现频率的动态调整。本文详细介绍了定时器频率的计算方法及配置步骤,并提供了示例代码供参考。希望这些内容能帮助大家更好地理解定时器在工业自动化控制中的应用。

在后续的文章中,我们将继续探讨更多关于SYK-0806-A2S1的应用案例,敬请期待!

——SingleYork

[本文内容由国芯人工智能辅助生成,仅供参考]
回复 支持 反对

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-2 22:11 , Processed in 0.344416 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表