
可以的,但SPI接口的器件有多种工作方式,如高位在前还是低位在前,空闲时时钟线高电平还是低电平
第一个跳变沿还是第二个跳变沿数据有效,程序是不同的,下面程序供参考
sbit CLK=P2^2;
sbit MOSI=P2^3; //发送方方管脚配置
sbit MISO=P2^4;
sbit BIT0=ACC^0;
sbit BIT7=ACC^7;//
void Write(uchar byte)//写数据
{
uchar i;
ACC=byte;
i=8;
while(i)
{
MOSI=BIT7;
CLK=1; // output 'uchar', MSB to MOSI
_nop_();
_nop_(); // shift next bit into MSB
_nop_();
_nop_();
ACC<<=1;
CLK=0; // Set SCK high
i--; // then set SCK low again
_nop_();
}
}
/
/函数:Read(uchar reg)
/功能:NRF24L01的读时序
//
uchar Read(void)
{
uchar i;
i=8;
sbit BIT0=ACC^0;
sbit BIT7=ACC^7;
while(i)
{
CLK=1; // output 'uchar', MSB to MOSI
_nop_();
_nop_();
_nop_();
_nop_(); // shift next bit into MSB
ACC<<=1;
BIT0=MISO ;
CLK=0; // Set SCK high
i--; // then set SCK low again
_nop_();
//led1=~led1;
}
return ACC; // return register value
}
这种SPI程序用51单片机的I/O口线很好模拟的,仔细看芯片的文档,下面这个是用在NRF905的:uchar bdata DATA_BUF;sbit flag =DATA_BUF^7;sbit flag1 =DATA_BUF^0;////function SpiWrite();void SpiWrite(uchar byte){ uchar i; DATA_BUF=byte; // Put function's parameter into a bdata variable for (i=0;i<8;i++) // Setup byte circulation bits { if (flag) // Put DATA_BUF7 on data line MOSI_nRF905=1; else MOSI_nRF905=0; SCK=1; // Set clock line high DATA_BUF=DATA_BUF<<1; // Shift DATA_BUF SCK=0; // Set clock line low } MOSI_nRF905=1;}////function SpiRead();uchar SpiRead(void){ uchar i; for (i=0;i<8;i++) // Setup byte circulation bits { DATA_BUF=DATA_BUF<<1; // Right shift DATA_BUF SCK=1; // Set clock line high if (MISO_nRF905) flag1=1; // Read data else flag1=0; SCK=0; // Set clock line low } MISO_nRF905=1; return DATA_BUF; // Return function parameter}
首先确保电路设计没什么问题。
然后根据手册确保时序没有问题。比如时钟线,片选线和IN,OUT线的时序关系。
另外如果是软件模拟时序的话注意上升和下降的次序。
如果是主控芯片发数据的话那么看DIN脚赋值后,当时钟线上拉或下拉时DIN脚的电平是否改变,从而确定是否传输成功。
1:SPI是一种高速,全双工的,同步的通信总线;
2:四线连接,MISO-主设备数据输入,从设备数据输出;MOSI-主设备数据输出,从设备数据输入;SCLK-时钟信号,由主设备产生;CS-从设备片选信号,由主设备控制。
3:主机和从机各有一个串行移位寄存器,两个寄存器中的数据在同一时刻被交换,如果只进行写 *** 作,主机只需要忽略接收到的字节;如果主机要读取从机中的字节,就必须发送一个空字节来引发从机的传输。
4:SPI可以设置输出串行时钟的极性和相位,时钟极性与串行同步时钟的空闲状态的电平有关,CPOL=0,串行同步时钟空闲状态为低电平,反之为高;CPHA可以设置选择两种不同的传输协议,CPHA=0,串行同步时钟的第一个跳边沿数据被采样,反之,在串行同步时钟的第二个跳边沿数据被采样;
5:为了防止MISO总线冲突,同一时间只允许一个从设备与主设备通讯;
6:SPI主机和从机的时钟极性和相位应该一致;
7:在数据传输(数据交换)的过程中,每次接收到的数据必须在下一次数据传输之前被采样如果之前接收到的数据没有被读取,那么这些已经接收完成的数据将有可能会被丢弃,导致SPI物理模块最终失效。因此,在程序中一般都会在SPI传输完数据后,去读取SPI设备里的数据,即使这些数据(DummyData)在我们的程序里是无用的。
1:概述
2:时序
1:配置相关引脚复用为SPI,使能SPI时钟;
2:设置SPI工作模式,包括主机或者从机、数据格式(高位在前还是低位在前)、设置串行时钟的极性和相位(采样方式)、SPI时钟频率(SPI的传输速度);
3:使能SPI;
spic-SPI驱动
flashc-w25q128驱动
这是 读写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=0;i<8;i++)
{
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=0;i<8;i++)
{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;
}
以上就是关于用51单片机引脚实现spi功能的程序全部的内容,包括:用51单片机引脚实现spi功能的程序、parmispi的程序编程步骤、DSP2812的SPI口通讯C语言程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)