Linux驱动入门实验班——DAC模块驱动(附百问网视频链接)

news2024/11/15 10:59:29

目录

前言

一、 SPI数据结构

1.SPI设备驱动

2.SPI设备数据结构

二 、函数接口

1.spi_sync_transfer

2.spi_register_driver

 三、DAC

1.数据格式

2.数据结构

 四、源码

驱动

应用

课程链接


前言

在这里主要记录学习韦东山老师Linux驱动人入门实验班的笔记,韦东山老师的驱动课程讲的非常好,想要学习驱动的小伙伴可以去b站学习他的课程。

一、 SPI数据结构

1.SPI设备驱动

Linux中使用spi_driver结构体描述SPI设备驱动:

struct spi_driver {
    const char *name;  // 设备名称
    struct spi_device *spi;  // 对应的SPI设备
    int (*probe)(struct spi_device *spi);  // 设备探测函数
    int (*remove)(struct spi_device *spi);  // 设备移除函数
    int (*suspend)(struct spi_device *spi, pm_message_t state);  // 设备挂起函数
    int (*resume)(struct spi_device *spi);  // 设备恢复函数
    struct device_driver driver;  // 设备驱动结构体
};

2.SPI设备数据结构

Linux中使用spi_device结构体描述SPI设备,里面记录有设备的片选引脚、频率、挂在哪个SPI控制器下面:

spi_device是一个用于描述SPI设备的结构体。它包含了一些重要的字段,用于表示SPI设备的一些属性和配置信息。以下是spi_device结构体的一些常见字段:

  • bus:表示SPI设备所连接的SPI总线编号。
  • chip_select:表示SPI设备的片选信号编号,用于选择要与之通信的设备。
  • mode:表示SPI设备的工作模式,包括时钟极性、时钟相位等。
  • bits_per_word:表示每个传输字节的位数,通常为8位。
  • max_speed_hz:表示SPI设备的最大传输速度。
  • chip_select_active:表示SPI设备的片选信号的激活电平。
  • delay_between_messages_us:表示两个消息之间的延迟时间。

二 、函数接口

1.spi_sync_transfer

spi_sync_transfer是SPI接口的同步传输函数,用于在SPI设备上进行同步的数据传输。它的函数原型通常如下:

int spi_sync_transfer(struct spi_device *spi, 
            struct spi_transfer *transfers, int num_transfers);

该函数接收三个参数:

  • struct spi_device *spi:指向表示SPI设备的结构体的指针。该结构体包含有关SPI设备的信息,例如片选引脚、模式、时钟频率等。
  • struct spi_transfer *transfers:指向包含传输数据的spi_transfer结构体的数组的指针。每个spi_transfer结构体描述了一次SPI传输的参数,例如发送缓冲区、接收缓冲区、传输长度等。
  • int num_transfers:要执行的SPI传输的次数。

该函数的返回值为传输的结果,通常为负数表示出错,0表示成功完成传输。

在调用spi_sync_transfer函数时,它会顺序执行传输数组中的每个传输,完成后返回传输结果。如果需要进行多次传输,可以在transfers数组中添加多个spi_transfer结构体,并将num_transfers设置为传输的次数。

2.spi_register_driver

spi_register_driver函数用于在Linux内核中注册SPI驱动程序,以便将SPI设备与驱动程序关联起来。它的函数原型通常如下:

int spi_register_driver(struct spi_driver *driver);

该函数接收一个参数:

  • struct spi_driver *driver:指向表示SPI驱动程序的结构体的指针。该结构体包含有关驱动程序的信息和回调函数,例如设备匹配表、probe函数、remove函数等。

该函数的返回值为注册结果,通常为负数表示出错,0表示成功注册。

然后spi_unregister_driver就是反注册了。

 三、DAC

1.数据格式

由于 TLC5615 是 10 位 DAC,它允许主控每次发送 12 位或者 16 位的数据, 12 位和 16 位的发送数据格式要求如下图所示。

2.数据结构

spi_transfer结构体是用于表示SPI传输的数据结构,在Linux内核中使用以进行SPI设备的读写操作。它的定义如下:

