原创 SPI总线学习

2008-9-2 10:43 6865 13 14 分类: 通信

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


1SPI总线速度:
波特率可以高达5Mbps,具体速度大小取决于SPI硬件。
例如,Xicor公司的SPI串行器件传输速度能达到5MHz
ATMEL
AT45DB021B20 MHz Max Clock Frequency


         LPC2214SPI最大数据位速率为输入时钟速率的1/8


 


2SPI简介:
同步外设接口(SPI)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量用在与EEPROMADCFLASH和显示驱动器之类的慢速外设器件通信。
 
 SPISerial Peripheral Interface)是一种串行同步通讯协议,由一个主设备和一个或多个从设备组成,主设备启动一个与从设备的同步通讯,从而完成数据的交换。通讯时,数据由MOSI  输出,MISO 输入,数据在时钟的上升或下降沿由MOSI 输出,在紧接着的下降或上升沿由MISO 读入,这样经过8/16 次时钟的改变,完成8/16 位数据的传输。


       ====在一次数据传输过程中,接口上只能有一个主机和一个从机能够通信。并且,主机总是向从机发送一个字节数据,而从机也总是向主机发送一个字节数据。


该总线通信基于主-从配置。它4个信号:
      MOSI:
主出/从入
      MISO:
主入/从出
      SCK:
串行时钟
      SS:
从属选择 。即CS(从使能信号),CS 决定了唯一的与主设备通信的从设备,如        没有CS 信号,则只能存在一个从设备,主设备通过产生移位时钟来发起通讯。

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


 


3、例子:


        LPC2214有两个SPI接口。


SPI 从机选择信号是一个低有效信号,用于指示被选择参与数据传输


的从机。每个从机都有各自特定的从机选择输入信号。在数据处理之前,SSEL


必须为低电平并在整个处理过程中保持低电平。如果在数据传输中SSEL 信号变


为高电平,传输将被中止。这种情况下,从机返回到空闲状态并将任何接收到


的数据丢弃。对于这样的异常没有其它的指示。该信号不直接由主机驱动。可


通过软件使用一个通用I/O 口来驱动。


注:配置为SPI 主机的LPC2114/2124/2212/2214 必须选择一个合适的管脚用作


SSEL 功能并使其保持高电平,只有这样,器件才能真正执行主机的功能。


<?xml:namespace prefix = v ns = "urn:schemas-microsoft-com:vml" />


 



 



 


例程:XFT-8001部分SPI软体;


     /*----定义SPI相关控制器的控制位(SPCR)----*/


#define  MSTR BIT5               /*-----主模式控制---- #define  BIT5  0x00000020   */


#define CPOL  BIT4               /*-----时钟极性控制---- #define BIT4  0x00000010  */


#define  CPHA BIT3               /*-----时钟相位控制----*/


#define  LSBF BIT6               /*-----移位方向控制----*/


 


#define  SCK  P0_4              /*------串行时钟-------*/


#define  MISO P0_5                    /*------主入从出-------*/


#define  MOSI P0_6                   /*------主出从入------*/


#define  SSEL_AD  P0_16              /*----从机选择SPI---*/


#define FLASH_CS P0_19


 


 


void SpiInit(uint8 x)


{


  switch(x)


       {


            case FLASHSPI:                                                                   //按照flash的要求初始化SPI


                         S0SPCCR = 0x00000036;         //400KHz的时钟频率   S0SPCCR=Fpclk/SPI频率


                            S0SPCR  = MSTR;                                                          //主控制器,模式选择0


                            break;


                   case SDSPI:                                                                                //按照SD卡的要求初始化SPI


                            S0SPCCR         = 0x0000000E;


                            S0SPCR  = MSTR;


                            break;


                   case HC595SPI:                                                                       //按照595的要求初始化SPI


                            break;


         }


}


 


/***********************************************************************


** 函数名称: SpiSendData()


** 功能描述:       SPI总线发送数据,由于SPI的特点,SPI在发送数据的时候,也在接收数据;如果仅仅要求接收数据,也要发送数据,不然没有SCK时钟


** 输 入:           x:SPI将要发送的数据


** 输 出:           返回接收的数据        


** 全局变量:      


** 调用模块:      


** 日 期:           <?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />20061112


************************************/


uint8 SpiSendData(uint8 x)


{ S0SPDR = x;


           while((S0SPSR&0x80)==0);


           return S0SPDR;


}


 


/*************************


** 函数名称: EraseFlashBlock()


** 功能描述:       擦除单个block的数据, 可以擦除器件中的任何一个指定编号的block,完成擦除之后要读取状态位来判断是否擦除完毕


**                在片选信号CS的上升沿开始擦除


** 输 入:           addr:要擦除的块编号,对于AT45DB021B而言,范围从0127


** 输 出:          


** 全局变量:      


** 调用模块:      


** 日 期:           2007512


****************************************************************/


