基于硬件 SPI 的數(shù)據(jù)抽象實(shí)例(附代碼)
1.寫在前面
spi(Serial Peripheral Interface)即串行外設(shè)接口。與i2c一樣,spi也常用外設(shè)設(shè)備通信的總線,從事嵌入式開(kāi)發(fā)必不可少的掌握。
2.spi總線抽象
此部分實(shí)現(xiàn)源碼為:spi_core.c spi_core.h
2.1 spi總線模型對(duì)外接口(API)
/*extern function*/extern int spi_send_then_recv(struct spi_dev_device *spi_dev,const void *send_buff,
unsigned short send_size,void *recv_buff,unsigned short recv_size);
extern int spi_send_then_send(struct spi_dev_device *spi_dev,const void *send_buff1,
unsigned short send_size1,const void *send_buff2,unsigned short send_size2);
extern int spi_send_recv(struct spi_dev_device *spi_dev,const void *send_buff,void *recv_buff,unsigned short data_size);
extern int spi_send(struct spi_dev_device *spi_dev,const void *send_buff,unsigned short send_size);
1)spi_send_then_recv,標(biāo)準(zhǔn)spi,常規(guī)操作,發(fā)送完一幀再接收,如讀取某芯片寄存器的值;
2.2 spi總線抽象API實(shí)現(xiàn)
以“spi_send_then_recv”函數(shù)為例:
2.3 struct spi_de_device
該結(jié)構(gòu)體為關(guān)鍵,調(diào)用API驅(qū)動(dòng)一個(gè)外設(shè)時(shí),需要先初始化(類似Linux的注冊(cè)設(shè)備驅(qū)動(dòng))。一個(gè)完整的spi外設(shè),包括片選和總線量部分,一個(gè)總線可和多個(gè)片選組成,驅(qū)動(dòng)多個(gè)外設(shè),因此struct spi_dev_device設(shè)計(jì)原型為:
{
void (*spi_cs)(unsigned char state);
struct spi_bus_device *spi_bus;
};
1)第一個(gè)參數(shù)為函數(shù)指針,主要功能的實(shí)現(xiàn)spi外設(shè)片選的選擇(拉低/拉高)功能;
2.4 struct spi_bus_device *spi_bus
該結(jié)構(gòu)體為底層硬件相關(guān)的spi總線實(shí)現(xiàn),具體由實(shí)際需求實(shí)現(xiàn),如用硬件spi還是用模擬spi。struct spi_bus_device*spi_bus原型為:
{
int (*spi_bus_xfer)(struct spi_dev_device *spi_bus,struct spi_dev_message *msg);
void *spi_phy;
unsigned char data_width;
};
1)第一個(gè)參數(shù)是函數(shù)指針,為spi總線收發(fā)函數(shù),這部分就是我們平常寫裸機(jī)代碼時(shí)候?qū)懙降?,只是這里把它放在一個(gè)結(jié)構(gòu)體里面,以函數(shù)指針的方式實(shí)現(xiàn);這樣的好處是,上層接口不變,更好其他MCU或者使用模擬spi時(shí),只需修改此部分的函數(shù)實(shí)體,上層代碼不需變動(dòng)。
2.5 spi_bus_xfer
該函數(shù)指針入口參數(shù)為spi設(shè)備指針(struct spi_dev_device )、spi設(shè)備信息幀指針(struct spi_dev_message)。struct spi_dev_device與前面提及的為同一類參數(shù),struct spi_dev_message為收發(fā)數(shù)據(jù)信息幀,其原型如下:
{
const void *send_buf;
void *recv_buf;
int length;
unsigned char cs_take : 1;
unsigned char cs_release : 1;
};
1)send_buf:待發(fā)送數(shù)據(jù)(緩存);
3. spi總線抽象實(shí)現(xiàn)
此部分實(shí)現(xiàn)源碼為:spi_hw.c spi_hw.h
3.1 spi總線抽象API實(shí)現(xiàn)
第一步:“spi_send_then_recv”,實(shí)現(xiàn)代碼如下:
{
struct spi_dev_message message;
message.length = send_size;
message.send_buf = send_buff;
message.recv_buf = 0;
message.cs_take = 1;
message.cs_release = 0;
spi_dev->spi_bus->spi_bus_xfer(spi_dev,