本帖最后由 nightingale2003 于 2014-11-23 00:25 编辑
本来以为自己对SPI有了一定的理解,不管软件模拟,还是硬件SPI都写过程序也调试成功了。但今天重看了一遍SPI,发现有些问题之前一直没考虑到。所以希望各位帮忙解答下。
问题一:一般的从器件(单片机作为从器件暂时不考虑)大多属于 空闲状态低电平,上升沿有效输入,即CPOL=0,CPHA=0;
那么也就是说第一位的数据先出现在主从器件的MOSI口,然后上升沿到达后传入移位寄存器。
那么问题来了,既然在空闲时还没时钟信号,主从器件怎么知道什么时候输出第一个位?(这里不讨论软件模拟的情况)
目前考虑的是两个可能性:
1.当我们将要发送的数据写入 SPI的移位寄存器时,第一个位就输出到IO口了
2.SPI有片选端,当片选拉低时,该信号作为第一位数据的输出信号输出到IO口
不知哪个正确呢?
问题二:SPI的最基础的数据函数就一个uchar SPI_rw(uchar data);(网上大多数例子都这样写,相信函数内容各位也清除吧)
下面以无线模块的nRF24L01为例。
一般我们会在这基础上建立对从器件的函数用于写和读寄存器,有时候还要建立连续读、写的函数,如:
void SPI_write(uchar addr,uchar dat)
{
CSN=0;
SPI_rw(addr);
SPI_rw(dat);
CSN=1;
}
如果只是单独一个这样的函数还好,如果需要不停的写入读取寄存器时,从我们的角度来看,还比较有条理,比如:
SPI_write(0x20+EN_AA,0x01);
SPI_write(0x20+SETUP_RETR,0x0f);
SPI_write(0x20+EN_RXADDR,0x01);
但对于IO口来说,其实就是一大堆的SPI_rw();
这样一来,问题就是,nRF24L01怎么认定哪个是命令,哪个是数据?
如果说0x20+EN_AA(其实就是0x21)的这个数据nRF24L01认得出来,那万一后面要写的数据也是0x21,那这个是数据要是命令?
另一种情况是从从器件连续读数据,这时主器件(单片机)要发送8个字节以便读取从器件的数据,一般习惯是发送个0xff或者0x00
但如果发了个命令,还会继续读取还是执行该命令呢?
目前的一个考虑的想法是 CSN作为控制信号,拉低后执行的第一个为命令第二个为数据,但记得看过别人写程序把CSN写进了SPI_rw,
好像也看过直接把片选线接地的情况(当然前提 SPI总线上就一个从器件)
PS1:现在看来 I2C协议虽然麻烦但确实严谨多了
PS2:可能有人觉得做实验比上来问强,不过这两天没板子在手上,做不了实验,还请大神不惜赐教
|