网上有很多关于pos机驱动教程,thread驱动框架分析的机教程知识,也有很多人为大家解答关于pos机驱动教程的驱动驱动问题,今天乐刷官方代理商(www.zypos.cn)为大家整理了关于这方面的框架知识,让我们一起来看下吧!
1、分析pos机驱动教程
struct rt_i2c_bit_ops{ void *data; void (*set_sda)(void *data, rt_int32_t state); void (*set_scl)(void *data, rt_int32_t state); rt_int32_t (*get_sda)(void *data); rt_int32_t (*get_scl)(void *data); void (*udelay)(rt_uint32_t us); rt_uint32_t delay_us; rt_uint32_t timeout;};
函数指针 功能 void (set_sda)(void data, rt_int32_t state) 设置SDA电平 void (set_scl)(void data, rt_int32_t state); 设置SCL电平 rt_int32_t (get_sda)(void data); 获取SDA电平 rt_int32_t (get_scl)(void data); 获取SCL电平 void (*udelay)(rt_uint32_t us); 软件I2C时序所需要的的延时函数
rt_i2c_bit_add_bus接口,主要注册软件I2C的引脚操作的回调函数。bit_opt层:可以归纳为驱动层。其主要实现软件I2C的时序等逻辑,并提供对应的I2C的收发处理函数,为drv_soft_i2c层提供提供了(struct rt_i2c_bit_ops)注册接口和(rt_i2c_bit_add_bus)接口,为i2c_core层提供主机模式的数据处理函数。bit_opt层主要对接到i2c_core层提供操作结构体:struct rt_i2c_bus_device_ops以及i2c总线的注册函数rt_i2c_bus_device_register:struct rt_i2c_bus_device_ops结构体:struct rt_i2c_bus_device_ops{ rt_size_t (*master_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); rt_size_t (*slave_xfer)(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num); rt_err_t (*i2c_bus_control)(struct rt_i2c_bus_device *bus, rt_uint32_t, rt_uint32_t);};
函数指针 功能 master_xfer 主机模式的数据收发 slave_xfer 从机模式的数据收发 i2c_bus_control i2c总线的的操作参数等设置
rt_i2c_bus_device_register接口:主要注册I2C总线和收发数据的回调函数。软件I2C驱动总结:rt-thread的软件I2C,如果要对接其他平台,只需要对接好结构体:struct rt_i2c_bit_ops。而软件I2C的逻辑完全不用理会,全部由bit_opt层管理。硬件I2C硬件I2C的层次图:drv_hw_i2c层:没有软件I2C的bit_opt层,而是直接对接i2c_core层提供的结构体:struct rt_i2c_bus_device_ops。作者为了简单说明,写了个例子(简单粗暴的例子):struct rt_i2c_bus_device i2c1_bus;I2C_HandleTypeDef hi2c1;static rt_err_t i2c_hw_Init(void){ hi2c1.Instance = I2C1; hi2c1.Init.ClockSpeed = 100000; hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; hi2c1.Init.OwnAddress1 = 0; hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; hi2c1.Init.OwnAddress2 = 0; hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; if (HAL_I2C_Init(&hi2c1) != HAL_OK) { Error_Handler(); } return RT_EOK;}static rt_size_t i2c_xfer(struct rt_i2c_bus_device *bus, struct rt_i2c_msg msgs[], rt_uint32_t num){ struct rt_i2c_msg *msg; rt_int32_t i, ret; for(i = 0; i< num; i++) { msg = &msgs[i]; if(msg->flags & RT_I2C_RD) { HAL_I2C_Master_Receive(&hi2c1, msg->addr, msg->buf, msg->len, 100); } else { HAL_I2C_Master_Transmit(&hi2c1, msg->addr, msg->buf, msg->len, 100); } } ret = i; return ret;}static const struct rt_i2c_bus_device_ops i2c_bus_ops ={ i2c_xfer, RT_NULL, RT_NULL};int rt_i2c_hw_init(void){ i2c_hw_init(); i2c1_bus.ops = &i2c_bus_ops; rt_i2c_bus_device_register(&i2c1_bus, "hw_i2c"); return RT_EOK;}INIT_DEVICE_EXPORT(rt_i2c_hw_init);以上硬件I2C对接,我只是对接了master_xfer。硬件I2C驱动总结:如果你是采用硬件I2C,那么就不需要去关乎bit_opt层,其实通过上面的描述,你不难理解bit_opt层和drv_hw_i2c层其实对接都是i2c_core层的结构。这也是我为什么把bit_opt层归纳为驱动层来讲解了。core 层:i2c_core层为驱动层提供结构体:struct rt_i2c_bus_device_ops。为设备层提供I2C的数据收发处理函数。其实i2c_core层主要是封装了一层API直接提供给用户层设备调用。
函数 说明 rt_i2c_bus_device_find 查找i2c总线 rt_i2c_transfer 主机模式的i2c数据传输 rt_i2c_master_send 主机模式的i2c数据发送 rt_i2c_master_recv 主机模式的i2c数据接受
其中rt_i2c_master_send函数和rt_i2c_master_recv函数是调用rt_i2c_transfer函数,而rt_i2c_transfer函数是调用master_xfer回调函数。如果你是使用这些接口,那么device层可以不用理会。device 层:i2c_dev层,对接rt-thread设备驱动框架。提供read,write,control函数。并通过函数rt_device_register注册到设备驱动框架。下面我也会使用这些接口来实现控制OLED。函数 说明 i2c_bus_device_read I2C读操作 i2c_bus_device_write I2C写操作 i2c_bus_device_control I2C总线的控制
软件I2C设计:关键代码, 注意软件I2C的地址需要偏移一位:struct rt_i2c_bus_device *i2c_bus;#define OLED_I2C_BUS_NAME "i2c1"#define OLED_ADDRESS 0x3cstatic rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data){ rt_uint8_t buf[2]; struct rt_i2c_msg msgs; buf[0] = reg; buf[1] = data; msgs.addr = OLED_ADDRESS; msgs.flags = RT_I2C_WR; msgs.buf = buf; msgs.len = 2; /@@* 调用I2C设备接口传输数据 */ rt_i2c_transfer(bus, &msgs, 1); return RT_EOK;}static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf){ struct rt_i2c_msg msgs; msgs.addr = OLED_ADDRESS; msgs.flags = RT_I2C_RD; msgs.buf = buf; msgs.len = len; /@@* 调用I2C设备接口传输数据 */ rt_i2c_transfer(bus, &msgs, 1); return RT_EOK;}int oled_init(void){ i2c_bus = rt_i2c_bus_device_find(OLED_I2C_BUS_NAME); if(i2c_bus == RT_NULL) { rt_kprintf("find i2c bus fail!\"); return RT_ERROR; } rt_kprintf("find i2c bus success!\"); ......}效果图:硬件I2C设计:关键代码,注意硬件I2C的地址不需要偏移:
struct rt_i2c_bus_device *i2c_bus;#define OLED_I2C_BUS_NAME "hw_i2c"#define OLED_ADDRESS 0x78static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t reg, rt_uint8_t data){ rt_uint8_t buf[2]; struct rt_i2c_msg msgs; buf[0] = reg; buf[1] = data; msgs.addr = OLED_ADDRESS; msgs.flags = RT_I2C_WR; msgs.buf = buf; msgs.len = 2; /@@* 调用I2C设备接口传输数据 */ rt_i2c_transfer(bus, &msgs, 1); return RT_EOK;}static rt_err_t read_regs(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *buf){ struct rt_i2c_msg msgs; msgs.addr = OLED_ADDRESS; msgs.flags = RT_I2C_RD; msgs.buf = buf; msgs.len = len; /@@* 调用I2C设备接口传输数据 */ rt_i2c_transfer(bus, &msgs, 1); return RT_EOK;}int oled_init(void){ i2c_bus = rt_i2c_bus_device_find(OLED_I2C_BUS_NAME); if(i2c_bus == RT_NULL) { rt_kprintf("find i2c bus fail!\"); return RT_ERROR; } rt_kprintf("find i2c bus success!\"); ......}使用驱动框架API实现:关键代码:
#define OLED_I2C_BUS_NAME "hw_i2c"struct rt_device *dev_i2c;#define OLED_ADDRESS 0x78static rt_err_t write_reg(struct rt_device *dev, rt_uint8_t reg, rt_uint8_t data){ rt_uint8_t buf[2]; rt_off_t pos; rt_uint16_t addr = OLED_ADDRESS; rt_uint16_t flags = RT_I2C_WR; buf[0] = reg; buf[1] = data; pos = (flags << 16) | addr; rt_device_write(dev, pos, buf, 2); return RT_EOK;}static rt_err_t read_regs(struct rt_device *dev, rt_uint8_t len, rt_uint8_t *buf){ rt_off_t pos; rt_uint16_t addr = OLED_ADDRESS; rt_uint16_t flags = RT_I2C_WR; pos = (flags << 16) | addr; rt_device_write(dev, pos, buf, 2); return RT_EOK;}int oled_init(void){ dev_i2c = rt_device_find(OLED_I2C_BUS_NAME); if(dev_i2c == RT_NULL) { rt_kprintf("find i2c bus fail!\"); return RT_ERROR; } rt_kprintf("find i2c bus success!\"); rt_device_open(dev_i2c, RT_DEVICE_OFLAG_RDWR); .... return RT_EOK;}总结有了I2C驱动框架,对于上层来说,不管硬件I2C还是软件I2C调用接口都是一样的。rt-thread为了方便,直接在核心层提供了一套API,这样用户层调用就更加方便。
以上就是关于pos机驱动教程,thread驱动框架分析的知识,后面我们会继续为大家整理关于pos机驱动教程的知识,希望能够帮助到大家!
相关文章: