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程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)