导航:首页 > 操作系统 > linuxspi读写

linuxspi读写

发布时间:2022-10-10 10:35:59

linux自带的SPI驱动,默认情况下是以什么方式读取数据的

一位一位来传输数据的。如果只是要在linux上开发应用,可以不去理会具体的SPI驱动细节。
可以在linux中写个简单的程序,只完成读spi并在屏幕输出的功能,不要涉及编写驱动的部分。

㈡ linux spi 应用程序。

你所指的spidev.c是SPI的用户模式设备接口的驱动,可以通过应用程序去操作/dev/spidev*达到与硬件设备的SPI通信,对于操作SPI NOR FLASH,更多是注册为MTD设备,详细可参考drivers/mtd/device/m25p80.c,里面已经有相关实现。
但无论如何,前提是你的内核里已经有SPI控制器的驱动,否则如何通信呢。代码一般在drivers/spi/里。
那是应该是给spi设备驱动范本吧,可以籍此写自己的spi设备驱动,没有设备节点就自己创建个嘛。或者在驱动中添加创建设备节点的函数。

㈢ linux下的SPI使用方法是怎样的

如果linux中已经提供了驱动,并且在/dev/目录下已经提供了相应的设备文件节点。那么可以和串口一样直接打开设置读写。如果内核中有驱动,但是没有生成设备文件节点,那么只要知道设备的主次设备号,可以使用mknode建立设备文件节点,然后直接来使用。如果没有驱动就需要自己添加设备驱动了。这个也分两种情况,看你外设怎么和你的板子连接的。如果接到板子上的spi控制器上,可以直接编写通过控制器来控制外设的驱动,这种情况一般生产主控芯片的厂家都已经提供了驱动。如果没有接到spi控制器上,而是通过gpio连接的外设,你编写的驱动就需要自己来模拟spi协议来控制外设。

㈣ 怎么写linux的spi设备驱动

回复
1#
我也是新手,不过调通了SPI,
在SPI
驱动里面是分为
设备
总线
驱动的。。这个你要搞清楚。你所说的几个文件就是在这个层次关系里面的代码,如果你只是简单的使用SPI,内核自带的spidev.c就已经能够满足要求了。。我就这么用的。。。你可以参照内核里面的例程来分析分析。
另外,你也可以试着写一个裸驱试试。。。

㈤ spi是通过什么判断是读还是写

void SpiWriteRegister (uchar reg,uchar value)
{
\x05RF_NSEL = 0; // 片选拉低启动SPI通讯
\x05SPI0DAT = (reg|0x80); // 写入1个字节的寄存器地址
\x05while( SPIF == 0);\x05\x05 // 等待SPI传输完成
\x05SPIF = 0;
\x05SPI0DAT = value; // 继续写入第二个字节(寄存器值)
\x05while( SPIF == 0);\x05 // 等待SPI传输完成
\x05SPIF = 0;\x05
\x05RF_NSEL = 1; // 片选拉高结束SPI通讯
}
//-----------------------------------------------------------------------------
//函数描述:SPI读取函数
//相关参数:
//返回信息:
//
//-----------------------------------------------------------------------------
uchar SpiReadRegister (uchar reg)
{
\x05RF_NSEL = 0; // 片选拉低启动SPI通讯
\x05SPI0DAT = reg;\x05\x05\x05 // 写入1个字节的寄存器地址
\x05while( SPIF == 0);\x05\x05 // 等待SPI传输完成
\x05SPIF = 0;
\x05SPI0DAT = 0xFF;\x05\x05\x05 // 写一个Dummy字节(因为要读取的话必须用写入来启动一个交换数据的传输),当写入完成后从机的数据也完成了读入.
\x05while( SPIF == 0);\x05\x05 // 等待SPI传输完成\x05\x05\x05\x05
\x05SPIF = 0;
\x05RF_NSEL = 1; // 片选拉高结束SPI通讯 \x05
\x05return SPI0DAT; // 返回读取的值(在SPI0DAT=0xFF中完成读取)
}
需要注意的是读写操作实际上完成的都是数据的交换,即主机传送1个字节给从机,从机同时传送1个字节给主机.所以读操作看起来像是写数据,但实际上写入完成后就可以从SPI0DAT中获得从机的应答数据了.

㈥ linux下spi驱动里的spi_write_then_read函数该怎么使用

