ARM32开发——LED驱动开发

🎬 秋野酱:《个人主页》
🔥 个人专栏:《Java专栏》《Python专栏》

⛺️心若有所向往,何惧道阻且长

文章目录

    • 需求介绍
    • 现实问题
    • 需求分析
    • 测试案例构建
    • BSP驱动构建
    • 业务实现

需求介绍

在这里插入图片描述

开发版中有4个灯,现在需要用4个灯显示充电情况:

  1. 开始充电时,需要呈现出流水灯闪烁
  2. 4盏灯表示当前的电量
  3. 充电流水灯起始位置是当前电量,全部点亮后,再次从当前电量位置进入流水灯效果
  4. 结束充电时,关闭充电显示,当前电量进行闪烁3次,然后熄灭。
    在这里插入图片描述

现实问题

  1. 产品最终电路板还没画好,目前只有产品所使用的芯片对应的开发板。
  2. ADC功能是别人开发,还没完成。
  3. 老板要求,如果开发板好了,要尽快完成工作。

需求分析

要啥没啥,还得尽快完成。盘点手头有的东西,开发板。构建测试案例逻辑,方便后续移植。
测试案例设计:

  1. 准备工作,4个灯,3个按钮
  2. 按钮1按下时,模拟开始充电
  3. 按钮2按下时,模拟停止充电
  4. 按钮3按下时,模拟电量增加。
    如果测试方案通过,基本上功能完成,那么后续其他人工作完成后,只需要对接以下逻辑:
  5. 灯对应的引脚和最终设计的电路板引脚进行校准
  6. 开始充电
  7. 电量变化时,更新电量
  8. 结束充电

编码实现分析:

  1. 需要把4个灯作为一个业务逻辑整体,完成一套关于电池电量显示的驱动
  2. 需要抽象出业务逻辑,转换为函数实现

测试案例构建

在这里插入图片描述

● PC0作为:开始按钮
● PC1作为:停止按钮
● PC2作为:电量更新按钮
按钮逻辑构建

static void GPIO_config(){	// PD0	开始充电// PD1 	结束充电// PD5	电量变化// rcu时钟rcu_periph_clock_enable(RCU_GPIOD);// 配置GPIO模式gpio_mode_set(GPIOD,GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5);	
}

