,spi_rw(reg)返回的值不是a的值,这里返回的值没有意义是被丢弃掉了的,紧接着下一次spi_rw(0)返回的才是。
一次spi *** 作一般在cs(片选)的一个周期进行,举返
在读取寄存器值时一般需要调用2次以上的spi_rw,
比如读取寄存器reg,
首先
拉低cs线(片选)->调用spi_rw(reg),这里的reg实际上是0...1111按位与上reg,因为reg这个地址没有用到最高位,最高位为0代表读地址 *** 作,1代表写地址 *** 作。->再次调用spi_rw(0)
,这里为0是因为读 *** 作,如果是写那么就是写地址reg的值,即spi_rw(val)
->拉高cs线结束spi *** 作。
spi读写时是先写地址与 *** 作或命令的一个byte,再读写值的一个byte,也就是clk周期是2个byte也就是2*
8bit
=
16个周期的。
地址与 *** 作的一个byte:这个字节的最高位是控制读写的,读写分别为
0b0xxxxxxx或0b1xxxxxxx
的形式,
xxxxxxx中的最后几位是地址。中间几位是spi命令。
值的一个byte:
如果是读,那么全为0,如果是写,那么就是要写的值。如果是命令就看命令的定义了。
在时钟线电平的上升yuan写1位,的在时钟下降yuan读1位的,当这8个时钟周期完结那么就得到了8位正好一个字节。当然如果寄存器的数据宽度是2个字节时,相应的这里就要是16个时钟周期2个字节。
没正哗饥用过nrf24l01模块,但一般spi的过程就是这样,关键要看你要访问的模块的spec文档,里面都描述芦洞了这些读写,控制的时序图。
这是 读写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
}
调试已经通过///////////////////////////spi.h/////////////////////////////
#ifndef
SPI_H
#define
SPI_H
#include
<stc12le5a60s2.h>
#include
<spi.h>
//sfr
P4
=
0xe8
//STC12LE5A60S2单片机自带SPI控制器连接
//sbit
VCC1
=
P2^0//
VCC1
NO
USE
//sbit
SON
=
P1^6
//
MISO
//sbit
SIN
=
P1^5
//
MOSI
//sbit
SCKN
=
P1^7
//
SCK
sbit
CSN
=
P1^4
//
28J60
--
CS
//sbit
RSTN
=
P3^5
//RST,
no
use
//sbit
INTN
=
P3^3
//
INT,
no
use
void
init_spi(void)
void
WriteByte(u8_t
temp)
u8_t
ReadByte(void)
#endif
//////////////咐毕//////////////////////////////////////////////////
///////////////////////////spi.c/////////////////////////////
#include<spi.h>
//STC12LE5A60S2单片机自带SPI控制器连接
void
init_spi(void)
{
//SSIG
=
1
//忽略SS脚
//SPEN
=
1
//允许SPI工作
//DORD
=
0
//先传高位MSB
//MSTR
=
1
//设置单片机为主机
SPCTL
=
0xD0
//SPI
Control
Register
SSIG
SPEN
DORD
MSTR
CPOL
CPHA
SPR1
SPR0
0000,0100
SPSTAT
=
0xC0
//歼简碰
//IE2
|=
0x02
//允许SPI中断控制位
}
void
WriteByte(u8_t
temp)
{
SPDAT
=
temp
while(!(SPSTAT
&
0x80))
SPSTAT
=
0xC0
}
u8_t
ReadByte(void)
{
idata
u8_t
temp
//SPSTAT
=
0xC0
SPDAT
=
0x00
while(!(SPSTAT
&
0x80))
temp
=
SPDAT
SPSTAT
=
0xC0
return
temp
}
/////氏谈///////////////////////////////////////////////////////////
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)