STM32开发,定时器和状态机实现不一样的跑马灯

Wesley13
• 阅读 1106

STM32开发,定时器和状态机实现不一样的跑马灯

  • 1 概述

  • 1.1 资源概述

  • 1.2 代码移植

  • 1.3 实现功能

  • 2 软件实现

  • 2.1工程修改

  • 2.2 main函数代码

  • 3 实验结果

1 概述

1.1 资源概述

开发板:正点原子STM32F103 Nano开发板
CUBEMX版本:1.3.0
MDK版本:5.23
主控芯片型号:STM32F103RBT6
STM32开发,定时器和状态机实现不一样的跑马灯

1.2 代码移植

移植armfly安富莱的代码,代码名称为《V4-001_不一样的流水灯(软件定时器、状态机)(V1.0)》,开发板的主控芯片为STM32F103ZE,均属于M3内核芯片,但是ZE的外设资源多很多,总共144个引脚。但是很可惜,他们的开发板基本没有视频教程,不太方便新人学习。但是代码写的是真的好。非常规范和工整。选择这个程序进行移植时由于都是103芯片,时钟相同,外部晶振也是相同的。程序也相对比较简单。
STM32开发,定时器和状态机实现不一样的跑马灯

1.3 实现功能

这个流水灯程序实现功能如下:
(1)上电时,LED1点亮,闪烁3次,闪烁频率为精确的1Hz。 — 状态0 (持续3秒)。
(2)依次点亮4个LED中的一个, 实现流水灯的效果。— 状态1 (持续5秒)。
(3)依次熄灭4个LED中的一个,实现第2种流水灯效果。 — 状态2 (持续5秒)。
(4)(状态0)–>(状态1)–>(状态2 ))–>(状态1)–>(状态2 )…
这个例子应用1个systick中断实现几个软件定时器,用来控制LED指示灯的闪烁时间。主程序采用了状态机编程方法。

2 软件实现

2.1工程修改

1,修改.s启动文件为startup_stm32f10x_md.s。
STM32开发,定时器和状态机实现不一样的跑马灯
2,修改器件为STM32F103RB。
STM32开发,定时器和状态机实现不一样的跑马灯
3,修改内存容量,当从大容量芯片变更为小容量芯片时容易报内存不足故障,这时需要修改。
STM32开发,定时器和状态机实现不一样的跑马灯
4,修改Define,这里为MD,而不是HD
STM32开发,定时器和状态机实现不一样的跑马灯
5,修改下载器类型,这里选择STLINK
STM32开发,定时器和状态机实现不一样的跑马灯
6,进入下载器设置,确认是否是中等容量flash
STM32开发,定时器和状态机实现不一样的跑马灯
7,修改代码外设,不仅仅时GPIO,还有定时器,通讯等,都要改为和目标板对应。如果时跨平台还要修改时钟等。
安富莱对应LED灯部分原理图。
STM32开发,定时器和状态机实现不一样的跑马灯
安富莱对应程序代码
STM32开发,定时器和状态机实现不一样的跑马灯
按照Nano开发板,改为如下
STM32开发,定时器和状态机实现不一样的跑马灯
8,删除多余外设资源。STM32F103RB只有四个定时器,没有TIM5,删除。
STM32开发,定时器和状态机实现不一样的跑马灯
9,编译下载,建议改代码时,改一块编译一次,否则错误太多不好查找原因更改。
STM32开发,定时器和状态机实现不一样的跑马灯

2.2 main函数代码

代码非常规整,注释也很到位,非常值得我们学习。

#include "bsp.h"                /* 底层硬件驱动 */

/* 定义例程名和例程发布日期 */
#define EXAMPLE_NAME    "V4-001_不一样的跑马灯(软件定时器、状态机)"
#define EXAMPLE_DATE    "2015-08-30"
#define DEMO_VER        "1.0"

uint8_t g_MainStatus = 0;    /* 状态机 */

static void status_0(void);
static void status_1(void);
static void status_2(void);

/*
*********************************************************************************************************
*    函 数 名: main
*    功能说明: c程序入口
*    形    参:无
*    返 回 值: 错误代码(无需处理)
*********************************************************************************************************
*/
int main(void)
{
    /*
        ST固件库中的启动文件已经执行了 SystemInit() 函数,该函数在 system_stm32f4xx.c 文件,主要功能是
    配置CPU系统的时钟,内部Flash访问时序,配置FSMC用于外部SRAM
    */
    bsp_Init();        /* 硬件初始化 */
    
    g_MainStatus = 0;    /* 初始状态为状态0 */
    
    /* 状态机大循环 */
    while (1)
    {
        switch (g_MainStatus)
        {
            case 0:            /* 上电执行一次。LED1闪烁3次,每次间隔1秒。3次后状态机返回。*/
                status_0();    
                g_MainStatus = 1;    /* 转移到状态1 */
                break;
            
            case 1:            /* LED1 - LED4 依次流水显示。每次点亮1个LED。状态持续5秒后返回。 */
                status_1();        
                g_MainStatus = 2;    /* 转移到状态2 */
                break;
            
            case 2:
                status_2();    /* LED1 - LED4 依次流水显示。每次点亮3个LED, 熄灭1个。状态持续5秒后返回。*/
                g_MainStatus = 1;    /* 转移到状态1 */
                break;
        }    
    }
}