struct spi_transfer {
    const void *tx_buf;
    void *rx_buf;
    unsigned int len;
    struct spi_message *spi;
    void *context;
    u64 timestamp;
    u32 speed_hz;
    u16 delay_usecs;
    u8 bits_per_word;
    u8 cs_change;
    u8 tx_nbits;
    u8 rx_nbits;
};

该结构体的成员说明如下:

  • const void *tx_buf:指向要发送的数据缓冲区的指针。
  • void *rx_buf:指向接收数据的缓冲区的指针。
  • unsigned int len:要传输的数据长度(以字节为单位)。
  • struct spi_message *spi:指向要执行传输的SPI消息的指针。
  • void *context:可以用于传递上下文信息的指针。
  • u64 timestamp:传输的时间戳。
  • u32 speed_hz:传输速度(以Hz为单位)。
  • u16 delay_usecs:传输之间的延迟时间(以微秒为单位)。
  • u8 bits_per_word:每个字的位数。
  • u8 cs_change:传输结束后是否保持片选(CS)信号的状态。
  • u8 tx_nbits:传输时发送的位数。
  • u8 rx_nbits:传输时接收的位数。

 使用前最好先将该结构体清零,将构造好的结构体使用spi_sync_transfer函数进行发送。

 四、源码

驱动

#include "asm/uaccess.h"
#include "linux/delay.h"

#include <linux/module.h>
#include <linux/poll.h>
#include "linux/i2c.h"
#include <linux/spi/spi.h>

#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
#include <linux/fcntl.h>
#include <linux/timer.h>

static int major;
static struct class *dac_class;
static struct spi_device *g_spi;

static ssize_t dac_drv_write (struct file *file, const char __user *buf, size_t size, loff_t *offset)
{
	unsigned short val;
	int err;
	unsigned char kernel_buf[2];

	struct spi_transfer t;
	memset(&t, 0, sizeof(t));

	if (size != 2)
	{
		return -EINVAL;
	}

	err = copy_from_user(&val, buf, 2);
	val <<= 2;
	val &= 0x0fff;

	kernel_buf[0] = val >> 8;
	kernel_buf[1] = val;

	t.tx_buf = kernel_buf;
	t.len = 2;

	err = spi_sync_transfer(g_spi, &t, 1);

	return err;
}

static struct file_operations dac_fops = {
	.owner = THIS_MODULE,
	.write = dac_drv_write,
};



static struct of_device_id spi_dt_match[] = {
	{.compatible = "spidev,dac"},
};

static int dac_drv_probe(struct spi_device *spi)
{
	// struct device_node *np = client->dev.of_node;

	/* 记录spi_device */
	g_spi = spi;

	/* 注册字符设备 */
	/* 注册file_operations 	*/
	major = register_chrdev(0, "100ask_spi", &dac_fops);  /* /dev/gpio_desc */

	dac_class = class_create(THIS_MODULE, "100ask_spi_class");
	if (IS_ERR(dac_class)) {
		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
		unregister_chrdev(major, "100ask_spi");
		return PTR_ERR(dac_class);
	}

	device_create(dac_class, NULL, MKDEV(major, 0), NULL, "myspi"); /* /dev/myspi */
	
	return 0;
}

static int dac_drv_remove(struct spi_device *spi)
{
	device_destroy(dac_class, MKDEV(major, 0));
	class_destroy(dac_class);
	unregister_chrdev(major, "dac_drv");

	return 0;
}

static struct spi_driver spi_dac_drive = {
	.driver = {
		.name = "my_spi_dac",
		.owner = THIS_MODULE,
		.of_match_table = spi_dt_match,
	},
	.probe = dac_drv_probe,
	.remove = dac_drv_remove,
};

static int __init dac_init(void)
{
	return spi_register_driver(&spi_dac_drive);
}

static void __exit dac_exit(void)
{
	spi_unregister_driver(&spi_dac_drive);
}

module_init(dac_init);
module_exit(dac_exit);

MODULE_LICENSE("GPL");



应用

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>

/*
 * dac_test /dev/mydac <val>
 */

