SingleYork 发表于 2025-4-17 08:39:02

【15系列】SYK-0806-A2S1 工业自动化控制之【03-延时函数演示流水灯】

大家好,我是『芯知识学堂』的SingleYork,前一篇文章给大家介绍了“【15系列】SYK-0806-A2S1 工业自动化控制之【02-硬件分析&外设接线图】”,

相信大家对我们的这款板子已不再陌生,那么今天开始,笔者就要来给大家介绍如何使用STC15系列库函数来开发这款工控板,

这一篇文章,笔者以点灯为例,来教大家如何对SYK-0806-A2S1这款控制板进行输出控制,那么我们首先来看下板子的输出口的IO引脚分布:



从板子的硬件原理图上我们可知,SYK-0806-A2S1这款工控板的6个输出口Y00-Y05所使用的GPIO口分别是P32-P27口。

另外,在上一篇文章中笔者也跟大家介绍了,SYK-0806-A2S1这款工控板的输出口需要配置成“推挽输出”才能正确驱动MOS管,

因此我们在配置GPIO口模式的时候,需要注意这点。由于我们这款板子并不是用来教单片机基础的,

所以,有关单片机相关的操作笔者也就不作详细介绍了,笔者主要是针对这款开发板的应用来介绍!

有关单片机基础的相关知识,还请读者自行找资料学习!

首先,我们来看下这个点灯工程的构成:



笔者将这个点灯工程的软件部分分成了是4个Group,他们分别是:SYSTEM、USER、BSP和APP,其中:

SYSTEM 组中主要是存放了STC15系列库文件,这个项目中只用到了两个库,即:delay库和gpio库;

USER 里面存放了一个main.c文件;

BSP 组中存放的就是板级配置文件,此处只用到了GPIO输入输出的控制,所以这个组中也存放了一个bsp_gpio.c文件;

APP 组里面放了一个app.c文件。

对于STC的库文件,我们一般不需要做太多修改。比如gpio.c这个库文件中,就是一些对GPIO的配置,我们只需要直接调用这个文件即可:

#include      "GPIO.h"

//========================================================================
// 函数: u8      GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx)
// 描述: 初始化IO口.
// 参数: GPIOx: 结构参数,请参考timer.h里的定义.
// 返回: 成功返回0, 空操作返回1,错误返回2.
// 版本: V1.0, 2012-10-22
//========================================================================
u8      GPIO_Inilize(u8 GPIO, GPIO_InitTypeDef *GPIOx)
{
      if(GPIO > GPIO_P7)                              return 1;      //空操作
      if(GPIOx->Mode > GPIO_OUT_PP)      return 2;      //错误
      if(GPIO == GPIO_P0)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P0M1 &= ~GPIOx->Pin,      P0M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P0M1 |=GPIOx->Pin,      P0M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P0M1 |=GPIOx->Pin,      P0M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P0M1 &= ~GPIOx->Pin,      P0M0 |=GPIOx->Pin;         //推挽输出
      }
      if(GPIO == GPIO_P1)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P1M1 &= ~GPIOx->Pin,      P1M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P1M1 |=GPIOx->Pin,      P1M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P1M1 |=GPIOx->Pin,      P1M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P1M1 &= ~GPIOx->Pin,      P1M0 |=GPIOx->Pin;         //推挽输出
      }
      if(GPIO == GPIO_P2)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P2M1 &= ~GPIOx->Pin,      P2M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P2M1 |=GPIOx->Pin,      P2M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P2M1 |=GPIOx->Pin,      P2M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P2M1 &= ~GPIOx->Pin,      P2M0 |=GPIOx->Pin;         //推挽输出
      }
      if(GPIO == GPIO_P3)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P3M1 &= ~GPIOx->Pin,      P3M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P3M1 |=GPIOx->Pin,      P3M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P3M1 |=GPIOx->Pin,      P3M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P3M1 &= ~GPIOx->Pin,      P3M0 |=GPIOx->Pin;         //推挽输出
      }
      if(GPIO == GPIO_P4)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P4M1 &= ~GPIOx->Pin,      P4M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P4M1 |=GPIOx->Pin,      P4M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P4M1 |=GPIOx->Pin,      P4M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P4M1 &= ~GPIOx->Pin,      P4M0 |=GPIOx->Pin;         //推挽输出
      }
      if(GPIO == GPIO_P5)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P5M1 &= ~GPIOx->Pin,      P5M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P5M1 |=GPIOx->Pin,      P5M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P5M1 |=GPIOx->Pin,      P5M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P5M1 &= ~GPIOx->Pin,      P5M0 |=GPIOx->Pin;         //推挽输出
      }
      if(GPIO == GPIO_P6)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P6M1 &= ~GPIOx->Pin,      P6M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P6M1 |=GPIOx->Pin,      P6M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P6M1 |=GPIOx->Pin,      P6M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P6M1 &= ~GPIOx->Pin,      P6M0 |=GPIOx->Pin;         //推挽输出
      }
      if(GPIO == GPIO_P7)
      {
                if(GPIOx->Mode == GPIO_PullUp)                P7M1 &= ~GPIOx->Pin,      P7M0 &= ~GPIOx->Pin;         //上拉准双向口
                if(GPIOx->Mode == GPIO_HighZ)                P7M1 |=GPIOx->Pin,      P7M0 &= ~GPIOx->Pin;         //浮空输入
                if(GPIOx->Mode == GPIO_OUT_OD)                P7M1 |=GPIOx->Pin,      P7M0 |=GPIOx->Pin;         //开漏输出
                if(GPIOx->Mode == GPIO_OUT_PP)                P7M1 &= ~GPIOx->Pin,      P7M0 |=GPIOx->Pin;         //推挽输出
      }
      return 0;      //成功
}
delay.c文件中void delay_ms(unsigned char ms)函数,因为这个函数的参数的数据类型使用的是unsigned char类型,所以,这里最大只支持1~255ms的延时,库文件中也有说明:

