imx6ull_SPI

news2024/11/17 16:01:40

SPI简介

SPI 是Motorola 公司推出的一种同步串行接口技术,是一种高速、全双工的同步通信总线。SPI 以主从方式工作,通常是有一个主设备和一个或多个从设备,一般SPI 需要4 根线,但是也可以使用三根线(单向传输)
这四根线如下:
①、CS/SS,Slave Select/Chip Select,这个是片选信号线,用于选择需要进行通信的从设备
I2C 主机是通过发送从机设备地址来选择需要进行通信的从机设备的,SPI 主机不需要发送从机
设备,直接将相应的从机设备片选信号拉低即可。

②、SCK,Serial Clock,串行时钟,和I2C 的SCL 一样,为SPI 通信提供时钟

③、MOSI/SDO,Master Out Slave In/Serial Data Output,简称主出从入信号线,这根数据线
只能用于主机向从机发送数据,也就是主机输出,从机输入。

④、MISO/SDI,Master In Slave Out/Serial Data Input,简称主入从出信号线,这根数据线只
能用户从机向主机发送数据,也就是主机输入,从机输出。
在这里插入图片描述

四种工作形式:通过串行时钟极性(CPOL)和相位(CPHA)的搭配

在这里插入图片描述
含义:CPOL:极性、CPHA:相位
如1:CPOL=1:高、CPHA=1:第二个相位。
高->低->高:第一个高->低为上升沿,第二个低->高·下降沿·
2:CPOL=1:高、CPHA=0:第一个相位。
高->低:第一个高->低为上升沿
①、CPOL=1,串行时钟空闲状态为高电平,CPHA=1,串行时钟的第二个跳变沿下降沿采集数据。
②、CPOL=1,串行时钟空闲状态为高电平,CPHA=0,串行时钟的第一个跳变沿下降沿采集数据。
③、CPOL=0,串行时钟空闲状态为低电平,CPHA=1,串行时钟的第二个跳变沿下降沿采集数据。
④、CPOL=0,串行时钟空闲状态为低电平,CPHA=0,串行时钟的第一个跳变沿上升沿采集数据。

SPI驱动

spi_imx.c

先找到spi_imx_driver, 这是imx在linux内核基础上写的

static struct platform_driver spi_imx_driver = {
	.driver = {
		   .name = DRIVER_NAME,
		   .of_match_table = spi_imx_dt_ids,//设备树中匹配
		   .pm = IMX_SPI_PM,
	},
	.id_table = spi_imx_devtype,//无设备树匹配
	.probe = spi_imx_probe,
	.remove = spi_imx_remove,
};

spi_imx_probe

static int spi_imx_probe(struct platform_device *pdev)
{
	struct device_node *np = pdev->dev.of_node;
	const struct of_device_id *of_id =
			of_match_device(spi_imx_dt_ids, &pdev->dev);
	struct spi_imx_master *mxc_platform_info =
			dev_get_platdata(&pdev->dev);
	struct spi_master *master;
	struct spi_imx_data *spi_imx;
	struct resource *res;
	int i, ret, num_cs, irq;

	if (!np && !mxc_platform_info) {
		dev_err(&pdev->dev, "can't get the platform data\n");
		return -EINVAL;
	}

	ret = of_property_read_u32(np, "fsl,spi-num-chipselects", &num_cs);
	if (ret < 0) {
		if (mxc_platform_info)
			num_cs = mxc_platform_info->num_chipselect;
		else
			return ret;
	}

	master = spi_alloc_master(&pdev->dev,
			sizeof(struct spi_imx_data) + sizeof(int) * num_cs);
	if (!master)
		return -ENOMEM;

	platform_set_drvdata(pdev, master);

	master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 32);
	master->bus_num = pdev->id;
	master->num_chipselect = num_cs;

	spi_imx = spi_master_get_devdata(master);
	spi_imx->bitbang.master = master;

	for (i = 0; i < master->num_chipselect; i++) {
		int cs_gpio = of_get_named_gpio(np, "cs-gpios", i);
		if (!gpio_is_valid(cs_gpio) && mxc_platform_info)
			cs_gpio = mxc_platform_info->chipselect[i];

		spi_imx->chipselect[i] = cs_gpio;
		if (!gpio_is_valid(cs_gpio))
			continue;

		ret = devm_gpio_request(&pdev->dev, spi_imx->chipselect[i],
					DRIVER_NAME);
		if (ret) {
			dev_err(&pdev->dev, "can't get cs gpios\n");
			goto out_master_put;
		}
	}

