C语言实现面向对象—以LED驱动为例

点亮一个LED

常见的LED代码

分层分离思想

面向对象的LED驱动

LED左边高电平。 当LED右边为低电平时,LED有电流通过,LED亮。反之,LED灭

GPIO功能描述:

点亮LED的步骤及代码:

开启GPIO的时钟

配置GPIO为输出模式

GPIO输出低电平

 

设备驱动的分层分离设计

硬件抽象层(HAL):硬件抽象层是位于最底层的层次,负责与特定硬件设备进行通信。它隐藏了底层硬件的细节,为上层提供统一的接口。HAL层通常由操作系统提供或者由芯片厂商提供的驱动程序组成。

设备驱动层:设备驱动层位于硬件抽象层之上,负责管理特定设备的操作和控制。它与硬件抽象层进行交互,并提供更高级别的接口供上层使用。设备驱动层通常由操作系统内核或者第三方开发者提供。

总线控制层:总线控制层负责管理设备之间的通信和协调。在一个系统中可能存在多个设备通过总线连接的情况,总线控制层负责管理这些设备之间的数据传输和信号交换。

操作系统抽象层:操作系统抽象层位于设备驱动层之上,提供了更高级别的接口和服务,使得应用程序可以方便地访问设备。这包括对文件系统的访问、进程管理、内存管理等。

用户空间接口:用户空间接口提供了用户空间程序与设备驱动层之间的通信接口,使得用户程序可以通过系统调用或者特定的库函数来访问设备。

main.c