#include      "delay.h"

//========================================================================
// 函数: voiddelay_ms(unsigned char ms)
// 描述: 延时函数。
// 参数: ms,要延时的ms数, 这里只支持1~255ms. 自动适应主时钟.
// 返回: none.
// 版本: VER1.0
// 日期: 2013-4-1
// 备注:
//========================================================================
voiddelay_ms(unsigned char ms)
{
      unsigned int i;
      do{
                i = MAIN_Fosc / 13000;
                while(--i)      ;   //14T per loop
      }while(--ms);
}


其中,MAIN_Fosc是系统晶振,这个大家需要根据自己板子上实际使用的晶振选择,程序中选择的晶振跟电路板上的一致,

定时才能比较准确。要修改晶振的话,是在config.h这个文件中,如下所示,本例中使用的是11.0592Mhz的晶振频率:

#ifndef                __CONFIG_H
#define                __CONFIG_H

/*********************************************************/

//#define MAIN_Fosc                22118400L      //定义主时钟
//#define MAIN_Fosc                12000000L      //定义主时钟
#define MAIN_Fosc                11059200L      //定义主时钟
//#define MAIN_Fosc               5529600L      //定义主时钟
//#define MAIN_Fosc                24000000L      //定义主时钟


/*********************************************************/

#include      "STC15Fxxxx.H"

#endif
接下来我们一起来看bsp_gpio.c文件,这个文件里面的内容不多,就是对板级输入、输出引脚的配置,代码如下:

#include      "bsp_gpio.h"

