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

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

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中获得从机的应答数据了。

1使用一片SPI flash,比如W25X16,有2M的空间给你储存点阵字库。可以将汉字字库文件在电脑上拷贝到SD卡,单片机通过FAT文件系统读取字库文件数据复制到W25X16中。

2将SD卡当做一个超大的flash,先由PC通过串口将字库数据逐个传入单片机,单片机再通过SPI传给SD卡,这样SD卡中就储存好字库,不过,这种方法不利于字库更新。

module

spi_mosi(rst,clk,rd,wr,datain,

spics,spiclk,spido,spidi,dataout);

input

rst;

//置位信号,低有效

input

clk;

//时钟信号

input

rd;

//接收数据命令

input

wr;

//发送数据命令

input

spidi;

//SPI数据输入信号

input

[7:0]

datain;

//发送数据输入

output

spics;

//SPI片选信号

output

spiclk;

//SPI时钟信号

output

spido;

//SPI数据输出信号

output

[7:0]

dataout;

//接收数据输出

reg

spics;

reg

spiclk;

reg

spido;

reg

[7:0]

dstate,

dsend,dataout,dreceive

;//,cnt;

reg

[1:0]

spistate;

parameter

idle

=

2'b00;

parameter

send_data

=

2'b01;

parameter

receive_data

=

2'b10;

initial

begin

spics

<=

1'b1;

spiclk

<=

1'b1;

spido

<=

1'b1;

end

always

@(posedge

clk)

begin

if(!rst)

begin

spistate

<=

idle;

//

cnt

<=

8'd0;

spics

<=

1'b1;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd0;

end

else

begin

case

(spistate)

2'b00:

begin

//

spics

<=

1'b1;

//

spiclk

<=

1'b1;

//

spido

<=

1'b1;

//

