怎样在fpga中实现spi的功能

怎样在fpga中实现spi的功能,第1张

spi(serial peripheral interface),串行外围设备接口。由一个主设备和一个或多个从设备组成。主设备启动一个与从设备的同步通讯,从而完成数据的交换。

SPI,是一种高速的、全双工、同步的通信总线。在芯片的管教上只占用四根线,节约了芯片的管教,同时为PCB的布局上节省了空间,该接口的四条线为:串行时钟线(SCK)、主机输入/从机输出数据线MISO、主机输出/从机输入数据线MOSI和低电平有效的从机选择线CS。

SPI的通信原理很简单,它以主从方式工作。需要4跟线,3跟也可以(非双工),这些线也是所有基于SPI的设备共有的,他们是前槐SDI,SDO,SCK,CS

①SDO-主设备数据输出,从设备数据输入

②SDI-主设备数据输入,从设备数据输出

③SCK-时钟信号,有主设备产生

④CS-从设备片选信号,有主设备控制

接下来就负责通讯的3根线了。通讯是通过数据交换完成的,这里先要知道SPI是串行通讯协议,也就是说数据是一位一位的传输的。这就是SCK时钟线存在的原因,由SCK提供时钟脉冲,SDI,SDO则基于此脉冲完成数据传输。数据输出通过 SDO线,数据在时钟上升沿或下降沿时改变,在紧接着的下降沿或上升沿被读取。完成一位数据传输,输入也使用同样原理。这样,在至少8次时钟信号的改变(上沿和下沿为一次),就可以完成8位数据的传输。

在点对点的通信中,SPI接口不需要进行寻址 *** 作,且为全双工通信,显得简单高效。在多个从设备的系统中,每个从设备需要独立的使能信号,硬件上比I2C系统要稍微复杂一些。 (I2C寻址时,先写入地址,在写入数据)

SPI通信

该总线通信基于主-从配置。它有以慧扰友下4个信号:

MOSI:主出/从入

MISO:主入/从出

SCK:串行时钟

SS:从属选择

芯片上“从属选择李罩”(slave-select)的引脚数决定了可连到总线上的器件数量。

在SPI传输中,数据是同步进行发送和接收的。数据传输的时钟基于来自主处理器的时钟脉冲,摩托罗拉没有定义任何通用SPI的时钟规范。然而,最常用的时钟设置基于时钟极性(CPOL)和时钟相位(CPHA)两个参数,CPOL定义SPI串行时钟的活动状态,而CPHA定义相对于SO-数据位的时钟相位。 CPOL和CPHA的设置决定了数据取样的时钟沿。

1.定义三个gpio: p0-sclk, p1-sdi, p2-sdo;p0用于模拟spi的clock,薯陆禅p1用于接收数据,p2用于f发送数据;硬件上单片机A的p0接单片机B的p0,A的p1接B的p2,A的p2接B的p1

2.发送程序:clock拉低,sdo输出0或1(数据),延时一定时间,clock拉高,延时一定时间,这样A就发送一位数据到B,循环8次就发送一个字节数据

3.接收程序:检测clock状态,数尘如果为低,就读取sdi,直到clock拉高,结束该次输入,重复8次,读取一个字节

注意:

1。clock空闲状态为高,发送数据就拉低;悉轮

2.还需要加入起始停止同步协议,可根据需要进行完善

这是 读写pcf2127a的程序。用spi接口。

cpu 是51兼容段帆派系列 cy7c68013

#define spi_read 0x20

#define spi_write 0xa0

void spi_start(void)

{ OEE|=spi_ce+spi_di+spi_clk

OEE &= ~spi_do

SYNCDELAY

IOE&=~(spi_ce|spi_clk)

SYNCDELAY

}

void spi_stop(void)

{

IOE |=spi_ce

SYNCDELAY

}

void spi_wr(unsigned char command)

{

char i

for (i=0i<8i++)

{

if((command&0x80)==0x80) {IOE |=spi_di}else {IOE &=~spi_di}

command<<=1

SYNCDELAY

IOE |=spi_clk

SYNCDELAY

IOE &=~spi_clk

SYNCDELAY

SYNCDELAY

}

}

unsigned char spi_rd(void)

{

unsigned char bret

char i

bret=0

for (i=0i<8i++)

{IOE |=spi_clk

bret<<=1

SYNCDELAY

SYNCDELAY

if((IOE&spi_do)==spi_do){ bret++}

IOE &= ~spi_clk

SYNCDELAY

SYNCDELAY

}

return bret

}

void spi_writedata(unsigned char address,unsigned char command)

{

address&=0x1f

address|=0x20

spi_start()

spi_wr(address)

SYNCDELAY

spi_wr(command)

spi_stop()

}

unsigned char spi_readdata(unsigned char address)

{unsigned char bret

address&=0x1f

address |=0xa0

spi_start()

spi_wr(address)

SYNCDELAY

bret=spi_rd()

spi_stop()

return bret

}

void read_time(unsigned char address)

{spi_start()

spi_wr(address|0xa0)

EP0BUF[8] =spi_rd()//握贺秒

EP0BUF[9]= spi_rd()//分

EP0BUF[10]= spi_rd()//时

EP0BUF[11]= spi_rd()//日

EP0BUF[12]= spi_rd()

hEP0BUF[13]= spi_rd()//轿孝月

EP0BUF[14]= spi_rd()//年

spi_stop()

}

void write_ram(unsigned int address,unsigned int command)

{unsigned char addh,addl,commandh,commandl

addh=(address&0xff00)>>8

addl=address&0x00ff

commandh=(command&0xff00)>>8

commandl=command&0x00ff

spi_writedata(0x1a,addh)

spi_writedata(0x1b,addl)

spi_writedata(0x1c,commandh)

spi_writedata(0x1c,commandl)

}

unsigned int read_ram(unsigned int address)

{

unsigned char addh,addl,commandh,commandl

unsigned int command

addh=(address&0xff00)>>8

addl=address&0x00ff

spi_writedata(0x1a,addh)

spi_writedata(0x1b,addl)

commandl=spi_readdata(0x1d)

commandh=spi_readdata(0x1d)

command=(commandh<<8)+commandl

return command

}


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

原文地址: http://outofmemory.cn/yw/12452618.html

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

发表评论

登录后才能评论

评论列表(0条)

保存