/************************ IO口配置 ****************************/
void GPIO_Config(void)
{
      GPIO_InitTypeDef      GPIO_InitStructure;                                                      //结构定义
   
    //Y00
    GPIO_InitStructure.Pin= Y00_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_OUT_PP;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(Y00_GPIO,&GPIO_InitStructure); //初始化
   
    //Y01
    GPIO_InitStructure.Pin= Y01_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_OUT_PP;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(Y01_GPIO,&GPIO_InitStructure); //初始化
   
    //Y02
    GPIO_InitStructure.Pin= Y02_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_OUT_PP;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(Y02_GPIO,&GPIO_InitStructure); //初始化
   
    //Y03
    GPIO_InitStructure.Pin= Y03_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_OUT_PP;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(Y03_GPIO,&GPIO_InitStructure); //初始化
   
    //Y04
    GPIO_InitStructure.Pin= Y04_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_OUT_PP;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(Y04_GPIO,&GPIO_InitStructure); //初始化
   
    //Y05
    GPIO_InitStructure.Pin= Y05_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_OUT_PP;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(Y05_GPIO,&GPIO_InitStructure); //初始化
   
    //X00
    GPIO_InitStructure.Pin= X00_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X00_GPIO,&GPIO_InitStructure); //初始化
   
    //X01
    GPIO_InitStructure.Pin= X01_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X01_GPIO,&GPIO_InitStructure); //初始化
   
    //X02
    GPIO_InitStructure.Pin= X02_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X02_GPIO,&GPIO_InitStructure); //初始化
   
    //X03
    GPIO_InitStructure.Pin= X03_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X03_GPIO,&GPIO_InitStructure); //初始化
   
    //X04
    GPIO_InitStructure.Pin= X04_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X04_GPIO,&GPIO_InitStructure); //初始化
   
    //X05
    GPIO_InitStructure.Pin= X05_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X05_GPIO,&GPIO_InitStructure); //初始化
   
    //X06
    GPIO_InitStructure.Pin= X06_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X06_GPIO,&GPIO_InitStructure); //初始化
   
    //X07
    GPIO_InitStructure.Pin= X07_GPIO_PIN;            //指定要初始化的IO
      GPIO_InitStructure.Mode = GPIO_PullUp;                //指定IO的输入或输出方式,GPIO_PullUp,GPIO_HighZ,GPIO_OUT_OD,GPIO_OUT_PP
      GPIO_Inilize(X07_GPIO,&GPIO_InitStructure); //初始化
      
    Y00 = OutputT_OFF;
    Y01 = OutputT_OFF;
    Y02 = OutputT_OFF;
    Y03 = OutputT_OFF;
    Y04 = OutputT_OFF;
    Y05 = OutputT_OFF;
}

GPIO_config()这个函数主要实现了Y00-Y05引脚输出模式的配置,根据前一节介绍到硬件部分,这里需要设置成推挽模式,即:GPIO_OUT_PP。

另外,在将所有输出引脚配置成推挽模式之后,还需要将所有输出端引脚的初始电平拉低,否则所有的MOS管在一上电就会被导通了。

所以在这个函数的后面,还添加了:

Y00 = OutputT_OFF;
Y01 = OutputT_OFF;
Y02 = OutputT_OFF;
Y03 = OutputT_OFF;
Y04 = OutputT_OFF;
Y05 = OutputT_OFF;

这六条语句。

细心的小伙伴们可能发现了,笔者这里用到了很多的宏定义,如:Y00_GPIO_PIN、Y00_GPIO等,

这些都是宏定义,这些宏定义是在bsp_gpio.h这个文件中:

#ifndef      __BSP_GPIO_H__
#define      __BSP_GPIO_H__

#include      "GPIO.h"

/****************** 输出GPIO ******************/
//Y00 - Y05
#define Y00                        P37
#define Y00_GPIO_PIN               GPIO_Pin_7
#define Y00_GPIO                   GPIO_P3

#define Y01                        P36
#define Y01_GPIO_PIN               GPIO_Pin_6
#define Y01_GPIO                   GPIO_P3

#define Y02                        P35
#define Y02_GPIO_PIN               GPIO_Pin_5
#define Y02_GPIO                   GPIO_P3

#define Y03                        P34
#define Y03_GPIO_PIN               GPIO_Pin_4
#define Y03_GPIO                   GPIO_P3

#define Y04                        P33
#define Y04_GPIO_PIN               GPIO_Pin_3
#define Y04_GPIO                   GPIO_P3

#define Y05                        P32
#define Y05_GPIO_PIN               GPIO_Pin_2
#define Y05_GPIO                   GPIO_P3

//X00 - X07
#define X00                        P12
#define X00_GPIO_PIN               GPIO_Pin_2
#define X00_GPIO                   GPIO_P1

#define X01                        P13
#define X01_GPIO_PIN               GPIO_Pin_3
#define X01_GPIO                   GPIO_P1

#define X02                        P14
#define X02_GPIO_PIN               GPIO_Pin_4
#define X02_GPIO                   GPIO_P1

#define X03                        P15
#define X03_GPIO_PIN               GPIO_Pin_5
#define X03_GPIO                   GPIO_P1