int main(int argc, char **argv)
{
	int fd;
	int buf[2];
	unsigned short dac_val = 0;

	if (argc != 3)
	{
		printf("Usage: %s <dev> <val>\n", argv[0]);
		return -1;
	}
	
	fd = open(argv[1], O_RDWR);
	if (fd < 0)
	{
		printf(" can not open %s\n", argv[1]);
		return -1;
	}

	dac_val = strtoul(argv[2], NULL, 0);

//	while (1)
	{
		write(fd, &dac_val, 2);
		dac_val += 50;
	}
	
	return 0;
}

课程链接

百问网韦老师的liunx驱动入门实验班icon-default.png?t=N7T8https://video.100ask.net/p/t_pc/course_pc_detail/video/v_639436ffe4b0fc5d1213db21?product_id=p_634cbce4e4b00a4f37500252&content_app_id=&type=6

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

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

相关文章

计算机网络——HTTP与HTTPS协议

HTTP与HTTPS是应用层的协议。 目录 一、HTTP 二、HTTPS 三、HTTP与HTTPs对比 四、HTTP/1.0 HTT/1.1 HTTP/2有什么区别 五、HTTP常用请求方法&#xff1f;get/post区别&#xff1f; 六、HTTP的工作过程 七、HTTPS的工作过程 八、Cookie、Session、Token 一、HTTP 超…

【CAN总线测试】——CAN物理层测试

从0开始学习CANoe使用 从0开始学习车载测试 相信时间的力量 星光不负赶路者&#xff0c;时光不负有心人。 目录 1.最小通讯电压测试 2.最大通讯电压测试 3.显性位/隐性位输出电压测试 4.信号跳变沿测试 5.地偏移 6.终端电阻 1.7. CANH/CANL短路 1.8. CANH /GND短路 …

Verilog刷题笔记58

题目&#xff1a; Exams/2014 q3c 解题&#xff1a; module top_module (input clk,input [2:0] y,input x,output Y0,output z );parameter s03d000,s13d001,s23d010,s33d011,s43d100;always(*)begincase(y)s0:Y0x;s1:Y0~x;s2:Y0x;s3:Y0~x;s4:Y0~x;endcaseendassign z(y3b01…

Kafka运行机制(二):消息确认,消息日志的存储和回收,生产者消息分区

前置知识 Kafka基本概念https://blog.csdn.net/dxh9231028/article/details/141270920?spm1001.2014.3001.5501Kafka运行机制&#xff08;一&#xff09;&#xff1a;Kafka集群启动&#xff0c;controller选举&#xff0c;生产消费流程https://blog.csdn.net/dxh9231028/arti…

Verilog刷题笔记57

题目: Exams/2014 q3bfsm Given the state-assigned table shown below, implement the finite-state machine. Reset should reset the FSM to state 000. 解题&#xff1a; module top_module (input clk,input reset, // Synchronous resetinput x,output z );parameter…

ESP32-IDF 在 Ubuntu 下的配置

目录 一、安装准备二、获取 ESP-IDF三、设置工具四、使用案例 参考资料&#xff1a;官方文档&#xff1a;Linux 和 macOS 平台工具链的标准设置。 一、安装准备 参照官方文档&#xff0c;首先下载编译 ESP-IDF 所需要的软件包&#xff1a; sudo apt-get install git wget fl…

如何使用ssm实现基于Java的共享客栈管理系统

TOC ssm058基于Java的共享客栈管理系统jsp 第1章 绪论 1.1 课题背景 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。所以各…

一篇快速搞懂 JavaSE 高级特性(代码块,注解,枚举,异常处理,多线程,集合框架,泛型,反射,IO ......)

JavaSE 高级 一、面向对象&#xff08;高级&#xff09;1、单例模式&#xff08;Singleton&#xff09;2、代码块1&#xff09;静态代码块2&#xff09;非静态代码块 3、关键字 final4、抽象类与抽象方法&#xff08;abstract&#xff09;5、模板方法设计模式&#xff08;Templ…