void EraseFlashBlock(uint8 addr)


{ uint16 temp;


  uint8 temp1,temp2;


         temp = (addr<<4);


           temp1=(temp>>8)&0x00FF;


           temp2=temp&0x00FF;


 


SpiSendData(0x50);    // 0x50 AT45DB021BBlock Erase命令。


         SpiSendData(temp1);   // 给出块的Address Byte


           SpiSendData(temp2);


           SpiSendData(0x00);


}



 


/******************************************************************************


** 函数名称: EraseFlashPage()


** 功能描述:       擦除单个page快的数据, 可以擦除器件中的任何一个指定编号的page,完成擦除之后要读取状态位来判断是否擦除完毕


**                在片选信号CS的上升沿开始擦除


** 输 入:           addr:要擦除的page编号,对于AT45DB021B而言,范围从01023


** 输 出:          


** 全局变量:      


** 调用模块:      


***************/


void EraseFlashPage(uint16 addr)


{


uint16 temp;


uint8 temp1,temp2;


           temp = (addr<<1);


 


           temp1=(temp>>8)&0x00FF;


           temp2=temp&0x00FF;


 


         SpiSendData(0x81);         // 0x81 AT45DB021BPage Erase命令。


           SpiSendData(temp1);        // 给出pageAddress Byte


           SpiSendData(temp2);


           SpiSendData(0x00);


}



 


 


/*************************************************************************


** 函数名称: PreReadPage()


** 功能描述:       读取某一页的任何数据,本函数并不从page中读数据,后面跟上SpiSendData函数读数据


** 输 入:           page_addrpage_addr是指定的页地址


**                byte_addr,byte_addr指定的字节地址


** 输 出:          


**        


** 全局变量:      


** 调用模块:      


************************************************/


void PreReadPage(uint16 page_addr,uint16 byte_addr)


{


uint32 temp;


uint8 temp1,temp2,temp3;


 


temp=byte_addr+page_addr<<9;


temp1=(temp>>16)&0x000000FF;


temp2=(temp>>8)&0x000000FF;


temp3=temp&0x000000FF;


 


SpiSendData(0xD2);     //0xD2 AT45DB021BMain Memory Page Read命令。


SpiSendData(temp1);     // 给出pageAddress Byte


SpiSendData(temp2);


SpiSendData(temp3);


 


SpiSendData(0x00);      //


SpiSendData(0x00);


SpiSendData(0x00);


SpiSendData(0x00);


}


 



 


/**************************************************************************


 


** 函数名称: ReadFlashState()


** 功能描述:       读取Flash的状态,在对flash进行包含buffer的操作,擦除操作等要检查flash的状态


** 输 入:          


** 输 出:           state:返回Flash的状态


**        


** 全局变量:      


** 调用模块:      


**********************/


 


uint8 ReadFlashState(void)


{


uint8 state="0";


SpiSendData(0xD7);    // 0xD7 AT45DB021BStatus Register Read 命令。


state=SpiSendData(0x00);


return state;


}

文章评论1条评论)

登录后参与讨论

用户1366686 2012-6-26 22:19

xue xi lo

用户78399 2007-3-1 21:17

手持式消费产品的用s3c2410等

工业用飞利浦

用户68661 2007-3-1 18:53

三星的,呵呵

相关推荐阅读
用户1329446 2013-07-17 21:25
__I、 __O 、__IO是什么意思?
   ---转自http://blog.csdn.net/denghuanhuandeng/article/details/7281293  __I、 __O 、__IO是什么意思?  ...
用户1329446 2013-04-08 20:44
LED调光简介2
第二部分 采用交流电源的LED调光   三.用可控硅对LED调光    普通的白炽灯和卤素灯通常采用可控硅来调光。因为白炽灯和卤素灯是一个纯阻器件,它不要求输入电...
用户1329446 2013-04-08 20:44
LED调光简介
  第一部分 采用直流电源LED的调光技术   一.用调正向电流的方法来调亮度   要改变LED的亮度,是很...
用户1329446 2013-02-25 17:06
功率放大器相关
  1.功率放大电路的定义 功率放大电路是一种以输出较大功率为目的的放大电路。它一般直接驱动负载,带负载能力要强。 2.功率放大电路与电压放大电路的区别 (1).本质相同 电压...
用户1329446 2011-12-03 18:27
2年了,有什么长进?
建立博客2年了,自己有什么长进?经济上,经验上,能力上有什么长进? 三岁看老是对的...
用户1329446 2009-12-24 19:05
好累
最近越来越累了,尤其在小公司,除了硬件的东西要搞,还要搞结构的、采购的、工艺的、测试的、调试的、售后的。地主家的长工...
我要评论
1
13
关闭 站长推荐上一条 /2 下一条