用OLED屏幕播放视频(2): 为OLED屏幕开发I2C驱动

这篇具有很好参考价值的文章主要介绍了用OLED屏幕播放视频(2): 为OLED屏幕开发I2C驱动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

下面的系列文章记录了如何使用一块linux开发扳和一块OLED屏幕实现视频的播放:

  1. 项目介绍
  2. 为OLED屏幕开发I2C驱动
  3. 使用cuda编程加速视频处理

这是此系列文章的第2篇, 主要总结和记录一个I2C从设备的驱动, 在linux内核中如何实现, 如何给用户态的程序暴露合适的接口, 让用户态有机会操作真实的硬件设备. 可以通过下面的视频快速了解最终达到的效果和实现的总体思路.

跳转到6:48, 直接观看演示

1). I2C驱动架构

I2C总线是一种主从, 同步, 半双工的低速通信总线, 硬件标准可以参考这里. 这篇文章只讨论I2C总线上从设备的驱动在linux平台下如何实现, 下图是linux中I2C总线相关的软件模块, 其中i2c core提供给驱动开发人员重要的数据结构和接口函数:

用OLED屏幕播放视频(2): 为OLED屏幕开发I2C驱动

  • i2c_adapter: 表示总线上的主设备, 或者说总线控制器
  • i2c_algorithm: 当主设备想要通信时, 它负责具体硬件时序的实现, 比如, 在总线上产生开始/结束条件, 发送/接收数据
  • i2c_client: 表示总线上的从设备
  • i2c_driver: 表示从设备对应的驱动, 需要实现其中的接口函数之后, 把驱动注册到i2c core之中
  • i2c_add_driver: 注册i2c_driver到i2c core, 一般在模块初始化函数中调用
  • i2c_del_driver: 删除i2c_driver, 一般在模块退出函数中调用
  • i2c_master_send/recv: 主设备发送/接收数据, 实际上为了驱动从设备, 需要让主设备向从设备发送合适的命令, 或者读取从设备的状态, 具体发送或者接收什么, 参考从设备的datasheet即可

2). 实现ssd1306屏幕的I2C驱动

  1. 注册i2c_driver
    使用module_i2c_driver宏, 并传递我们实现的i2c_driver, 该宏能够为我们生成模块的init和exit函数, 在函数中自动注册和删除传递进来的i2c_driver. 如果需要在init和exit中做一些其他工作, 则需要自己实现, 不能使用这个宏.
module_i2c_driver(ssd130x_driver);
  1. 实现i2c_driver中的接口
static struct i2c_driver ssd130x_driver = {
    .driver = {
        .owner = THIS_MODULE,
        .name = "ssd130x_driver",
    },
    .probe = ssd130x_probe,
    .remove = ssd130x_remove,
    .id_table = ssd130x_id_table,
};

这里只实现了i2c_driver中的probe和remove. 当驱动和设备匹配成功时, probe函数被调用, 在probe函数中, 完成了字符设备的相关的操作, 包括:

  • 分配设备号
  • 初始化字符设备结构体
  • 添加字符设备到内核
  • 创建设备文件
  1. 实现字符设备接口, 暴露给用户态程序
static struct file_operations ssd130x_fops = {
	.owner = THIS_MODULE,
	.open = ssd130x_open,
	.release = ssd130x_close,
	.write = ssd130x_write,
};

用户态程序可以对设备文件进行打开, 关闭, 写入3种操作. 当打开设备文件时, ssd130x_open被调用, 完成OLED屏幕的初始化; 关闭设备文件时, ssd130x_close被调用, 屏幕被关闭; 当向设备文件写入数据时, ssd130x_write被调用, 一帧数据被发送到ssd1306的RAM上, 屏幕显示的内容被更新. 以上3种操作, 底层都是通过i2c_master_send向从设备发送特定的命令或者数据实现的.

2.1). 阅读数据手册