这上部分都是platform_device 的基本操作

下部分出现bitbang为关键,bitbang的作用是GPIO口模仿SPI模式,其他的为驱动正常操作

SPI发送:

spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;
		spi_imx->rx = spi_imx_buf_rx_u8;
		spi_imx->tx = spi_imx_buf_tx_u8;

spi_imx->bitbang.txrx_bufs = spi_imx_transfer;
bitbang下的txrx_bufs,函数为 spi_imx_transfer

spi_imx_transfer  
	->spi_imx_pio_transfer
		->spi_imx_push->spi_imx
			->tx(spi_imx);

SPI接收
中断函数接收数据

spi_imx_isr
	->spi_imx->rx(spi_imx);

bitbang启动

spi_bitbang_start(struct spi_bitbang *bitbang)
master->transfer_one_message = spi_bitbang_transfer_one;
spi_bitbang_transfer_one
	->bitbang->txrx_bufs(spi, t)=spi_imx_transfer
									->->tx(spi_imx)=spi_imx_buf_tx_u8

SPI设备驱动

发送

定义一个spi_transfer
对下面3个成员赋值

	struct spi_transfer t[] = {
		{
			.tx_buf = tx_buff,
			.rx_buf = rx_buff,
			.len = len,
	};

定义一个 spi_message

	spi_message_init(&spi_message);//初始化
	spi_message_add_tail(&spi_transfer , &spi_message);//将spi_transfer 打包进spi_message

选择设备,选择发送方式(同步,异步)
同步 :spi_sync(spi_device, &spi_message);
异步:spi_async(spi_device, &spi_message);

读和写只需要一个spi_transfer 就行了

tx_buf 放寄存器地址
rx_buf 写要存放信息的地址
t->len =1(发送的数据:寄存器大小)+len(读取的数据:此表示接收信息的大小)

	unsigned char txdata[1];
	struct spi_message m;
	struct spi_transfer *t;
	/* 一共发送len+1个字节的数据,第一个字节为
	寄存器首地址,一共要读取len个字节长度的数据,*/
	txdata[0] = reg | 0x80;		/* 写数据的时候首寄存器地址bit8要置1 */			
	t->tx_buf = txdata;			/* 要发送的数据 */
    t->rx_buf = rxdata;			/* 要读取的数据 */
	t->len = len+1;				/* t->len=发送的长度+读取的长度 */
	spi_message_init(&m);		/* 初始化spi_message */
	spi_message_add_tail(t, &m);/* 将spi_transfer添加到spi_message队列 */
	ret = spi_sync(spi, &m);	/* 同步发送 */

SPI选片都是软选,发送数据前的片选信号拉低都是在发送一段spi_message 前拉低,发完就拉高
,现在操作不像裸机

txdata =sizeof(char)+len,寄存器地址+要写入的内容

	unsigned char *txdata;
	struct spi_message m;
	struct spi_transfer *t;
	txdata = kzalloc(sizeof(char)+len, GFP_KERNEL);
	/* 一共发送len+1个字节的数据,第一个字节为
	寄存器首地址,len为要写入的寄存器的集合,*/
	*txdata = reg & ~0x80;	/* 写数据的时候首寄存器地址bit8要清零 */
    memcpy(txdata+1, buf, len);	/* 把len个寄存器拷贝到txdata里,等待发送 */
	t->tx_buf = txdata;			/* 要发送的数据 */
	t->len = len+1;				/* t->len=发送的长度+读取的长度 */
	spi_message_init(&m);		/* 初始化spi_message */
	spi_message_add_tail(t, &m);/* 将spi_transfer添加到spi_message队列 */
	ret = spi_sync(spi, &m);	/* 同步发送 */

读和写的 t->len = len+1; 这个1都是寄存器地址长度一个字节,len的长度为tx_buf+rx_buf ,tx_buf为寄存器地址

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

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

相关文章

torch函数合集

torch.tensor() 原型&#xff1a;torch.tensor(data, dtypeNone, deviceNone, requires_gradFalse) 功能&#xff1a;其中data可以是:list,tuple,NumPy,ndarray等其他类型,torch.tensor会从data中的数据部分做拷贝(而不是直接引用),根据原始数据类型生成相应类型的torch.Tenso…

RestTemplate Java调用restful接口

目录1. GET请求相关方法&#xff08;1&#xff09;getForObject&#xff08;2&#xff09;getForEntity2. POST请求相关设置请求头和请求体&#xff1a;HttpEntity&#xff08;1&#xff09;postForLocation&#xff08;2&#xff09;postForObject&#xff08;3&#xff09;po…

pyqt实现聊天机器人

环境要求 通过调用openai接口实现聊天机器人功能&#xff0c;支持各种参数得调整&#xff0c;文章末尾有各个参数得说明 python3.9pyqt5环境安装 pip install pyqt5 pip install openai pip install pyinstaller源码如下&#xff1a; chat.py import sys from PyQt5.QtWid…

Cortex-A7中断控制器GIC

Cortex-A7中断控制器GIC 中断号 芯片内部的中断都会引起IRQ InterruptGIC将所有的中断源(最多1020个中断ID)分为三类: SPI(SharedPeripheralInterrupt)共享中断&#xff0c;外部中断都属于SPI中断 [ID32-1019]PPI(PrivatePeripheralInterrupt)私有中断 [ID16-31]SGI(Software-…

【MySQL】基础操作:登录、访问、退出和卸载

一、MySQL简介 MySQL数据库最初是由瑞典MySQL AB公司开发&#xff0c;2008年1月16号被Sun公司收购。2009年&#xff0c;SUN又被Oracle收购。MySQL是目前IT行业最流行的开放源代码的数据库管理系统&#xff0c;同时它也是一个支持多线程、高并发、多用户的关系型数据库管理系统。…

亚马逊物流仓库配送延误,美国暴风雪造成损失严重!

美国拉响暴风雪警报&#xff0c;物流配送大面积延误 去年年底&#xff0c;美国的暴风雪给卖家带来的阴影还没有散去。在这本该春暖百花开的季节&#xff0c;暴风雪天气又回到了美国&#xff0c;这次的破坏力比去年年底的有过之而无不及。 当地2月22日&#xff0c;暴风雪在美国…

环境搭建01-Ubuntu16.04如何查看显卡信息及安装NVDIA显卡驱动

1. 查看显卡型号、驱动 ubuntu-drivers devices2. 安装NVIDIA显卡驱动 &#xff08;1&#xff09;验证是否禁用nouveau lsmod | grep nouveau若有输出&#xff0c;没有禁用&#xff0c;进行以下操作禁用。 sudo gedit /etc/modprobe.d/blacklist.conf在文件末尾中添加两条&…

从一个实例配置引入Prometheus的PromQL语法

1. PromQL介绍 PromQL提供对时间序列数据进行逻辑运算、过滤、聚合的支持。应用于数据查询、可视化、告警处理 2. 基本用法 2.1 查询时间序列 点击Prometheus图标,进行查询页面。可以点击地图图标查看有哪些metrics name。输入要查询的metrics name和过滤条件,然后点击执行…

数字逻辑基础:原码、反码、补码

时间紧、不理解可以只看这里的结论 正数的原码、反码、补码相同。等于真值对应的机器码。 负数的原码等于机器码&#xff0c;反码为原码的符号位不变&#xff0c;其余各位按位取反。补码为反码1。 三种码的出现是为了解决计算问题并简化电路结构。 在原码和反码中&#xff0c;存…

C语言 入门教程||C语言 指针||C语言 字符串

C语言 指针 学习 C 语言的指针既简单又有趣。通过指针&#xff0c;可以简化一些 C 编程任务的执行&#xff0c;还有一些任务&#xff0c;如动态内存分配&#xff0c;没有指针是无法执行的。所以&#xff0c;想要成为一名优秀的 C 程序员&#xff0c;学习指针是很有必要的。 …

湖北某灌区量测水监测系统-案例分享

应用背景湖北某灌区是当地主要的粮棉油产区&#xff0c;由于运行多年&#xff0c;渠系工程老化&#xff0c;阻水现象严重&#xff0c;造成了大量水资源浪费。该灌区2019年对渠道进行疏挖、清淤、衬砌&#xff0c;解决输水不畅等问题&#xff0c;2022年启动灌区续建配套与节水改…

Netty核心功能以及线程模型

目录 Netty核心功能以及线程模型 Netty初探 Netty的使用场景&#xff1a; Netty通讯示例 Netty线程模型 Netty模块组件 Netty核心功能以及线程模型 Netty初探 NIO 的类库和 API 繁杂&#xff0c; 使用麻烦&#xff1a; 需要熟练掌握Selector、 ServerSocketChannel、 So…

wepack4配置入门

一、 webpack 简介 1.1 webpack 是什么 webpack是一种前端资源构建工具&#xff0c;一个静态模块打包器(module bundler)。 在 webpack 看来, 前端的所有资源文件(js/json/css/img/less/...)都会作为模块处理。 它将根据模块的依赖关系进行静态分析&#xff0c;打包生成对应的…

机器学习100天(三十二):032 KD树的构造和搜索

机器学习100天,今天讲的是:KD树的构造和搜索! 《机器学习100天》完整目录:目录 在 K 近邻算法中,我们计算测试样本与所有训练样本的距离,类似于穷举法。如果数据量少的时候,算法运行时间没有大的影响,但是如果数据量很大,那么算法运行的时间就会很长。这在实际的应用…

GFD563A101 3BHE046836R0101

GFD563A101 3BHE046836R0101关于高端涂布机张力控制系统方案的介绍高端涂布机张力控制系统方案涂布机是将具有某种功效的胶&#xff0c;或者油墨类物质均匀粘连在塑料薄膜、铝箔、纺织品等表面的机械设备。本系统从放卷到收卷共采用七台变频器&#xff0c;其中收放卷采用闭环张…

Databend 开源周报第 81 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.com 。Whats New探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。Accepted RFCsrfc: 查询结果缓存…

Cartesi 举办的2023 黑客马拉松

Cartesi 是具有 Linux 运行时的特定于应用程序的Rollups执行层。Cartesi 的特定应用程序 Optimistic Rollup 框架使区块链堆栈足够强大&#xff0c;开发人员可以构建计算密集型和以前不可能的去中心化实例。Cartesi 的 RISC-V 虚拟机支持 Linux 运行时环境&#xff0c;允许像你…

DevOps 学习笔记(二)| 使用 Harbor

文章目录1. 上传镜像到 Harbor2. 拉取 Harbor 镜像3. 使用 Jenkins 操作 Harbor1. 上传镜像到 Harbor 首先在CI/CD 服务器中配置 Docker mkdir -p /etc/docker/ cd /etc/docker/ vim daemon.json其中的 IP 地址为Harbor 服务器的 IP 地址 {"xxx": "xxxx"…

IGH主站通信测试csp模式(DC同步 preemrt)连通一从站并实现控制

IGH主站通信测试 linuxcnc配置基础机器人控制LinuxCNC与EtherCAT介绍&&PDO&SDO&#xff0c;搭建环境步骤 需要配置IGH主站的查看这篇文章 linux系统学习笔记7——一次性安装igh-ethercat主站 CSP模式 DC同步方式 preemrt实时补丁 直接上代码&#xff0c;这…

YOLOV7模型调试记录

先前的YOLOv7模型是pytorch重构的&#xff0c;并非官方提供的源码&#xff0c;而在博主使用自己的数据集进行实验时发现效果并不理想&#xff0c;因此生怕是由于源码重构导致该问题&#xff0c;此外还需进行对比实验&#xff0c;因此便从官网上下载了源码&#xff0c;进行调试运…