利用GPT绘制流程图(无需下载任何软件

目录 什么是Flowchart Fun&#xff1f;如何利用GPT绘制流程图&#xff1f;步骤1&#xff1a;确定流程图的目的和内容步骤2&#xff1a;训练GPT编写流程图的文本描述步骤3&#xff1a;转换文本格式为可视化的流程图步骤4&#xff1a;调整和优化 结论小结&#xff1a; 什么是Flow…

SpringBoot【重修之HTTP协议】

request 请求&#xff0c;response 响应&#xff01; HTTP-协议的解析&#xff1a; 客户端&#xff1a;浏览器已经会自动解析了 服务端&#xff1a;通过Web服务器来解析&#xff01;【Tomcat , Jetty , WebLogic , WebSphere 】 Tomcat的研究学习 SpringBoot Web快速入门…

AIxBoard部署BLIP模型进行图文问答

一、AIxBoard简介 AIxBoard&#xff08;X板&#xff09;是一款IA架构的人工智能嵌入式开发板&#xff0c;体积小巧功能强大&#xff0c;可让您在图像分类、目标检测、分割和语音处理等应用中并行运行多个神经网络。它是一款面向专业创客、开发者的功能强大的小型计算机&#xf…

[Linux CMD] 查看系统资源 (持续更新中)

概述 在Linux中&#xff0c;有许多命令和工具可用于查看系统的资源使用情况。以下是一些常用的方式&#xff1a; top&#xff1a;top命令是最常见的实时系统监视工具之一。它显示了当前运行的进程列表&#xff0c;以及每个进程的CPU、内存使用情况、nice值等信息。top命令还会…

【Linux】简易日志工具项目

有些鸟儿是不应该被关在笼子里的&#xff0c; 因为他们的羽毛太丰润了。 当他们飞走&#xff0c;你会由衷地庆贺他获得自由。 --- 肖申克的救赎》--- 从零开始构建简易日志系统 1 日志1.1 什么是日志1.2 日志的意义1.3 为什么要构建自己的日志工具 2 构建自己的日志工具2.1…

带有限制编辑的PDF文件怎么取消编辑限制

在日常工作和学习中&#xff0c;我们经常会遇到一些带有“限制编辑”的PDF文件。这些文件由于设置了密码保护&#xff0c;使得我们无法直接编辑、复制或打印其中的内容&#xff0c;给信息的处理和利用带来了诸多不便。然而&#xff0c;通过一些有效的方法和工具&#xff0c;我们…

C++—八股文总结(25秋招期间一直更新)

1、const 1.1 指针常量和常量指针 说说const int *a, int const *a, const int a, int *const a, const int *const a分别是什么&#xff0c;有什么特点。 const int *aint const *a; //可以通过 a 访问整数值&#xff0c;但不能通过 a 修改该整数的值&#xff0c;指针本身是…

【AI赋能游戏】《黑神话:悟空》专属黑悟空无限创意生成器!(整合包分享)

最近最火的话题&#xff0c;肯定就是《黑神话&#xff1a;悟空》了&#xff01;这游戏实在是忒火火火了。。。全网破圈霸屏&#xff0c;连官媒央视都给了无死角宣传&#xff01; 《黑神话&#xff1a;悟空》登顶Steam历史售卖榜&#xff0c;同时在线玩家冲到了最高**222**万人&…

8.22-docker的部署及其使用

docker 1.docker环境部署以及语法 [rootdocker ~]# cat << EOF | tee /etc/modules-load.d/k8s.conf> overlay> br_netfilter> EOFoverlaybr_netfilter[rootdocker ~]# modprobe overlay[rootdocker ~]# modprobe br_netfilter[rootdocker ~]# cat /etc/module…

【个人学习】JVM(8): 对象的实例化、内存布局、访问定位

对象的实例化内存布局与访问定位 对象的实例化 对象创建的方式 new&#xff1a;最常见的方式、单例类中调用getInstance的静态类方法&#xff0c;XXXFactory的静态方法Class的newInstance方法&#xff1a;在JDK9里面被标记为过时的方法&#xff0c;因为只能调用空参构造器&am…

Ignition Gateway配置

Config-System backup和restore&#xff1a; backup可以直接备份整个gateway配置&#xff0c;包括所有项目。 restore可以恢复gateway配置&#xff0c;包括所有项目。

pytorch基础学习

环境安装 mac安装conda&#xff08;为什么安装conda? conda类似沙箱&#xff0c;将一个一个环境隔离起来&#xff0c;解决Python工程之前的包冲突问题&#xff09; 下载Miniconda安装器:https://docs.conda.io/en/latest/miniconda.html 执行dmg安装。 安装完成后&#xff0c…