水平不行,不一定对,仅供参考哈。
如果只是从AD里读数据的话,用spi_read就可以了,定义一个8位的缓冲区和一个16位的缓冲区。然后把读到的2个8bit的数据组合成1个16bit的数据。每次读到的数据量通过该函数的参数设定。
如果是想实现全双工,可以使用spi_write_then_read
读是一样的,写的话自己先把16位数据转换成2个8bit的数据,存放在一个8bit的缓冲区,作为该函数的参数。

㈦ 帮忙分析一个这个spi读写程序,详细一点的,解释一下。怎么觉得读和写的内容怎么差不多呢,怎么实现的读写

void SpiWriteRegister (uchar reg, uchar value)
{
RF_NSEL = 0; // 片选拉低启动SPI通讯
SPI0DAT = (reg|0x80); // 写入1个字节的寄存器地址
while( SPIF == 0); // 等待SPI传输完成
SPIF = 0;
SPI0DAT = value; // 继续写入第二个字节(寄存器值)
while( SPIF == 0); // 等待SPI传输完成
SPIF = 0;
RF_NSEL = 1; // 片选拉高结束SPI通讯
}

//-----------------------------------------------------------------------------
//函数描述: SPI读取函数
//相关参数:
//返回信息:
//
//-----------------------------------------------------------------------------
uchar SpiReadRegister (uchar reg)
{
RF_NSEL = 0; // 片选拉低启动SPI通讯
SPI0DAT = reg; // 写入1个字节的寄存器地址
while( SPIF == 0); // 等待SPI传输完成
SPIF = 0;
SPI0DAT = 0xFF; // 写一个Dummy字节(因为要读取的话必须用写入来启动一个交换数据的传输),当写入完成后从机的数据也完成了读入。
while( SPIF == 0); // 等待SPI传输完成
SPIF = 0;
RF_NSEL = 1; // 片选拉高结束SPI通讯
return SPI0DAT; // 返回读取的值(在SPI0DAT=0xFF中完成读取)
}

需要注意的是读写操作实际上完成的都是数据的交换,即主机传送1个字节给从机,从机同时传送1个字节给主机。所以读操作看起来像是写数据,但实际上写入完成后就可以从SPI0DAT中获得从机的应答数据了。

㈧ linux spi设备驱动中probe函数何时被调用

这两天被设备文件快搞疯了,也怪自己学东西一知半解吧,弄了几天总算能把设备注册理清楚一点点了。就以spi子设备的注册为例总结一下,免得自己忘记。
首先以注册一个spidev的设备为例:
static struct spi_board_info imx5_spi_printer_device[] __initdata =
{
{
.modalias = "spidev",
.max_speed_hz = 8000000,
.bus_num = 1,
.chip_select = 1,
.mode = SPI_MODE_0,
},
};
spi_register_board_info(imx5_spi_printer_device,ARRAY_SIZE(imx5_spi_printer_device));

在mx5_loco.c文件中添加上面结构体spi_board_info,modalias必须指定已有的一个驱动,至于bus_num和chip_select,如果你不知道bus_num是多少,可以在你的父驱动中打印出来,这里的bus_num一定要和父类的bus_num一致,否则是无法生成设备文件的。如果spi一直没有时钟信号,很有可能是bus_num不对。
这样系统起来之后就会在/dev目录下出现一个名为spidev1.1的设备文件,读写这个文件就可以实现spi的操作
还有下面这种情况:
static struct spi_board_info prt_spi_device[] __initdata = {
{
.modalias = "HotPRT",
.max_speed_hz = 12500000, /* max spi clock (SCK) speed in HZ */
.bus_num = 1,
.chip_select = 1,
// .mode = SPI_MODE_0,
.platform_data = 0,
},
};
spi_register_board_info(prt_spi_device, ARRAY_SIZE(prt_spi_device));