#define X04                        P16
#define X04_GPIO_PIN               GPIO_Pin_6
#define X04_GPIO                   GPIO_P1

#define X05                        P17
#define X05_GPIO_PIN               GPIO_Pin_7
#define X05_GPIO                   GPIO_P1

#define X06                        P54
#define X06_GPIO_PIN               GPIO_Pin_4
#define X06_GPIO                   GPIO_P5

#define X07                        P55
#define X07_GPIO_PIN               GPIO_Pin_5
#define X07_GPIO                   GPIO_P5

#define Input_ON                   0   //输入ON
#define Input_OFF                  1   //输入OFF

#define OutputT_ON               1   //晶体管输出ON
#define OutputT_OFF                0   //晶体管输出OFF

void GPIO_Config(void);

#endif

用宏定义虽然有点浪费程序空间,但是对于笔者使用的IAP15W413AS这个单片机来说,这点空间还是微不足道,

而使用宏定义的好处,自然却是不少,不仅让程序的可读性变得更加友好,同时对于以后的不同项目之间的移植也是提供了极大的方便,

所以,大家以后也可以多多尝试一下。

当然咯,如果大家需要更长时间的延时,可以自行修改一下这个函数,不过笔者建议,

如果需要更大延时和更精准的延时的话,还是使用定时器比较好一些,后续笔者也会给大家介绍。

接下来,我们就来看下main.c里面的代码:

#include      "delay.h"
#include      "app.h"
   
void main(void)
{
    Y00 = OutputT_OFF;
    Y01 = OutputT_OFF;
    Y02 = OutputT_OFF;
    Y03 = OutputT_OFF;
    Y04 = OutputT_OFF;
    Y05 = OutputT_OFF;
   
    delay_ms(250);      //延时一段时间,等待电源稳定
   
      app_init();

      EA = 1;                            //开启总中断

      while(1)
      {      
      app_run();
      }
}

在这里,细心的小伙伴们应该发现了一个问题,在主函数开始的部分,笔者将Y00-Y05全部设置为OFF了,这是为什么呢?

而前面的GPIO_config()函数中,我们也做了同样的操作,这样岂不是多此一举?

其实一开始笔者也没有这么做,但是发现,板子上电的瞬间,所有输出口都会全部闪一下然后又灭了!

于是,笔者去找STC的技术,技术告诉我,上电瞬间单片机的IO口是处于不稳定状态的,初始化完毕后,才会进入设定的模式运行,

而且MOS管是电压驱动,上电IO口浮空的时候的电压足以让MOS管导通了,所以上电后先将输出口全部置0再来进行相关配置,可以避免输出瞬间闪烁的现象!

main.c文件中主要有两个函数需要注意一下,一个是“app_init()”函数,一个是“app_run()”函数,其中,“app_init()”函数主要用于系统初始化,内容也很简单:

void app_init(void)
{
      GPIO_Config();      //GPIO配置
}

而“app_run()”这个函数主要就是实现了这个“流水灯”的效果了:

void app_run(void)
{
    Y00 = OutputT_ON;delay_ms(250);Y00 = OutputT_OFF;delay_ms(250);
    Y01 = OutputT_ON;delay_ms(250);Y01 = OutputT_OFF;delay_ms(250);
    Y02 = OutputT_ON;delay_ms(250);Y02 = OutputT_OFF;delay_ms(250);
    Y03 = OutputT_ON;delay_ms(250);Y03 = OutputT_OFF;delay_ms(250);
    Y04 = OutputT_ON;delay_ms(250);Y04 = OutputT_OFF;delay_ms(250);
    Y05 = OutputT_ON;delay_ms(250);Y05 = OutputT_OFF;delay_ms(250);
}

我们将代码编译没问题后,我们就可以将程序下载到板上,打开STC-ISP软件,按照如下设置并加载keil软件生产的hex文件,

然后点击“下载/编程”按钮准备下载(详细下载方法如有不明白的可以参考STC官方手册):



当出现“正在检测目标单片机”时,我们给板子上电即可开始下载,当出现“操作成功”字样后,说明程序已经成功下载到我们的工控板里面了:



按理说,下载完程序后,我们便会看到输出端的流水灯效果,然而,实际上我们并未看到这个效果,这是为什么呢?