/*
*********************************************************************************************************
*    函 数 名: status_0
*    功能说明: 状态0  上电执行一次。LED1闪烁3次,每次间隔1秒。3次后状态机返回。
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
static void status_0(void)
{
    /* 关闭LED */
    bsp_LedOff(1);
    bsp_LedOff(2);
    bsp_LedOff(3);
    bsp_LedOff(4);
    
    /* 点亮 LED1 */
    bsp_LedOn(1);
    
    bsp_StartTimer(0, 3000);        /* 定时器0是3000ms 单次定时器 */        
    bsp_StartAutoTimer(1, 500);        /* 定时器1是500ms 自动重装定时器, 控制LED1按1Hz频率翻转闪烁 */
    while (1)
    {            
        bsp_Idle();        /* CPU空闲时执行的函数,在 bsp.c */
        
        /* 这个地方可以插入其他任务 */        
        
        /* bsp_CheckTimer()检查定时器1时间是否到。函数形参表示软件定时器的ID, 值域0 - 3 */
        if (bsp_CheckTimer(1))        
        {
            bsp_LedToggle(1);        /* 间隔500ms 翻转一次 LED1 */
        }
        
        /* 检查定时器0时间是否到 */
        if (bsp_CheckTimer(0))
        {
            /* 3秒定时到后退出本状态 */
            break;
        }
    }
    
    /* 任务结束时,应该关闭定时器,因为他们会占用后台的资源 */
    //bsp_StopTimer(0);     单次定时器如果超时到过一次后,可以不必关闭
    bsp_StopTimer(1);
}

/*
*********************************************************************************************************
*    函 数 名: status_1
*    功能说明: 状态1。 LED1 - LED4 依次流水显示。每次点亮1个LED。状态持续5秒后返回。
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
static void status_1(void)
{
    uint8_t led_no = 1;        /* LED指示灯序号 1-4 */
    
    bsp_StartTimer(0, 5000);        /* 定时器0是5000ms 单次定时器 */
    bsp_StartAutoTimer(1, 200);        /* 定时器1是500ms 自动重装定时器, 控制LED1按1Hz频率翻转闪烁 */
    bsp_LedOn(1);
    led_no = 1;
    while (1)
    {            
        bsp_Idle();        /* CPU空闲时执行的函数,在 bsp.c */
        
        /* 这个地方可以插入其他任务 */        
        
        /* 检查定时器0时间是否到 */
        if (bsp_CheckTimer(0))
        {
            break;
        }

        if (bsp_CheckTimer(1))        /* 检查自动定时器2,间隔200ms翻转一次LED1 */
        {
            /* 先关闭所有的LED,然后在打开其中一个 */
            bsp_LedOff(1);
            bsp_LedOff(2);
            bsp_LedOff(3);
            bsp_LedOff(4);
            
            if (++led_no == 5)
            {
                led_no = 1;
            }

            bsp_LedOn(led_no);    /* 点亮其中一个LED */    
        }        
    }
    
    /* 任务结束时,应该关闭定时器,因为他们会占用后台的资源 */
    //bsp_StopTimer(0);     单次定时器如果超时到过一次后,可以不必关闭
    bsp_StopTimer(1);
}

/*
*********************************************************************************************************
*    函 数 名: status_2
*    功能说明: 状态2.  LED1 - LED4 依次流水显示。每次点亮3个LED, 熄灭1个。状态持续5秒后返回。
*    形    参:无
*    返 回 值: 无
*********************************************************************************************************
*/
static void status_2(void)
{
    uint8_t led_no = 1;        /* LED指示灯序号 1-4 */
    
    bsp_StartTimer(0, 5000);        /* 定时器0是5000ms 单次定时器 */
    bsp_StartAutoTimer(1, 200);        /* 定时器1是500ms 自动重装定时器, 控制LED1按1Hz频率翻转闪烁 */
    bsp_LedOn(1);
    led_no = 1;
    while (1)
    {            
        bsp_Idle();        /* CPU空闲时执行的函数,在 bsp.c */
        
        /* 这个地方可以插入其他任务 */        
        
        /* 检查定时器0时间是否到 */
        if (bsp_CheckTimer(0))
        {
            break;
        }

        if (bsp_CheckTimer(1))        /* 检查自动定时器2,间隔200ms翻转一次LED1 */
        {
            /* 先打开所有的LED,然后在关闭其中一个 */
            bsp_LedOn(1);
            bsp_LedOn(2);
            bsp_LedOn(3);
            bsp_LedOn(4);
            
            if (++led_no == 5)
            {
                led_no = 1;
            }

            bsp_LedOff(led_no);    /* 点亮其中一个LED */            
        }        
    }
    
    /* 任务结束时,应该关闭定时器,因为他们会占用后台的资源 */
    //bsp_StopTimer(0);     单次定时器如果超时过一次后,可以不必执行stop函数
    bsp_StopTimer(1);
}

实验完整代码已经同步上传

3 实验结果

下载完程序之后,复位运行程序。观察开发板上的LED1-LED4 指示灯的状态。与设计预期一致。
STM32开发,定时器和状态机实现不一样的跑马灯

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Stella981 Stella981
2年前
Eclipse插件开发_学习_00_资源帖
一、官方资料 1.eclipseapi(https://www.oschina.net/action/GoToLink?urlhttp%3A%2F%2Fhelp.eclipse.org%2Fmars%2Findex.jsp%3Ftopic%3D%252Forg.eclipse.platform.doc.isv%252Fguide%2
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这