導航:首頁 > 操作系統 > 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讀寫相關的資料

熱點內容
java地址重定向 瀏覽:268
一年級下冊摘蘋果的演算法是怎樣的 瀏覽:448
程序員出軌電視劇 瀏覽:88
伺服器系統地址怎麼查 瀏覽:54
解壓游戲發行官 瀏覽:601
國外小伙解壓實驗 瀏覽:336
頂級大學開設加密貨幣 瀏覽:437
java重載與多態 瀏覽:528
騰訊應屆程序員 瀏覽:942
一鍵編譯程序 瀏覽:129
語音加密包哪個好 瀏覽:339
有什麼學習高中語文的app 瀏覽:282
安卓手機的表格里怎麼打勾 瀏覽:409
阿里雲伺服器有網路安全服務嗎 瀏覽:968
超解壓兔子視頻 瀏覽:24
單片機怎麼測負脈沖 瀏覽:174
魅族備份的app在哪裡 瀏覽:740
java倒三角列印 瀏覽:115
通達信回封板主圖源碼 瀏覽:46
戰地什麼伺服器 瀏覽:301