当前位置: 首页> 教育> 就业 > 泰安齐鲁人才网最新招聘网_seo整站如何优化_百度企业_网站关键词优化方法

泰安齐鲁人才网最新招聘网_seo整站如何优化_百度企业_网站关键词优化方法

时间:2025/7/15 23:52:05来源:https://blog.csdn.net/BeiJingXunWei/article/details/144290529 浏览次数:0次
泰安齐鲁人才网最新招聘网_seo整站如何优化_百度企业_网站关键词优化方法

iTOP-4412全能版采用四核Cortex-A9,主频为1.4GHz-1.6GHz,配备S5M8767 电源管理,集成USB HUB,选用高品质板对板连接器稳定可靠,大厂生产,做工精良。接口一应俱全,开发更简单,搭载全网通4G、支持WIFI、蓝牙、陀螺仪、CAN总线、RS485总线、500万摄像头等模块,稳定运行Android 4.0.3/Android 4.4操作,系统通用Linux-3.0.15+Qt操作系统(QT支持5.7版本),Ubuntu版本:12.04,接口智能分配 方便好用。


第六十四章 Linux-SPI驱动实验

SPI 和 I2C 一样,也是一个很常用的通信接口,大多数用于芯片之间的通信,同 I2C 相比,SPI 接口拥有更快的速度,速度可达十几 MHz。SPI 全程 SerialPerripheral Interface,是 Motorola 公司推出的一种同步串行接口技术,是一种高速、全双工的同步通信总线。标准的 SPI 需要四根线,分别是 CS/SS 片选信号,用于选择进行通信的设备,SCK 串行时钟线,用于为 SPI 提供时钟,MOSI 主出从入信号线,用于主机像从机发送数据,MISO 主入从出信号线,用于从机向主机发送数据。

在进行 SPI 实验之前,我们要先明确主机驱动和外设驱动分离思想,SPI 的驱动架构可以分为如下三个层次:SPI 核心层、SPI 控制器驱动层和 SPI 设备驱动层。

64.1 SPI核心层

SPI 核心层是 Linux 的 SPI 核心部分,提供了核心数据结构的定义、SPI 控制器驱动和设备驱动的注册、注销管理等 API。其为硬件平台无关层,向下屏蔽了物理总线控制器的差 异,定义了统一的访问策略和接口;其向上提供了统一的接口,以便 SPI 设备驱动通过总线控制器进行数据收发。Linux 中,SPI 核心层的代码位于 driver/spi/ spi.c。

64.2 SPI控制器驱动层

SPI 控制器驱动层,每种处理器平台都有自己的控制器驱动,属于平台移植相关层。它的职责是为系统中每条 SPI 总线实现相应的读写方法。在物理上,每个 SPI 控制器可以连接若干个 SPI 从设备。

控制器驱动可以用数据结构struct spi_master 来描述,如下图所示:

struct spi_master {
struct device	dev;
s16 bud_num;
u16 num_chipselect;
int (*setup)(struct spi_device *spi);
int (*transfer)(struct spi_device *spi, struct spi_message *mesg);
void (*cleanup)(struct spi_device *spi);
};

bus_num 为该控制器对应的 SPI 总线号。

num_chipselect 控制器支持的片选数量,即能支持多少个 spi 设备

setup 函数是设置 SPI 总线的模式,时钟等的初始化函数, 针对设备设置 SPI 的工作时钟及数据传输模式等。在 spi_add_device 函数中调用。

transfer 函数是实现 SPI 总线读写方法的函数。实现数据的双向传输,可能会睡眠cleanup 注销的时候调用

64.3 SPI设备驱动层

SPI 设备驱动层为用户接口层,其为用户提供了通过 SPI 总线访问具体设备的接口。 SPI 设备驱动层可以用两个模块来描述,struct spi_driver 和 struct spi_device。

struct spi_driver 用来描述一个 SPI 设备的驱动信息,Driver 是为 device 服务的spi_driver 注册时会扫描 SPI bus 上的设备,进行驱动和设备的绑定,probe 函数用于驱动和设备匹配时被调用。

struct spi_driver {
int (*probe)(struct spi_device *spi);
int (*remove)(struct spi_device *spi);
void (*shutdown)(struct spi_device *spi);
int (*suspend)(struct spi_device *spi, pm_message_t mesg);
int (*resume)(struct spi_device *spi);
struct device_driver driver;
};

struct spi_device 用来描述一个 SPI 总线上的从设备,如下图所示:

struct spi_device {
struct device dev;
struct spi_master	*master;
u32 max_speed_hz;
u8 chip_select
u8 mode;
u8 bits_per_word;
int irq;
void *controller_state;
void *controller_data;
char modalias[32];
};

