官网文档的介绍有点笼统,正好最近公司在用RT_Thread,写下这篇博客,给有同样困惑的小伙伴,也给自己做参考。
全程干货,无废话,侧重实战,手把手教你怎么用Device!
一.介绍使用场景
此功能可令你的代码更加规范,更有可读性,同时方便写代码,后期维护。
如:你想要同时控制一个小车的两个电机,一个LED灯,一个舵机。
二.实战
应用层的Device代码会是这样:
rt_device_control(Motor1_dev, MOTOR_RUN, RT_NULL);
rt_device_control(Motor2_dev, MOTOR_RUN, RT_NULL);
rt_device_control(LED_dev, LED_OPEN, RT_NULL);
rt_device_control(Servo_dev, SERVO_RUN, RT_NULL);
(第二个参数是自己定义的宏定义,功能需要自己函数实现)
原型:
rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg);
那么,rt_device_control是如何找到你定义的Motor1,Motor2,LED和Servo设备呢?
首先我们需要进行初始化,进行引脚的配置。
以Motor1为例,其它三个设备同理,你的初始化代码会是这样:
static int Motor1_init_device(void)
{
struct motor_dev_init init; //定义一个初始化结构体,后面会讲到
init.motor_device_name = Motor1; //起一个名字
init.htim = &htim3; //结构体里找到初始化定时器的底层配置成员
init.htim_ch = TIM_CHANNEL_1;
init.Port_Pin_dir = GET_PIN(A, 8); //结构体里找到初始化IO引脚的底层配置成员
init.Port_Pin_en = GET_PIN(A, 7);
init.htim_freq = HAL_RCC_GetPCLK1Freq() * 2U / (htim3.Init.Prescaler + 1);
Motor_device_init(&init); //这个函数里调用rt_device_register
}
在Motor_device_init里调用rt_device_register函数:
if (rt_device_register(&Motor1_dev, Motor1, RT_DEVICE_FLAG_WRONLY) != RT_EOK)
{
LOG_E("can not register dev!"); //顺手写一个错误提示
}
原型如下:
rt_err_t rt_device_register(rt_device_t dev, const char* name, rt_uint8_t flags);
这一步完成了注册。
接下来我们看motor_dev_init内部的结构体实现
struct motor_dev_init
{
const char *motor_device_name;
TIM_HandleTypeDef *htim;
uint32_t htim_ch;
rt_base_t Port_Pin_en;
rt_base_t Port_Pin_dir;
uint32_t htim_freq;
}
初始化后,我们需要找到设备,用以下代码:
Motor1_dev = rt_device_find(Motor1);
//Motor1_dev是你实际rt_device_control里调用的名字
//Motor1是你初始化时用的名字
完成之后,rt_device_control就可以直接使用啦。