我们仔细看下输出端的接线端子丝印,会发现,原来还有两个V+和V-:



那么这两个接线端子是用来干嘛的呢?我们再来仔细看下原理图:



从原理图上我们可以看到,原来,要是输出端LED灯亮的话,这里还需要接外部电源,

那么我们可以直接用电源适配器供电,然后将DC+、DC-端子分别接到V+和V-上即可:



实物连接图如下图所示:



线路连好之后,我们就可以看到程序能正常的运行了,我们想要的流水灯效果如下:



好了,关于使用延时函数实现流水灯的效果笔者就介绍到这里了,有疑问的小伙伴们可以给笔者留言或者直接参与评论,

下一节笔者将给大家介绍如何利用输入来控制输出,详见“SYK-0806-A2S1 工业自动化控制之【04-输入输出点动控制】”感谢大家的支持!

本章附件:







国芯人工智能 发表于 2025-4-17 08:43:00

在工业自动化控制领域,STC15系列单片机因其高性价比和稳定性,被广泛应用于各种控制场景。本文将详细介绍如何使用STC15系列库函数开发SYK-0806-A2S1工业自动化控制板,并通过延时函数演示流水灯效果。

一、硬件分析
SYK-0806-A2S1工控板的输出口Y00-Y05分别对应GPIO口P32-P27。为了实现正确的输出控制,需要将这些GPIO口配置为“推挽输出”模式。这种配置能够确保输出口有足够的驱动能力,以正确驱动MOS管。

二、软件架构
点灯工程的软件部分分为四个Group:SYSTEM、USER、BSP和APP。

1. SYSTEM组
   该组主要存放STC15系列库文件。在本项目中,主要使用了delay库和gpio库。delay库用于实现精确的延时功能,而gpio库则用于配置和控制GPIO口。

2. USER组
   该组存放了项目的main.c文件,这是整个程序的入口文件。在这里,我们将调用各个模块的功能,实现流水灯效果。

3. BSP组
   该组存放板级配置文件。由于本项目仅涉及GPIO输入输出的控制,因此该组中只包含一个bspgpio.c文件。该文件负责初始化GPIO口,并将其配置为推挽输出模式。

4. APP组
   该组存放应用层代码。在这里,我们将实现流水灯的具体逻辑。

三、代码实现
1. GPIO配置
首先,我们需要在bspgpio.c文件中初始化GPIO口,并将其配置为推挽输出模式。

c
include "stc15gpio.h"

void BSPGPIOInit(void) {
    GPIOInitTypeDef GPIOInitStruct;

    GPIOInitStruct.Pin = GPIOPIN27 | GPIOPIN28 | GPIOPIN29 | GPIOPIN30 | GPIOPIN31 | GPIOPIN32;
    GPIOInitStruct.Mode = GPIOMODEOUTPUTPP;
    GPIOInitStruct.Speed = GPIOSPEEDFREQHIGH;

    GPIOInit(GPIOPORT3, &GPIOInitStruct);
}

2. 延时函数
在delay.c文件中,我们实现了一个简单的延时函数,用于控制流水灯的速度。

c
include "delay.h"

void delayms(uint32t ms) {
    uint32t i, j;
    for (i = 0; i < ms; i++) {
      for (j = 0; j < 1000; j++) {
            NOP();
      }
    }
}

3. 流水灯实现
在main.c文件中,我们调用上述函数,实现流水灯效果。

c
include "stc15gpio.h"
include "delay.h"
include "bspgpio.h"

int main(void) {
    BSPGPIOInit();

    while (1) {
      GPIOResetBits(GPIOPORT3, GPIOPIN27);
      delayms(500);
      GPIOSetBits(GPIOPORT3, GPIOPIN27);

      GPIOResetBits(GPIOPORT3, GPIOPIN28);
      delayms(500);
      GPIOSetBits(GPIOPORT3, GPIOPIN28);

      GPIOResetBits(GPIOPORT3, GPIOPIN29);
      delayms(500);
      GPIOSetBits(GPIOPORT3, GPIOPIN29);

      GPIOResetBits(GPIOPORT3, GPIOPIN30);
      delayms(500);
      GPIOSetBits(GPIOPORT3, GPIOPIN30);

      GPIOResetBits(GPIOPORT3, GPIOPIN31);
      delayms(500);
      GPIOSetBits(GPIOPORT3, GPIOPIN31);

      GPIOResetBits(GPIOPORT3, GPIOPIN32);
      delayms(500);
      GPIOSetBits(GPIOPORT3, GPIOPIN32);
    }
}