通常来说 spi_device 对应着 SPI 总线上某个特定的 slave。并且 spi_device 封装了一个 spi_master 结构体。spi_device 结构体包含了私有的特定的 slave 设备特性,包括它最大的频率,片选那个,输入输出模式。

64.4 RFID-RC522 简介

在 SPI 实验送,我们使用的为 RC522 芯片,RC522 主要应用于非接触通信中高度集成度的读写,并且利用了先进的调制和解调的概念,集成了在 13.56MHz 下所有类型的被动非接触式通信方式和协议。RFID 的应用范围也是非常广泛的,如公共交通终端,非接触式的公用电话等,并且可以通过 SPI 接口简单的几条线就可以直接和我们的主板进行通信。

64.5 硬件原理分析

下图为 RFID 接口的原理图,其中 SDA 为数据接口,这里接 CS 片选信号,SCK 为时钟接口,这里我们要接 SPI 的时钟信号,MOSI 为出从入信号线,MISO 为主入从出信号线,RST 为复位信号。

 

64.6 实验操作

SPI 试验中我们需要用到以下函数。

设备注册:spi_board_info,spi_register_board_info

驱动注册函数和结构体:spi_register_driver/spi_unregister_driver,spi_driver

读写函数和结构体:spi_transfer 和 spi_message 结构体,spi_async

第一步:描述 spi_device 的板信息,用 spi_board_info 结构体来描述

spi2_board_info 设备描述结构体,设备注册函数 spi_register_board_info 而这个info 在 init 函数调用的时候会初始化:

spi_register_board_info(s3c_spi_devs,ARRAY_SIZE(s3c_spi_devs));//注册 spi_board_info。

这个代码会把 spi_board_info 注册到链表 board_list 上。spi_device 封装了一个spi_master 结构体,事实上 spi_master 的注册会在 spi_register_board_info 之后, spi_master 注册的过程中会调用 scan_boardinfo 扫描 board_list,找到挂接在它上面的 spi 设备,然后创建并注册 spi_device。至此 spi_device 就构建并注册完成了。

第二步:spi_driver 的构建与注册 

static struct spi_driver	m25p80_driver = {
.driver = {
.name	="rc522",
.bus	=&spi_bus_type,
.owner = THIS_MODULE,
},
.probe	= rc522_probe,
.remove = devexit_p(rc522_remove),
};

spi_transfer 结构:

struct spi_transfer {
const void*tx_buf;	//驱动提供的发送缓冲区 
dma, void *rx_buf;	//接收缓冲区
unsigned len;	//长度一般是 8 位
dma_addr_ttx_dma;		//发送 dma,controller 使用
dma_addr_t rx_dma;	//接收 dma
unsigned cs_change:1;	//片选位
u8 bits_per_word;	//每字长度
u16 delay_usecs; //延迟
u32 speed_hz; //速度
struct list_headtransfer_list;	//transfer 链 表
};

在 spi_transfer 中时常更改的域也许只有 len,tx_buf 和 rx_buf。剩下的当以 0 来初始化。

spi_message 结构:

struct spi_message {
struct list_head transfers; 
struct spi_device *spi; unsigned is_dma_mapped:1;
void (*complete)(void*context);
void *context;
unsigned actual_length; 
int status;
struct list_head queue; 
void *state;
};

transfer 这个 spi_message 所包含有的 spi_transfer 链表头。

is_dma_mappedspi_transfer 中 tx_dma 和 rx_dma 是否已经 mapped。

complete 回调函数

context 提供给 complete 的可选参数

actual_lengthspi_message 已经传输了的字节数

status 出错与否,错误时返回 errorcode

queue 和 state 供 controller 驱动内部使用

在每次使用 spi_message 可以使用函数 void spi_message_init(structspi_message *m);来初始化。

向 spi_message 添加 transfers 可以使用 spi_message_add_tail()函数:

void spi_message_add_tail(structspi_transfer *t, struct spi_message *m);

一旦你准备好了 spi_message,就可以使用 spi_async()来向 SPI 系统提交了:

int spi_async(struct spi_device *spi,struct spi_message *message);

因为是异步的,一提交就立马返回了,这也就是说需要同步机制(complete 就是了)。他确保不会睡眠,可安全的在中断 handler 或其他不可休眠的代码中调用。稍后会念念他的好的。

使用 spi_async()需要注意的是,在 complete()未返回前不要轻易访问你一提交的spi_transfer 中的 buffer。也不能释放 SPI 系统正在使用的 buffer。一旦你的 complete 返回了,这些 buffer 就又是你的了

关键字:泰安齐鲁人才网最新招聘网_seo整站如何优化_百度企业_网站关键词优化方法

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: