SingleYork 发表于 2025-4-17 09:40:17

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

大家好,我是『芯知识学堂』的SingleYork,前一篇文章给大家介绍了“SYK-0806-A2S1 工业自动化控制之【06-输入信号延时控制输出】”,

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

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

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

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

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

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

输出时钟频率=T0溢出率/2
T0如果工作在1T模式,那么

输出时钟频率=(SYSclk)/(65536-)/2
T0如果工作在12T模式,那么

输出时钟频率=(SYSclk)/12/(65536-)/2
由此可知,T0工作在1T模式的时候,定时器的重装值为:

=65536 -(SYSclk/输出时钟频率/2)
T0工作在12T模式的时候,定时器的重装值为:

=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-步进电机启动和停止】”感谢大家的支持!


本章附件:






国芯人工智能 发表于 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 - } / 2
   \]
   其中,\(\)为定时器的重装值。

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

重装值计算

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

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

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

定时器配置

基于上述公式,我们可以编写定时器的配置函数。以下是一个示例代码,展示了如何配置Timer0以生成特定频率的脉冲信号:

c
void Timer0configure(uint16t frequency) {
    uint16t reloadvalue;

    // 假设系统时钟为12MHz,定时器工作在1T模式
    reloadvalue = 65536 - (12000000 / (frequency2));

    // 配置Timer0
    TH0 = (reloadvalue >> 8) & 0xFF;// 高字节
    TL0 = reloadvalue & 0xFF;         // 低字节

    // 设置定时器模式
    TMOD &= 0xF0;// 清除Timer0的模式位
    TMOD |= 0x01;// 设置为16位定时器模式

    // 启动定时器
    TR0 = 1;
}

频率调整逻辑

为了实现频率的动态调整,我们需要在外部输入信号变化时调用上述配置函数,并更新定时器的重装值。以下是一个简单的逻辑示例:

c
void handleinputs() {
    static uint16t timer0frequency = 1000;
    static uint16t timer2frequency = 1000;

    if (X00risingedge()) {
      timer0frequency += 1000;
      if (timer0frequency > 10000) {
            timer0frequency = 1000;
      }
      Timer0configure(timer0frequency);
    }

    if (X01risingedge()) {
      timer2frequency += 1000;
      if (timer2frequency > 10000) {
            timer2frequency = 1000;
      }
      Timer2configure(timer2frequency);
    }
}

总结

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

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

——SingleYork

[本文内容由国芯人工智能辅助生成,仅供参考]
页: [1]
查看完整版本: 【15系列】SYK-0806-A2S1 工业自动化控制之【07-定时器产生特定频率脉冲】