ssd1306的数据手册参考这里, 手册内容较多, 不宜通读, 主要关注以下几点:

  • 基本硬件参数: 屏幕分辨率, 支持的通信接口, 支持哪些显示相关的功能(比如滚动, 反转等) ...
  • 基本工作原理: 通过向RAM中写入数据, 控制屏幕像素点的亮灭
  • 基本使用方法: 支持哪些命令? 分别能控制它的什么功能?
  • Application Note: 典型硬件电路, 示例代码

2.2). 设备的初始化

在数据手册的Application Note中包含使用ssd1306时的初始化流程, 如下图所示. 在此基础上, 可以做一些调整, 比如我在驱动中关闭了屏幕滚动.

用OLED屏幕播放视频(2): 为OLED屏幕开发I2C驱动

2.3). 调整I2C的频率

我在beaglebone black板子上刷入的debian系统, 其设备树中的i2c时钟频率是100kbits/s, 内核中的i2c_algorithm会根据这个频率计算在i2c总线上发送数据时使用的延时. 实际测试之后发现按照这个频率播放视频存在一些卡顿, 因此需要对i2c时钟频率做修改, 有两种方式:

  • 在uboot启动时, 进入uboot的shell, 使用fdt相关的命令修改始终频率
  • 备份原来的设备树文件, 使用dtc编译器从dtb得到dts, 在dts中修改始终频率, 再编译得到新的dtb, 替换原来的设备树文件

我这里采用的是dtc的方式, 这样就不需要每次系统启动都手动修改了, 修改之后的时钟频率为400kbits/s, 播放视频流畅很多.

3). 测试驱动功能

驱动代码编写完成之后, 需要实际测试一下功能, 下面代码首先打开OLED屏幕的设备文件, 写入一帧数据, 每个字节都填充为0x88, 这样屏幕上会显示出预期的条纹, sleep两秒之后, 关闭设备文件, 屏幕熄灭.

#define FRAME_SIZE (128 * 8)

int main(int argc, char **argv)
{
	int device_fd = open("/dev/ssd130x0", O_WRONLY);
	if (device_fd < 0) {
		return -1;
	}

	char *frame = malloc(FRAME_SIZE);
	memset(frame, 0x88, FRAME_SIZE);
	write(device_fd, frame, FRAME_SIZE);
	sleep(2);

	free(frame);
	close(device_fd);
	return 0;
}

4). 文末推广

欢迎关注我的B站账号, 或者加入QQ群838923389, 一起研究计算机底层技术, 一起搞事情:P

其实还有很多实现的细节没有在博客中写出来, 只有自己在做的时候遇到了才能够体会的到, 需要完整代码的老铁直接在qq群中问一下.文章来源地址https://www.toymoban.com/news/detail-704057.html