int main(void) {// 系统滴答定时器初始化systick_config();// GPIO初始化GPIO_config();// LED初始化Battery_led_init();FlagStatus pre_state0 = SET;// 默认高电平抬起FlagStatus pre_state1 = SET;// 默认高电平抬起FlagStatus pre_state2 = SET;// 默认高电平抬起uint32_t cnt = 0;uint8_t power = 1;while(1) {// PC0FlagStatus state0 = gpio_input_bit_get(GPIOC, GPIO_PIN_0);if (state0 != pre_state0){if(state0 == RESET){   // 当前低电平, 上一次为高电平,按下Battery_led_start(power);}pre_state0 = state0;	}// PC1FlagStatus state1 = gpio_input_bit_get(GPIOC, GPIO_PIN_1);if (state1 != pre_state1){if(state1 == RESET){   // 当前低电平, 上一次为高电平,按下Battery_led_stop();}pre_state1 = state1;	}// PC2FlagStatus state2 = gpio_input_bit_get(GPIOC, GPIO_PIN_2);if (state2 != pre_state2){if(state2 == RESET){   // 当前低电平, 上一次为高电平,按下//				Battery_led_turn_off(LED1);Battery_led_update(++power);}pre_state2 = state2;	}// 间隔50个10ms = 500ms执行一次led的状态更新if(++cnt % 50 == 0){Battery_led_loop();}delay_1ms(10);}}

BSP驱动构建

接口定义

  1. 驱动初始化,属于标配
  2. 业务相关的操作行为抽象化
  3. 时序问题
void Battery_led_int();

具体的业务抽象行为

void Battery_led_start(uint8_t power);
void Battery_led_stop();
void Battery_led_update(uint8_t power);

在涉及到需要控制时间的问题时,我们通常有以下做法:

  1. 自己主动调用 delay来进行延时
  2. 使用统一的延时,到达自己的时间点就去执行
    自己调用delay 不利于后续的移植。
    采用统一时钟,方便移植,也方便时间片统一调度管理

业务实现

  1. 采用bsp独立驱动进行开发
  2. 状态管理,通过status记录当前状态。
  3. 电量记录,记录当前电量。
  4. 充电闪烁计数,记录当前的闪烁的值。
#ifndef __BSP_BATTERY_LED_H__
#define __BSP_BATTERY_LED_H__#include "gd32f4xx.h"#define LED1	1
#define LED2	2
#define LED3	3
#define LED4	4void Battery_led_init();void Battery_led_turn_on(uint8_t led_index);void Battery_led_turn_off(uint8_t led_index);void Battery_led_turn(uint8_t led_index, uint8_t value);void Battery_led_start(uint8_t power);void Battery_led_loop();void Battery_led_update(uint8_t power);void Battery_led_stop();#endif
#include "bsp_battery_led.h"
#include "systick.h"// 声明gpio初始化所需参数的结构体
typedef struct {rcu_periph_enum rcu;uint32_t port;uint32_t pin;
} Led_GPIO_t;// 声明所有gpio对应参数的数组
Led_GPIO_t g_gpio_list[] = {{RCU_GPIOC, GPIOC, GPIO_PIN_6},        // LED_SW{RCU_GPIOD, GPIOD, GPIO_PIN_8},        // LED1{RCU_GPIOD, GPIOD, GPIO_PIN_9},        // LED2{RCU_GPIOD, GPIOD, GPIO_PIN_10},       // LED3{RCU_GPIOD, GPIOD, GPIO_PIN_11},       // LED4
};// 用于计算数组长度的宏
#define MAX_LED_COUNT	(sizeof(g_gpio_list) / sizeof(Led_GPIO_t))/*********************************************************** @brief LED GPIO初始化**********************************************************/
static void GPIO_config(rcu_periph_enum rcu, uint32_t port, uint32_t pin) {// 初始化为推挽输出模式rcu_periph_clock_enable(rcu);gpio_mode_set(port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, pin);gpio_output_options_set(port, GPIO_OTYPE_PP, GPIO_OSPEED_MAX, pin);
}void Battery_led_init() {uint8_t count = MAX_LED_COUNT;for(uint8_t i = 0; i < count; i++) {Led_GPIO_t gpio = g_gpio_list[i];// 初始化GPIO_config(gpio.rcu,gpio.port, gpio.pin);// 默认全部拉高(关闭)gpio_bit_write(gpio.port, gpio.pin, SET);}// 总开关拉低(打开)gpio_bit_write(g_gpio_list[0].port, g_gpio_list[0].pin, RESET);
}// 开灯
void Battery_led_turn_on(uint8_t led_index) {Led_GPIO_t gpio = g_gpio_list[led_index];gpio_bit_write(gpio.port, gpio.pin, RESET);
}// 关灯
void Battery_led_turn_off(uint8_t led_index) {Led_GPIO_t gpio = g_gpio_list[led_index];gpio_bit_write(gpio.port, gpio.pin, SET);
}/*********************************************************** @brief 设置灯亮灭* @param led_index LED索引* @param value 0亮,其他灭* @return**********************************************************/
void Battery_led_turn(uint8_t led_index, uint8_t value) {Led_GPIO_t gpio = g_gpio_list[led_index];gpio_bit_write(gpio.port, gpio.pin, value ? RESET : SET);
}int state = 0; // 0:停止, 1:充电中
uint8_t current_power = 0;
uint8_t show_power = 0;
/*********************************************************** @brief 开始充电流水灯* @param 当前电量[0,1,2,3,4]**********************************************************/
void Battery_led_start(uint8_t power) {current_power = power;show_power = current_power;state = 1;
}void Battery_led_loop() {if(state == 0) {Battery_led_turn_off(LED1);Battery_led_turn_off(LED2);Battery_led_turn_off(LED3);Battery_led_turn_off(LED4);} else if(state == 1) {Battery_led_turn(LED1, show_power >= 1);Battery_led_turn(LED2, show_power >= 2);Battery_led_turn(LED3, show_power >= 3);Battery_led_turn(LED4, show_power >= 4);if(++show_power > 4) show_power = current_power;}
}void Battery_led_update(uint8_t power) {current_power = power;
}void Battery_led_stop() {// 当前电量闪三次for( uint8_t i = 0; i < 3; i++) {// 关闭所有灯Battery_led_turn_off(LED1);Battery_led_turn_off(LED2);Battery_led_turn_off(LED3);Battery_led_turn_off(LED4);delay_1ms(200);// 根据当前电量闪灯Battery_led_turn(LED1, current_power >= 1);Battery_led_turn(LED2, current_power >= 2);Battery_led_turn(LED3, current_power >= 3);Battery_led_turn(LED4, current_power >= 4);delay_1ms(200);}state = 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/20181.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

618大促有哪些好物是最值得入手的的?请收下这份618必买好物清单!

最近聊的最多的话题就是618&#xff0c;年中购物大狂欢马上来了&#xff01;&#xff01;今天整理了一下之前购买的好物&#xff0c;发现相比之前的价格真的是太划算了&#xff0c;赶紧分享出来给大家&#xff0c;趁着这个大促赶紧多存入手~ 推荐1、南卡Neo 2——不伤耳黑科技…

SPHINX的输出文档格式

SPHINX的输出文档格式 SPHINX的输出文档格式更多信息 SPHINX的输出文档格式 用rst编写&#xff0c;然后用sphinx-build进行编译&#xff0c;还是效果相当不错地&#xff0c;只要掌握了格式&#xff0c;可以一次编译&#xff0c;多种格式输出&#xff0c;主要是用的可能是html和…

记一次netty客户端的开发

背景 近日要开发一个tcp客户端程序去对接上游厂商的数据源&#xff0c;决定使用netty去处理&#xff0c;由于很久没有开发过netty了&#xff0c;顺便学习记录下 netty搭建 考虑到我们需要多个client去对接server服务&#xff0c;所以我们定义一个公共的AbstractNettyClient父…

机器学习:人工智能中实现自动化决策与精细优化的核心驱动力

机器学习在人工智能中确实扮演着实现自动化决策与精细优化的核心驱动力角色。以下是关于这一点的详细分析: 一、机器学习在自动化决策中的应用 数据驱动:机器学习依赖于大量的数据来进行模型训练和评估,从而确保决策的准确性。通过自动化数据分析和处理,机器学习能够从海量…

LabVIEW与Arm控制器之间的通讯

LabVIEW是一个强大的图形化编程环境&#xff0c;广泛应用于自动化控制、数据采集和测试测量等领域。而Arm控制器则是嵌入式系统中常用的处理器架构&#xff0c;广泛用于各种控制和计算任务。将LabVIEW与Arm控制器进行通讯控制&#xff0c;可以结合二者的优势&#xff0c;实现高…

vue3 中可缓存的方法

场景&#xff1a;在列表中&#xff0c;有这么一个属性&#xff0c;需要通过同行的其他属性&#xff0c;进行复杂的计算&#xff0c;才能得出&#xff0c;如果我们用方法&#xff0c;然后传参&#xff0c;得到这个属性&#xff0c;那么每次更改列表后&#xff0c;每行都会重新计…

WordPress plugin MStore API SQL注入漏洞复现(CVE-2023-3077)

0x01 产品简介 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 0x02 漏洞概述 WordPress plugin MStore API 3.9.8 版本之前存在S…

Linux 深入讲解自动化构建工具

各位大佬好 &#xff0c;这里是阿川的博客 &#xff0c; 祝您变得更强 个人主页&#xff1a;在线OJ的阿川 大佬的支持和鼓励&#xff0c;将是我成长路上最大的动力 阿川水平有限&#xff0c;如有错误&#xff0c;欢迎大佬指正 Linux一系列的文章&#xff08;质量分均在93分…

配置arduino和ESP8266

首先准备好arduino 的IDE和ESP8266的驱动以及板子 1.安装驱动&#xff0c;双击x64的版本驱动&#xff0c;安装好以后&#xff0c;在资源管理器检查端口&#xff0c;比如下下图出现的COM4就是esp8266所使用的端口 2.安装好arduino最好不要在路径中存在中文符号&#xff0c;打开…

水滴式粉碎机:多功能饲料粉碎设备

饲料粉碎机是一种专门用于将各种饲料原料进行粉碎处理的机械设备。无论是玉米、小麦等谷物&#xff0c;还是豆粕、鱼粉等动物性原料&#xff0c;甚至是一些粗纤维含量较高的秸秆、牧草等&#xff0c;都可以经过饲料粉碎机的处理&#xff0c;变成适合畜禽消化吸收的精细饲料。这…

521源码-游戏源码-2024卡牌回合自走棋手游《梦间集》推出全新Linux手工服务端

首款稀有卡牌回合自走棋手游《梦间集》推出全新Linux手工服务端整理 更多网站源码&#xff0c;游戏源码&#xff0c;学习教程&#xff0c;请点击&#x1f449;-521源码-&#x1f448;获取最新资源 本游戏下载地址&#xff1a;2024卡牌回合自走棋手游《梦间集》推出全新Linux手…

【再探】设计模式—中介者模式、观察者模式及模板方法模式

中介者模式让多对多的复杂引用关系变成一对多&#xff0c;同时能通过中间类来封装多个类中的行为&#xff0c;观察者模式在目标状态更新时能自动通知给订阅者&#xff0c;模版方法模式则是控制方法的执行顺序&#xff0c;子类在不改变算法的结构基础上可以扩展功能实现。 1 中…

003 MySQL

文章目录 左外连接、右外连接 的区别where/having的区别执行顺序聚合 聚合函数MySQL约束事务一致性一致性的含义一致性在事务中的作用如何维护一致性 存储引擎 Innodb MyIsam区别事务的ACID属性数据库的隔离级别MySQL中的并发问题1. 锁等待和死锁2. 并发冲突3. 脏读、不可重复读…

理解接口回调及其在 RabbitMQ 中的实际运用

介绍 接口回调是一种常见的编程模式&#xff0c;它在异步编程中发挥着重要作用。本文将通过一个简单的示例介绍接口回调的概念和原理&#xff0c;并探讨它在 RabbitMQ 中的实际应用。 接口回调的概念 接口回调是一种编程模式&#xff0c;用于在异步编程中实现回调机制。它允许…

ChatGPT AI专题资料合集【65GB】

介绍 ChatGPT & AI专题资料合集【65GB】 &#x1f381;【七七云享】资源仓库&#xff0c;海量资源&#xff0c;无偿分享√

stm32和esp32硬件资源上有什么区别 哪个更适合初学者

对于初学者来说&#xff0c;ESP32和STM32都有各自的优点和适用场景&#xff0c;但通常ESP32被认为是更适合初学者的选择&#xff0c;原因如下&#xff1a; 内置无线通信&#xff1a;ESP32集成了WiFi和蓝牙功能&#xff0c;这意味着初学者可以更容易地构建无线通信应用&#xff…

文件系统小册(FusePosixK8s csi)【1 Fuse】

文件系统小册&#xff08;Fuse&Posix&K8s csi&#xff09;【1 Fuse&#xff1a;用户空间的文件系统】 Fuse(filesystem in userspace),是一个用户空间的文件系统。通过fuse内核模块的支持&#xff0c;开发者只需要根据fuse提供的接口实现具体的文件操作就可以实现一个文…

【测评|白嫖】雨云宁波新区,2C4G200M,公测期间全免费!

雨云香港三区云服务器&#xff0c;高性能的 Xeon Platinum 处理器 企业级 NVME SSD 高性能云服务器。 一键白嫖链接&#xff1a;https://www.rainyun.com 本篇纯测评&#xff0c;无任何广告&#xff0c;请放心食用&#xff01;&#xff01; 本次测评服务器配置如下&#xff1…

用万界星空科技低代码平台能快速搭建一个云MES系统

一、低代码平台与MES:智能制造的新篇章 随着工业4.0和智能制造的兴起&#xff0c;企业对于生产过程的数字化、智能化需求日益迫切。传统的MES系统实施周期长、成本高&#xff0c;成为许多企业数字化转型的瓶颈。而低代码开发平台的出现为这一问题提供了新的解决思路。 二、万界…

linux可观测性ebpf(一) ----------- 环境搭建

参考书籍 开发环境 Ubuntu 18.04.6 LTS (GNU/Linux 5.4.0-150-generic x86_64) 1.1 下载内核源码 cd /usr/src/ sudo git clone -b v5.4 https://github.com/torvalds/linux.git1.2 下载书中代码 git clone https://github.com/bpftools/linux-observability-with-bpf1.3 编…