Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
LED
RT-Thread
rt_device
RT-Thread 入门学习笔记:把LED抽象成rt_device来操作
发布于 2022-01-16 23:03:45 浏览:1934
订阅该版
[tocm] [RT-Thread 入门学习笔记 - 目录](https://club.rt-thread.org/ask/article/3420.html) ## 前言 - RT-Thread 的device框架,还是比较的实用的,可以用来对一些外设、模块进行【抽象】,这样底层驱动与上层应用可以降低耦合性。 - 默认RT-Thread的BSP工程,大部分都是一个流水灯控制,一般流水灯是通过GPIO引脚直接控制的。 - 这里使用rt_device的方法,把led注册成一个led device,通过device的API接口进行控制 ## 学习rt_device - rt_device 提供了较为通用的接口,可以实现对设备的初始化、读写、控制,当然,如果外设过于复杂,可以增加额外的ops,也就是可以自己定义一个device,继承rt_device。 - rt_device 主要的ops如下: ```c /* common device interface */ rt_err_t (*init) (rt_device_t dev); rt_err_t (*open) (rt_device_t dev, rt_uint16_t oflag); rt_err_t (*close) (rt_device_t dev); rt_size_t (*read) (rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size); rt_size_t (*write) (rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size); rt_err_t (*control)(rt_device_t dev, int cmd, void *args); ``` - 可以通过自定义的cmd,充分利用device的control,来实现对设备的管理,如开关、配置等操作 ## LED改为Device设备 - 验证平台:NUCLEO-L476RG 开发板(STM32L476RG) - LED : PA5引脚,高电平:亮 低电平:灭 - 抽象在软件设计中很有用,使用rt_device框架后,你会发现,上层应用可以与底层解耦,也就是上层应用只需要通过一个设备名称来访问控制设备,通过标准的device api 来操作设备,不用关心底层的改变。如果直接控制某个引脚,引脚改变后,应用就要一起更改。 - 使用框架的好处就是底层改变,上层不需要改变或只会很少的改变。 - 注册设备的代码如下: - `led_dev.c` : led设备注册 ```c #include "led_dev.h" #include "board.h" #define LED1_DEVICE_NAME "led1" /* defined the LED0 pin: PA5 */ #define LED0_PIN GET_PIN(A, 5) static struct rt_device _led_dev; static rt_err_t _led_init(rt_device_t dev) { rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT); return RT_EOK; } static rt_err_t _led_open(rt_device_t dev, rt_uint16_t oflag) { if (dev == RT_NULL) return -RT_ERROR; return RT_EOK; } static rt_err_t _led_close(rt_device_t dev) { if (dev == RT_NULL) return -RT_ERROR; return RT_EOK; } static rt_err_t _led_control(rt_device_t dev, int cmd, void *args) { if (dev == RT_NULL) return -RT_ERROR; switch (cmd) { case LED_CTRL_CMD_POWER_ON: rt_pin_write(LED0_PIN, PIN_HIGH); break; case LED_CTRL_CMD_POWER_OFF: rt_pin_write(LED0_PIN, PIN_LOW); break; default: break; } return RT_EOK; } #ifdef RT_USING_DEVICE_OPS const static struct rt_device_ops led_dev_ops = { _led_init, _led_open, _led_close, RT_NULL, RT_NULL, _led_control }; #endif static int led1_device_register(const char *name, void *user_data) { _led_dev.type = RT_Device_Class_Miscellaneous; _led_dev.rx_indicate = RT_NULL; _led_dev.tx_complete = RT_NULL; #ifdef RT_USING_DEVICE_OPS _led_dev.ops = &led_dev_ops; #else _led_dev.init = _led_init; _led_dev.open = _led_open; _led_dev.close = _led_close; _led_dev.read = RT_NULL; _led_dev.write = RT_NULL; _led_dev.control = _led_control; #endif _led_dev.user_data = user_data; /* register a character device */ rt_device_register(&_led_dev, name, RT_DEVICE_FLAG_RDWR); return 0; } int led1_device_init(void) { return led1_device_register(LED1_DEVICE_NAME, RT_NULL); } ``` - `led_dev.h` ```c #ifndef __LED_DEV_H__ #define __LED_DEV_H__ #include
#include
#define LED_CTRL_CMD_POWER_OFF 0x00 #define LED_CTRL_CMD_POWER_ON 0x01 int led1_device_init(void); #endif ``` - led1_app.c : led 设备应用接口 ```c #include "led1_app.h" #ifndef LED1_DEVICE_NAME #define LED1_DEVICE_NAME "led1" #endif static rt_device_t led1_dev = RT_NULL; static rt_device_t get_led1_dev(void) { if (led1_dev != RT_NULL) return led1_dev; led1_dev = rt_device_find(LED1_DEVICE_NAME); return led1_dev; } static rt_err_t led1_open(void) { rt_device_t dev = get_led1_dev(); if (dev == RT_NULL) return -RT_ERROR; return rt_device_open(dev, RT_DEVICE_FLAG_RDWR); } rt_err_t led_grn_init(void) { led1_device_init(); return led1_open(); } rt_err_t led_grn_power_on(void) { rt_device_t dev = get_led1_dev(); if (dev == RT_NULL) return -RT_ERROR; return rt_device_control(dev, LED_CTRL_CMD_POWER_ON, RT_NULL); } rt_err_t led_grn_power_off(void) { rt_device_t dev = get_led1_dev(); if (dev == RT_NULL) return -RT_ERROR; return rt_device_control(dev, LED_CTRL_CMD_POWER_OFF, RT_NULL); } ``` - led1_app.h ```c #ifndef __LED1_APP_H__ #define __LED1_APP_H__ #include "led_dev.h" rt_err_t led_grn_init(void); rt_err_t led_grn_power_on(void); rt_err_t led_grn_power_off(void); #endif ``` - main.c 初始化与功能验证 ```c #include
#include
#include
#include "drv_gpio.h" #include "key.h" #include "pms.h" #include "led1_app.h" int main(void) { key_gpio_init(); led_grn_init(); pms_task_init(); rt_thread_mdelay(1000); #ifdef RT_USING_PM rt_pm_module_delay_sleep(PM_POWER_ID, 10000); //rt_pm_module_release(PM_POWER_ID, PM_SLEEP_MODE_NONE); #endif while (1) { led_grn_power_on(); /* LED ON */ rt_thread_mdelay(500); led_grn_power_off(); /* LED OFF */ rt_thread_mdelay(500); } } ``` ## 运行效果 ```c msh > \ | / - RT - Thread Operating System / | \ 4.1.0 build Jan 16 2022 18:19:43 2006 - 2021 Copyright by rt-thread team [D/key] key_gpio_init. [D/key] PIN_KEY0=45 msh > msh > msh > msh >list_device device type ref count -------- -------------------- ---------- led1 Miscellaneous Device 1 /* 注册的设备 */ uart2 Character Device 2 pin Miscellaneous Device 0 msh > ``` ## 心得体会 - 注意rt_device设备,操作前先: `init` 或 `open` - 使用device的方式,发现代码量变多了,有点复杂,看上去不如直接控制引脚来的方便,但是后期维护很容易 - 使用device的方式,可以很容易的扩展到其他外设的控制,如喇叭、电机等 - 如果只是控制一个led,确实有点浪费,通过修改可以用来控制一组LED ## 小结 - 学习掌握rt_device的框架的使用,了解使用的目的是为了上层应用于底层驱动的解耦。 - 了解抽象在软件设计中的作用。
13
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
张世争
学以致用
文章
131
回答
809
被采纳
175
关注TA
发私信
相关文章
1
应用开发如何包含头文件
2
STM32F03RC跑RTT标准版 没有运行
3
为什么 Count 的值不连续和间隔为 7?
4
请求LED.C/H文件
5
RT-thread 如何被当做“单片机”,控制小灯的亮灭?
6
ART-PI Smart User 运行LED 程序崩溃
7
agile led软件包怎么使用
8
AT32F423开发板呼吸灯无作用,只有一个灯亮
9
RT-THREAD在STM32H747平台上移植lwip
10
正点原子miniSTM32开发板读写sdcard
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
UART
WIZnet_W5500
ota在线升级
freemodbus
PWM
flash
cubemx
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
flashDB
GD32
socket
中断
编译报错
Debug
SFUD
rt_mq_消息队列_msg_queue
msh
keil_MDK
ulog
C++_cpp
MicroPython
本月问答贡献
a1012112796
10
个答案
1
次被采纳
踩姑娘的小蘑菇
4
个答案
1
次被采纳
红枫
4
个答案
1
次被采纳
张世争
4
个答案
1
次被采纳
Ryan_CW
4
个答案
1
次被采纳
本月文章贡献
catcatbing
3
篇文章
5
次点赞
YZRD
2
篇文章
5
次点赞
qq1078249029
2
篇文章
2
次点赞
xnosky
2
篇文章
1
次点赞
Woshizhapuren
1
篇文章
5
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部