if(cnt

==

8'd0)

//

begin

//

cnt

<=

8'd0;

if((wr

==

1'b0)

&&

(rd

==

1'b1))

//发送资料转换

begin

spistate

<=

send_data;

dstate

<=

8'd0;

dsend

<=

datain;

end

else

if((wr

==

1'b1)

&&

(rd

==

1'b0))

//接收数据转换

begin

spistate

<=

receive_data;

dstate

<=

8'd0;

end

else

begin

spistate

<=

idle;

dstate

<=

8'd0;

end

//

end

//

else

//

begin

//

cnt

<=

cnt

+

8'd1;

//

end

end

2'b01:

//发送数据状态

begin

case

(dstate)

8'd0:

//产生片选信号有效

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd1;

end

8'd1:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd2;

end

8'd2:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

1'b1;

dstate

<=

8'd3;

end

8'd3:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

dsend[7];

//发送数据最高位

dstate

<=

8'd4;

end

8'd4:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[7];

dstate

<=

8'd5;

end

8'd5:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

dsend[6];

dstate

<=

8'd6;

end

8'd6:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[6];

dstate

<=

8'd7;

end

8'd7:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

dsend[5];

dstate

<=

8'd8;

end

8'd8:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[5];

dstate

<=

8'd9;

end

8'd9:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

dsend[4];

dstate

<=

8'd10;

end

8'd10:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[4];

dstate

<=

8'd11;

end

8'd11:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

dsend[3];

dstate

<=

8'd12;

end

8'd12:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[3];

dstate

<=

8'd13;

end

8'd13:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

dsend[2];

dstate

<=

8'd14;

end

8'd14:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[2];

dstate

<=

8'd15;

end

8'd15:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

dsend[1];

dstate

<=

8'd16;

end

8'd16:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[1];

dstate

<=

8'd17;

end

8'd17:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

//发送最低位数据

spido

<=

dsend[0];

dstate

<=

8'd18;

end

8'd18:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

dsend[0];

//spiclk的下降沿让最低位数据被读取

dstate

<=

8'd19;

end

8'd19:

//置片选信号无效

begin

spics

<=

1'b1;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd20;

end

8'd20:

begin

spics

<=

1'b1;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd0;

spistate

<=

idle;

end

default

begin

spics

<=

1'b1;

spiclk

<=

1'b1;

spido

<=

1'b1;

spistate

<=

idle;

end

endcase

end

2'b10:

//接收数据状态

begin

case

(dstate)

//片选信号有效

8'd0:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd1;

end

8'd1:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd2;

end

8'd2:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

spido

<=

1'b1;

dstate

<=

8'd3;

end

8'd3:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd4;

end

8'd4:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

//紧接着上升沿的下降沿数据被读取

dreceive[7]

<=

spidi;

//接收数据最高位

dstate

<=

8'd5;

end

8'd5:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd6;

end

8'd6:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

dreceive[6]

<=

spidi;

dstate

<=

8'd7;

end

8'd7:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd8;

end

8'd8:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

dreceive[5]

<=

spidi;

dstate

<=

8'd9;

end

8'd9:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd10;

end

8'd10:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

dreceive[4]

<=

spidi;

dstate

<=

8'd11;

end

8'd11:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd12;

end

8'd12:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

dreceive[3]

<=

spidi;

dstate

<=

8'd13;

end

8'd13:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd14;

end

8'd14:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

dreceive[2]

<=

spidi;

dstate

<=

8'd15;

end

8'd15:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd16;

end

8'd16:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

dreceive[1]

<=

spidi;

dstate

<=

8'd17;

end

8'd17:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

dstate

<=

8'd18;

end

8'd18:

begin

spics

<=

1'b0;

spiclk

<=

1'b0;

dreceive[0]

<=

spidi;

//接收数据最低位

dstate

<=

8'd19;

end

8'd19:

begin

spics

<=

1'b0;

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd20;

dataout<=

dreceive;

end

8'd20:

begin

spics

<=

1'b1;

//片选信号无效

spiclk

<=

1'b1;

spido

<=

1'b1;

dstate

<=

8'd0;

spistate

<=

idle;

end

endcase

end

default:

begin

spics

<=

1'b1;

spiclk

<=

1'b1;

spido

<=

1'b1;

spistate

<=

idle;

end

endcase

//对应上面的发送数据情形

end

//对应上面的RST没有按下的情形

end

//对应最上面的always@(posedge

clk)

endmodule

//------------------------------------------------------------------------------

//SPI控制数码管显示

//首先还是先介绍一下大概的 *** 作流程~~

//SPI时钟值计算如下:SPI时钟=Fpclk/SPCCR,式子中,SPCCR的值必须大于8的偶数

//------------------------------------------------------------------------------

//主机SPI的基本 *** 作方法如下:

//1)设置I/O连接

//2)设置SPCCR得到相应的SPI时钟

//3)设置SPCR控制SPI为主机模式,并配置SPI时钟的极性等~~

//4)片选从机,将数据写入SPDR,然后将数据发送出去

//5)等待SPIF置位,既数据发送完毕

//6)取消从机选择,读取接受的数据SPDR(可选)~~

//------------------------------------------------------------------------------

//从机SPI的基本 *** 作方法如下:

//1)设置I/O连接

//2)设置SPCR控制SPI为从机模式,并且配置SPI时钟极性等~~

//3)将要发送的数据写入SPDR(可选)~~

//4)等待SPIF置位,既接收到主机发送的数据

//5)从SPDR中读取数据

//------------------------------------------------------------------------------

//使用SPI接口向74HC595发送数据

//控制数码管显示

//------------------------------------------------------------------------------

#include"lpc210xh"

#include"macroandconsth"

#include"delayh"

//------------------------------------------------------------------------------

#define HC595_CS 0x00000100 //P08口为74HC595的片选

uchar const seg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,

0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

//------------------------------------------------------------------------------

//master_spi_init()

//主机初始化SPI接口

void master_spi_init()

{

S0SPCCR=0x52; //设置SPI时钟分频

S0SPCR=0x30; //这里得好好说说:

//设置SPI控制寄存器:SPIE为0,既SPI中断被禁止

//LSBF为0,既SPI数据传输MSB(bit7)在先

//MSTR为1,既SPI处于主机模式

//CPOL为1,既时钟极性的控制。该位为1,既SCK的低电平有效

}

//------------------------------------------------------------------------------

//master_send_data()

//主机向SPI中线发送数据

uchar master_send_data(uchar dat)

{

IOCLR=HC595_CS; //片选

S0SPDR=dat;

while((S0SPSR&0x80)==0); //等待SPIF置位,既等待数据发送完毕

//这里一定要注意:SPIF不是SPI中断标志,中断标志位于SPINT寄存器中

IOSET=HC595_CS; //取消片选

return(S0SPDR); //这里也要注意:SPI实际上也就是一个16位的数据的一个循环,也就是主机和从机数据的交换

}

//------------------------------------------------------------------------------

//main()

int main()

{

uchar receive_data;

uchar i;

PINSEL0=0x00005500; //设置SPI引脚连接

PINSEL1=0x00000000;

IODIR=HC595_CS; //设置HC595的I/O口方向位输出,其它为输入

master_spi_init();

while(1)

{

for(i=0;i<16;i++)

{

receive_data=master_send_data(seg[i]); //发送显示数据

delay_nms(1000);

}

}

}

你所指的spidevc是SPI的用户模式设备接口的驱动,可以通过应用程序去 *** 作/dev/spidev达到与硬件设备的SPI通信,对于 *** 作SPI NOR FLASH,更多是注册为MTD设备,详细可参考drivers/mtd/device/m25p80c,里面已经有相关实现。

但无论如何,前提是你的内核里已经有SPI控制器的驱动,否则如何通信呢。代码一般在drivers/spi/里。

那是应该是给spi设备驱动范本吧,可以籍此写自己的spi设备驱动,没有设备节点就自己创建个嘛。或者在驱动中添加创建设备节点的函数。

以上就是关于帮忙分析一个这个spi读写程序,详细一点的,解释一下。怎么觉得读和写的内容怎么差不多呢,怎么实现的读写全部的内容,包括:帮忙分析一个这个spi读写程序,详细一点的,解释一下。怎么觉得读和写的内容怎么差不多呢,怎么实现的读写、如何把字库生成直接烧入SPI、spi接口的Verilog程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10218344.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-06
下一篇 2023-05-06

发表评论

登录后才能评论

评论列表(0条)

保存