我自己实现了一个spi的驱动,然后需要创建一个设备文件,设备文件的创建是在probe中完成。
static struct spi_driver prt_driver = {
.driver = {
.name = "HotPRT",
.bus = &spi_bus_type,
.owner = THIS_MODULE,
},
.probe = prt_probe,
.remove = __devexit_p(prt_remove),
};
spi_register_driver(&prt_driver);
但是我开始一直触发不了probe,于是找啊找,总算知道probe的调用过程了,如下:
int spi_register_driver(struct spi_driver *sdrv)
{
sdrv->driver.bus = &spi_bus_type;
if (sdrv->probe)
sdrv->driver.probe = spi_drv_probe;
if (sdrv->remove)
sdrv->driver.remove = spi_drv_remove;
if (sdrv->shutdown)
sdrv->driver.shutdown = spi_drv_shutdown;
return driver_register(&sdrv->driver);
}
然后调用driver_register
<pre name="code" class="cpp">int driver_register(struct device_driver *drv)
{
int ret;
struct device_driver *other;

BUG_ON(!drv->bus->p);

if ((drv->bus->probe && drv->probe) ||
(drv->bus->remove && drv->remove) ||
(drv->bus->shutdown && drv->shutdown))
printk(KERN_WARNING "Driver '%s' needs updating - please use "
"bus_type methods\n", drv->name);

other = driver_find(drv->name, drv->bus);
if (other) {
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
return -EBUSY;
}

ret = bus_add_driver(drv);
if (ret)
return ret;
ret = driver_add_groups(drv, drv->groups);
if (ret)
bus_remove_driver(drv);
return ret;
}

直接看bus_add_driver
klist_init(&priv->klist_devices, NULL, NULL);
priv->driver = drv;
drv->p = priv;
priv->kobj.kset = bus->p->drivers_kset;
error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
"%s", drv->name);
if (error)
goto out_unregister;

if (drv->bus->p->drivers_autoprobe) {
error = driver_attach(drv);
if (error)
goto out_unregister;
}
klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
mole_add_driver(drv->owner, drv);

这里只截取一部分,最后调用的是driver_attach
int driver_attach(struct device_driver * drv)
{
return bus_for_each_dev(drv->bus, NULL, drv, __driver_attach);
}

真正起作用的是__driver_attach:

static int __driver_attach(struct device * dev, void * data)
{
。。。
if (!dev->driver)
driver_probe_device(drv, dev);
。。。
}

int driver_probe_device(struct device_driver * drv, struct device * dev)
{
。。。
//1.先是判断bus是否match:
if (drv->bus->match && !drv->bus->match(dev, drv))
goto done;
//2.再具体执行probe:
ret = really_probe(dev, drv);
。。。
}

really_probe才是我们要找的函数:
static int really_probe(struct device *dev, struct device_driver *drv)
{
。。。
//1.先是调用的驱动所属总线的probe函数:
if (dev->bus->probe) {
ret = dev->bus->probe(dev);
if (ret)
goto probe_failed;

} else if (drv->probe) {
//2.再调用你的驱动中的probe函数:
ret = drv->probe(dev);
if (ret)
goto probe_failed;
}
。。。
}

其中,drv->probe(dev),才是真正调用你的驱动实现的具体的probe函数。至此probe函数被调用。
在板文件中添加spi_board_info,并在板文件

㈨ 请教linux的SPI驱动问题

内核版本2.6.30。编进内核的SPI驱动,通过看代码我明白了,大致过程是这样:
1、先创建一个spi_board_info结构描述spi设备信息,调用spi_register_board_info将这个结构添加到board_list中。
2、然后调用spi_register_master注册SPI控制器驱动,此时会调用scan_boardinfo扫描board_list,根据spi_board_info调用spi_new_device生成spi_device结构,用spi_add_device添加设备。
3、调用spi_register_driver注册spi_driver,通过与device匹配驱动设备。

阅读全文

与linuxspi读写相关的资料

热点内容
邓伦参加密室逃脱视频 浏览:391
音频压缩编码标准 浏览:300
常提到的app是表示什么 浏览:261
天津程序员传销 浏览:349
下班之后的程序员 浏览:71
检测支持ssl加密算法 浏览:344
衢州发布新闻什么APP 浏览:85
中国移动长沙dns服务器地址 浏览:251
wifi密码加密了怎么破解吗 浏览:598
linux命令cpu使用率 浏览:67
linux实用命令 浏览:240
传奇引擎修改在线时间命令 浏览:109
php取域名中间 浏览:898
cad命令栏太小 浏览:830
php开发环境搭建eclipse 浏览:482
qt文件夹名称大全 浏览:214
金山云服务器架构 浏览:230
安卓系统笔记本怎么切换系统 浏览:622
u盘加密快2个小时还没有搞完 浏览:94
小米有品商家版app叫什么 浏览:94