四、总结
通过以上步骤,我们成功实现了SYK-0806-A2S1工控板的流水灯效果。本文详细介绍了硬件配置、软件架构以及代码实现,希望能够帮助读者更好地理解STC15系列单片机在工业自动化控制中的应用。对于更复杂的控制逻辑,读者可以根据实际需求,进一步扩展和优化代码。

[本文内容由国芯人工智能辅助生成,仅供参考]

国芯人工智能 发表于 2025-4-17 08:43:00

在工业自动化控制领域,STC15系列微控制器以其高性能和稳定性,广泛应用于各类工控设备中。本文将以SYK-0806-A2S1工业自动化控制板为例,详细介绍如何利用STC15系列库函数实现延时函数演示流水灯的效果。

首先,我们需要了解SYK-0806-A2S1控制板的硬件结构。从硬件原理图可知,该板的6个输出口Y00-Y05分别对应GPIO口P32-P27。为了正确驱动MOS管,这些输出口需要配置为“推挽输出”模式。因此,在编写代码时,务必注意GPIO口的配置。

接下来,我们来看点灯工程的软件结构。该工程主要分为四个组:SYSTEM、USER、BSP和APP。其中,SYSTEM组存放了STC15系列的库文件,本项目主要使用了delay库和gpio库;USER组中存放了主函数文件main.c;BSP组存放了板级配置文件,本项目主要使用了bspgpio.c文件。

在实现流水灯效果时,我们首先需要在main.c文件中初始化GPIO口,并将其配置为推挽输出模式。然后,通过调用delay库中的延时函数,控制各个LED灯的亮灭顺序,从而实现流水灯效果。具体代码如下:

c
include "stc15.h"
include "gpio.h"
include "delay.h"

void main(void)
{
    // 初始化GPIO口
    GPIOInitTypeDef GPIOInitStructure;
    GPIOInitStructure.Pin = GPIOPin32 | GPIOPin31 | GPIOPin30 | GPIOPin27 | GPIOPin26 | GPIOPin25;
    GPIOInitStructure.Mode = GPIOModeOutPP;
    GPIOInit(GPIOP3, &GPIOInitStructure);

    while (1)
    {
      // 流水灯效果
      GPIOSetBits(GPIOP3, GPIOPin32);
      delayms(200);
      GPIOResetBits(GPIOP3, GPIOPin32);
      GPIOSetBits(GPIOP3, GPIOPin31);
      delayms(200);
      GPIOResetBits(GPIOP3, GPIOPin31);
      GPIOSetBits(GPIOP3, GPIOPin30);
      delayms(200);
      GPIOResetBits(GPIOP3, GPIOPin30);
      GPIOSetBits(GPIOP3, GPIOPin27);
      delayms(200);
      GPIOResetBits(GPIOP3, GPIOPin27);
      GPIOSetBits(GPIOP3, GPIOPin26);
      delayms(200);
      GPIOResetBits(GPIOP3, GPIOPin26);
      GPIOSetBits(GPIOP3, GPIOPin25);
      delayms(200);
      GPIOResetBits(GPIOP3, GPIOPin25);
    }
}

在上述代码中,我们首先通过GPIOInit函数初始化了P3口的P32-P27引脚,并将其配置为推挽输出模式。然后,在while循环中,依次点亮和熄灭各个LED灯,并通过delayms函数实现200ms的延时,从而形成流水灯效果。

通过以上步骤,我们成功利用STC15系列库函数实现了SYK-0806-A2S1控制板的延时函数演示流水灯效果。希望本文能为广大工控开发者提供有益的参考,助力工业自动化控制技术的进一步发展。

[本文内容由国芯人工智能辅助生成,仅供参考]
页: [1]
查看完整版本: 【15系列】SYK-0806-A2S1 工业自动化控制之【03-延时函数演示流水灯】