#define LED_CLOCK_0()                 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE)
#define LED_PIN_0                     GPIO_Pin_5
#define LED_PORT_0                    GPIOE#define LED_CLOCK_1()                 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE)
#define LED_PIN_1                     GPIO_Pin_6
#define LED_PORT_1                    GPIOE#define LED_CLOCK_2()                 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE)
#define LED_PIN_2                     GPIO_Pin_13
#define LED_PORT_2                    GPIOCLED_t LED;/******************************************************************************* @brief     初始化LED** @param[in] 无** @return    无*******************************************************************************/
void LED_Init_Easy(void)
{GPIO_InitTypeDef GPIO_InitStructure;LED_CLOCK_0();    //使能GPIO引脚时钟LED_CLOCK_1();LED_CLOCK_2();GPIO_InitStructure.GPIO_Mode     =  GPIO_Mode_OUT;       //配置GPIO为输出模式GPIO_InitStructure.GPIO_OType    =  GPIO_OType_PP;       //推挽输出GPIO_InitStructure.GPIO_PuPd     =  GPIO_PuPd_UP;        //上拉模式GPIO_InitStructure.GPIO_Speed    =  GPIO_Speed_100MHz;   //引脚速度为100MhzGPIO_InitStructure.GPIO_Pin      =  LED_PIN_0;           //初始化LED0GPIO_Init(LED_PORT_0, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin      =  LED_PIN_1;           //初始化LED1GPIO_Init(LED_PORT_1, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin      =  LED_PIN_2;           //初始化LED2GPIO_Init(LED_PORT_2, &GPIO_InitStructure);GPIO_SetBits(LED_PORT_0, LED_PIN_0);                     //三个LED全部设置为灭GPIO_SetBits(LED_PORT_1, LED_PIN_1);GPIO_SetBits(LED_PORT_2, LED_PIN_1);//    GPIO_InitTypeDef GPIO_InitStructure;
//    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
//    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
//    
//    GPIO_InitStructure.GPIO_Mode     =  GPIO_Mode_OUT;       //配置GPIO为输出模式
//    GPIO_InitStructure.GPIO_OType    =  GPIO_OType_PP;       //推挽输出
//    GPIO_InitStructure.GPIO_PuPd     =  GPIO_PuPd_UP;        //上拉模式
//    GPIO_InitStructure.GPIO_Speed    =  GPIO_Speed_100MHz;   //引脚速度为100Mhz//    GPIO_InitStructure.GPIO_Pin      =  GPIO_Pin_5;
//    GPIO_Init(GPIOE, &GPIO_InitStructure);
//    
//    GPIO_InitStructure.GPIO_Pin      =  GPIO_Pin_6;
//    GPIO_Init(GPIOE, &GPIO_InitStructure);
//    
//    GPIO_InitStructure.GPIO_Pin      =  GPIO_Pin_13;
//    GPIO_Init(GPIOC, &GPIO_InitStructure);
}/******************************************************************************* @brief     简单的延时函数** @param[in]  time  :  延时时间** @return     无*******************************************************************************/
void Delay(int time)
{for (int i = time; i > 0; i--) {for (int j = 0xffff; j > 0; j--) {;}}
}//int main(void)
//{
//    LED_Init_Easy();//    while (1) {//        //打开所有的LED灯
//        GPIO_ResetBits(LED_PORT_0, LED_PIN_0);
//        GPIO_ResetBits(LED_PORT_1, LED_PIN_1);
//        GPIO_ResetBits(LED_PORT_2, LED_PIN_2);
//        Delay(1000);//        //关闭所有的LED灯
//        GPIO_SetBits(LED_PORT_0, LED_PIN_0);
//        GPIO_SetBits(LED_PORT_1, LED_PIN_1);
//        GPIO_SetBits(LED_PORT_2, LED_PIN_2);
//        Delay(1000);
//    }
//}LED_t gLed[3];int main(void)
{LED_Init(&gLed[0], GPIOE, GPIO_Pin_5);LED_Init(&gLed[1], GPIOE, GPIO_Pin_6);LED_Init(&gLed[2], GPIOC, GPIO_Pin_13);while (1) {//打开所有的LED灯LED_On(&gLed[0]);LED_On(&gLed[1]);LED_On(&gLed[2]);Delay(1000);//关闭所有的LED灯LED_Off(&gLed[0]);LED_Off(&gLed[1]);LED_Off(&gLed[2]);Delay(1000);}
}

 led.c

#include "led.h"//高电平灭,低电平亮
#define     LED_PIN_ON                          0
#define     LED_PIN_OFF                         1#if  defined  (STM32F40_41xxx)#define    __LED_CONFIG_IO_OUTPUT(port, pin)         { GPIO_InitTypeDef                    GPIO_InitStructure; \GPIO_InitStructure.GPIO_Mode     =  GPIO_Mode_OUT; \GPIO_InitStructure.GPIO_OType    =  GPIO_OType_PP; \GPIO_InitStructure.GPIO_PuPd     =  GPIO_PuPd_UP; \GPIO_InitStructure.GPIO_Speed    =  GPIO_Speed_100MHz; \GPIO_InitStructure.GPIO_Pin      =  pin ; \GPIO_Init(port, &GPIO_InitStructure);}#define    __LED_IO_SET(port, pin, value)            { if (value == LED_PIN_OFF) \GPIO_SetBits(port, pin); \else \GPIO_ResetBits(port, pin); \}
#endif/******************************************************************************* @brief     初始化LED** @param[in]  led   :  led结构体指针* @param[in]  port  :  引脚端口* @param[in]  pin   :  引脚** @return     0, 表示初始化成功, 其他值表示失败*******************************************************************************/
int LED_Init(LED_t *led, LED_GPIO_Port_t port, uint32_t pin) //IO初始化
{if (!led)return -1;//配置引脚,默认输出
#if  defined  (STM32F40_41xxx)assert_param(IS_GPIO_ALL_PERIPH(port));if (port  == GPIOA)        { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); }else if (port  == GPIOB)   { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); }else if (port  == GPIOC)   { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); }else if (port  == GPIOD)   { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE); }else if (port  == GPIOE)   { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); }else if (port  == GPIOF)   { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE); }else if (port  == GPIOG)   { RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); }else return -1;#endifled->port = port;led->pin = pin;led->init = true;led->status = false;__LED_CONFIG_IO_OUTPUT(led->port, led->pin);LED_Off(led);return 0;
}/******************************************************************************* @brief      打开led** @param[in]  led   :  led结构体指针** @return     0, 表示正常, 其他值表示失败*******************************************************************************/
int LED_On(LED_t *led)
{if (!led || !led->init)return -1;  //初始化引脚之后__LED_IO_SET(led->port, led->pin, LED_PIN_ON);   //低电平亮led->status = true;return 0;
}/******************************************************************************* @brief      关闭led** @param[in]  led   :  led结构体指针** @return     0, 表示正常, 其他值表示失败*******************************************************************************/
int LED_Off(LED_t *led)
{if (!led || !led->init)return -1;  //初始化引脚之后__LED_IO_SET(led->port, led->pin, LED_PIN_OFF);   //高电平灭led->status = false;return 0;
}/******************************************************************************* @brief      设置led状态** @param[in]  led   :  led结构体指针* @param[in]  status:  led开关状态** @return     0, 表示正常, 其他值表示失败*******************************************************************************/
int LED_SetStatus(LED_t *led, bool status)
{if (!led || !led->init)return -1;  //初始化引脚之后led->status = status;return 0;
}/******************************************************************************* @brief      刷新led状态** @param[in]  led   :  led结构体指针** @return     0, 表示正常, 其他值表示失败*******************************************************************************/
int LED_RefreshStatus(LED_t *led)
{if (!led || !led->init)return -1;  //初始化引脚之后if (led->status == true) {__LED_IO_SET(led->port, led->pin, LED_PIN_ON);   //低电平亮} else {__LED_IO_SET(led->port, led->pin, LED_PIN_OFF);   //高电平灭}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

【linux】dmesg工具

dmesg介绍 dmesg工具用途: dmesg - print or control the kernel ring buffer kernel ring buffer, 内核环形缓冲区,也叫环形队列,Linux内核日志就存储在一个环形队列中,环形队列满的时候,新的消息会覆盖掉旧的消息。…

pdf转word,结果为什么是图片?怎么才能转成可编辑的文字?

PDF转Word为何会变成图片?这是许多人在使用文件格式转换工具时经常遇到的问题。为了解答这个疑问,我们需要从多个方面来探讨这个问题。 首先,PDF文件本身的特点是一个重要的因素。PDF,即Portable Document Format,是一…

在ubuntu虚拟机中手动安装VMware Tools(VMware Workstation 17 player)

可参考官方文档:在 Linux 虚拟机中手动安装 VMware Tools 以下列出我在安装过程中遇见的问题: 1、“安装VMware Tools”选项为灰,无法选中 原因是VMware Tools的安装包镜像在Player的安装目录下,需要在虚拟机启动的时候加载这个…

品鉴中的情感交流:如何通过红酒建立深厚的社交联系

品鉴红酒不仅仅是一种感官体验,更是一种情感交流的方式。云仓酒庄雷盛红酒作为一种品质的红酒品牌,能够为人们提供一种与众不同的社交体验,帮助建立深厚的社交联系。 首先,共享品鉴体验是建立社交联系的关键。与朋友、家人或合作伙…

ODOO17数据库安全策略一(ODOO17 Database Security Policy I)

ODOO17作为ERP软件,其核心优势在于数据安全。凭借强大的原生安全机制及灵活的配置,确保数据安全无忧: ODOO17, as an ERP software, boasts its significant advantage in exceptional data security performance. It effectively ensures wo…

Linux最新提权通杀五大绝招(上)

点击星标,即时接收最新推文 本文选自《内网安全攻防:红队之路》 扫描二维码五折购书 Linux 主机权限提升问题是普遍存在的。在Web 服务器、数据库、防火墙、IOT等基础设施中,大部分都运行着Linux 操作系统,鉴于Linux 设备在大量基…

鸿蒙OS NEXT的推出,不仅面向App端

华为官方公布6月份的版本为beta版,依然属于开发者测试版,但可以向普通用户开放了。这点和苹果iOS系统测试形式略微相似:6月份开放首个测试版,随后过渡到公测版,最后再和年度新机一起发布正式版系统。 如果按照这个进度…

git bash退出vim编译模式

解决方法: 1.按esc键(回到命令模式) 此时是没有分号让我们在后面输入命令的 2.按shift键: 3.再输入:wq,并按enter键 此时我们发现又回到git bash窗口 希望对大家有所帮助!

flutter开发实战-GetX响应式状态管理使用

flutter开发实战-GetX响应式状态管理使用 GetX是一个简单的响应式状态管理解决方案。GetX是Flutter的一款超轻、功能强大的解决方案。它将高性能状态管理、智能依赖注入和路由管理快速而实用地结合在一起。这里简单使用一下GetX 一、引入GetX 在工程的pubspec.yaml中引入插件…

第十四届蓝桥杯大赛软件赛省赛(Python大学A组)

2023年蓝桥杯 省赛真题Python大学A组 试题A:特殊日期 试题B:分糖果 试题C:三国游戏 试题D:平均 试题E:翻转 试题F:子矩阵 试题G:阶乘的和 …

微软 AI 研究团队推出 SIGMA:一个开源研究平台,旨在推动混合现实与人工智能交叉领域的研究与创新

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

在Linux上使用Selenium驱动Chrome浏览器无头模式

大家好,我们平时在做UI自动化测试的时候,经常会用到Chrome浏览器的无头模式(无界面模式),并且将测试代码部署到Linux系统中执行,或者平时我们写个爬虫爬取网站的数据也会使用到,接下来和大家分享…

KT148A语音芯片串口版本播放音乐的时候,直接导致单片机工作异常

一、问题描述 在使用你们KT148A串口版本播放音乐的时候,直接导致单片机工作异常,测了一下供电发现每次播放音乐的时候,供电会有很大波动。看了一下你们的手册,说是带载能力不够,但是我把供电接出来,接到你…

项目经理【人】任务

系列文章目录 【引论一】项目管理的意义 【引论二】项目管理的逻辑 【环境】概述 【环境】原则 【环境】任务 【环境】绩效 【人】概述 【人】原则 【人】任务 一、定义团队的基本规则&塔克曼阶梯理论 1.1 定义团队的基本规则 1.2 塔克曼阶梯理论 二、项目经理管理风格 …

蓝桥杯单片机之模块代码《AT24C02》

过往历程 历程1:秒表 历程2:按键显示时钟 历程3:列矩阵按键显示时钟 历程4:行矩阵按键显示时钟 历程5:新DS1302 历程6:小数点精确后两位ds18b20 历程7:35定时器测量频率 文章目录 过往历…

CSS引用

CSS定义 层叠样式表:(Cascading Style Sheets,缩写为css),是一种样式表语言,用来描述HTML文档的呈现(美化内容) 书写位置:title标签下方添加style双标签,style标签里写入CSS代码 在s…

【1小时掌握速通深度学习面试11】元学习

目录 ​编辑 52.元学习适合哪些学习场景?可解决什么样的学习问题? 55.元学习与有监督学习/强化学习具体有哪些区别? 1、迁移学习(Transfer Learning) 2、元学习(Meta Learning) 3、小样本学习(Few-Shot Learning&#xf…

YOLOv8的训练、验证、预测及导出[目标检测实践篇]

这一部分内容主要介绍如何使用YOLOv8训练自己的数据集,并进行验证、预测及导出,采用代码和指令的两种方式,参考自官方文档:Detect - Ultralytics YOLOv8 Docs。实践篇不需要关注原理,只需要把流程跑通就行,…

24年审计师报名时间汇总所需材料提前准备

2024审计师报名本周开始(5月10日起),各地报名时间不一,报名指南整理好了! ✅全国报名时间汇总报名费用资格审核:P1~P2。 ✅2024年审计师考试科目: 《审计相关基础知识》和《审计理论与实务》 ✅…

json-server的安装和使用

json-server介绍 json-server是可以把本地当做服务器,然后axios向本地区发送请求,并且不会出现跨域的问题,若是等不及后端数据,可以用这个模拟假数据 json-server安装及使用 【json-server网址】https://www.npmjs.com/package/…