到了这里,关于用OLED屏幕播放视频(2): 为OLED屏幕开发I2C驱动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32配合cubeMX硬件I2C驱动0.96寸OLED

    目录 一、简单介绍 1.1   OLED 1.2   I2C协议 二、实战 2.1 工程配置 2.2 测试工程 2.3 波形分析 三、驱动OLED 3.1 初始化代码 3.2 清屏函数 3.3 设置坐标函数 3.4 显示字符函数 3.5 显示字符串函数 3.6 显示图片函数 附录 驱动代码文件 oled.c oled.h f6x8.h 有机发光二极管 (英语:Organic

    2024年02月08日
    浏览(52)
  • 1.3寸OLED模块初始化,驱动芯片为SH1106,i2c通讯

    之前使用过0.96寸的OLED,驱动芯片SSD1306,看了下两个芯片数据手册,差异不是很大,买了一个1.3寸的,花了一个下午点亮了,在过程中遇到了些问题,网上的资料不多,于是做个总结。 主要遇到的问题有, 1.显示不正常,出现花屏等现象。 从我遇到的情况来说,出现花屏可

    2024年02月12日
    浏览(34)
  • MSP430学习笔记(四)丨I2C通信(MSP430F5529驱动OLED显示屏)

    ​  笔者学习采用单片机型号为MSP430F5529,使用MSP-EXP430F5529LP开发板。 ​  笔者拥有一定的STM32基础,在学习MSP430的过程中,最开始苦于没有合适的OLED显示驱动代码,所以花了很多时间钻研。综合网上的各种代码,笔者认为江协科技的STM32课程中提供的OLED代码使用方便,

    2024年02月16日
    浏览(43)
  • [RISC-V]Milk-V开发板 i2c测试oled及波形输出

    引脚图 修改i2c3复用功能 buildboardscv180xcv1800b_sophpi_duo_sdu-bootcvi_board_init.c 扫描I2C3上的设备 [root@cvitek]~# i2cdetect -y -r 3 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: – – – – – – – – – – – – – 10: – – – – – – – – – – – – – – – – 20: – – – – – – – – – – – –

    2024年02月12日
    浏览(40)
  • STM32F103C8T6—库函数应用I2C/SPI驱动OLED显示中文、字符串

    I2C(Inter-Integrated Circuit) SPI(Serial Peripheral Interface) 传输方式 半双工 全双工 传输速度 低速,100Kbps----4Mbps 高速,30Mbps以上 几线制 4线制:VCC,GND,SCL,SDA 6/7线制:VCC,GND,SCLK(D0),MOSI(D1/SDA),DC,CS/SS 主从模式 多主机总线,通过SDA上的地址信息锁定从机 只有一个主机,主

    2024年02月02日
    浏览(50)
  • QEMU学习(五):I2C设备仿真及驱动开发

            I2C 是很常用的一个串行通信接口,用于连接各种外设、传感器等器件, 本章我们来学习一下如何在QEMU里仿真I2C设备及 Linux 下开发 I2C 接口器件驱动。 下面是标准的设备添加结构,我们使用的是常见的at_24c系列设备来做I2C的通信,详细代码请看qemuhwnvrameeprom_

    2024年02月08日
    浏览(84)
  • Linux驱动开发(I2C系统的重要结构体)

    本篇文章来讲解I2C系统的重要结构体,了解这些结构体对于编写I2C驱动来说是至关重要的,所以要想编写好一个I2C驱动程序那么就必须先了解这些结构体。 这里使用百问网的一张图片来讲解: 一个芯片中可以有多个I2C控制器,并且一个I2C控制器可以控制多个设备。那么在对

    2024年02月07日
    浏览(40)
  • Linux驱动开发之i2c框架讲解到例程

            本篇章在rk3399平台上,基于设备树的i2c驱动开发。i2c直接使用硬件i2c总线,体系结构分为3部分:I2C 核心、I2C 总线驱动和I2C 设备驱动。 I2C 核心 (i2c-core.c)提供了I2C 总线驱动和设备驱动的注册、注销方法等。我们主要了解Linux中i2c的基本框架,分为 i2c主机驱动开发

    2024年02月02日
    浏览(36)
  • linux i2c驱动开发之最简单入门:设备树与驱动的匹配

    1在设备树中声明我们的模拟I2C设备: i2c的设备加入是必须放在某个i2c的总线下面的,我们这里是放在 i2c7下面。 可以直接在设备树搜索i2c7,然后把status 修改为okay,然后再加入设备信息. 这里我们指定和驱动匹配的字符串是 myi2c-dev,在bus segment 上分配的地址是 0x70 。 当然这

    2024年02月16日
    浏览(39)
  • Linux设备驱动开发学习笔记(等待队列,锁,字符驱动程序,设备树,i2C...)

    container_of函数可以通过结构体的成员变量检索出整个结构体 函数原型: 内核开发者只实现了循环双链表,因为这个结构能够实现FIFO和LIFO,并且内核开发者要保持最少代码。 为了支持链表,代码中要添加的头文件是linux/list.h。内核中链表实现核心部分的数据结构 是struct li

    2024年01月22日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包