
原作者:heekee 添加时间:2010-05-27 原文发表:2010-05-27 人气:826
--------------------------------------------------------------------------------
-
先给大家把源代码贴上来吧,等有时间了好好整理一下。
在大家做之前,先给大家说下模拟常识。
1。由于GPIO的相应速度有限,所以模拟的SPI速度有限,我这里大概是1.7M。所以GPIO模拟SPI只适合用于SPI设备控制和少量低速率数据传输。一般,SPI可以到26M。
2。通用性差,需要按照操作的SPI设备提供的SPI时序来模拟,不想专用SPI硬件接口,可以配置多种时序。
3。一定要那示波器来抓取模拟的读写时序,和SPI设备手册一一对照。
/*************************************************************************/
/* */
/* FILE NAME */
/* drv_spi.c */
/* */
/* DESCRIPTION */
/* This file contains the basic spi function by using GPIO. */
/* */
/*************************************************************************/
#include "target.h" // This is the GPIO define of your board
static u32 SPI_CS_PIN;
static u32 SPI_CLK_PIN;
static u32 SPI_DOUT_PIN;
static u32 SPI_DIN_PIN;
static u32 SPI_BUS;
#define USE_SPI_BUSY_PIN 0
// 20 ---> 195 KHz
// 10 ---> 355 KHz
#define DELAY 10
void spiDelay(u16 iCount)
{
u16 i;
for(i=0;i // SPI Internal Interface API /* -------------------------------------------------------------------------* * Function : spiWrBitHigh * * Description: This function is used to transfer a High bit to SPI bus. * * Parameters : None * * Return : None * * -------------------------------------------------------------------------*/ void spiWrBitHigh(void) { hal_gpio_SetBit(SPI_DOUT_PIN); hal_gpio_ClrBit(SPI_CLK_PIN); spiDelay(10); hal_gpio_SetBit(SPI_CLK_PIN); spiDelay(10); hal_gpio_ClrBit(SPI_CLK_PIN); } /* -------------------------------------------------------------------------* * Function : spiWrBitLow * * Description: This function is used to transfer a Low bit to SPI bus. * * Parameters : None * * Return : None * * -------------------------------------------------------------------------*/ void spiWrBitLow(void) { hal_gpio_ClrBit(SPI_DOUT_PIN); hal_gpio_ClrBit(SPI_CLK_PIN); spiDelay(10); hal_gpio_SetBit(SPI_CLK_PIN); spiDelay(10); hal_gpio_ClrBit(SPI_CLK_PIN); } // I2C Extern Interface API /* -------------------------------------------------------------------------*/ /* Function : spi_Open */ /* Description: Init SPI port. */ /* Parameters : GPIO bit which defined as SPI bus. */ /* Return : TRUE if OK. */ /* FALSE if Wrong. */ /* -------------------------------------------------------------------------*/ bool spi_Open(u8 spi_cs,u8 spi_dout,u8 spi_din,u8 spi_clk) { spi_fprintf((TSTDOUT,"init SPI ports...")); SPI_CS_PIN = 1 << spi_cs; SPI_DOUT_PIN = 1 << spi_dout; SPI_DIN_PIN = 1 << spi_din; SPI_CLK_PIN = 1 << spi_clk; SPI_BUS = SPI_CS_PIN | SPI_DOUT_PIN |SPI_DIN_PIN | SPI_CLK_PIN; //if ((SPI_BUS & USED_GPIO)!= SPI_BUS) //{ // spi_fprintf((TSTDOUT, "SPI BUS is 0x%x.",SPI_BUS)); // spi_fprintf((TSTDOUT, "SPI BUS is 0x%x.",USED_GPIO)); // spi_fprintf((TSTDOUT, "SPI BUS is 0x%x.",(SPI_BUS & USED_GPIO))); // spi_fprintf((TSTDOUT, "SPI GPIO Used Wrong in Board Config.")); // return(FALSE); //} // Set the GPIO direction of SPI interface hal_gpio_SetOut(SPI_CS_PIN); hal_gpio_SetOut(SPI_DOUT_PIN); hal_gpio_SetOut(SPI_CLK_PIN); hal_gpio_SetIn(SPI_DIN_PIN); //hal_gpio_SetIn(SPI_BUSY_PIN); // Set the initialize status of each SPI interface hal_gpio_ClrBit(SPI_CS_PIN); hal_gpio_ClrBit(SPI_CLK_PIN); hal_gpio_ClrBit(SPI_DOUT_PIN); return(TRUE); } /* -------------------------------------------------------------------------*/ /* Function : spi_Close */ /* Description: Close SPI port. */ /* Parameters : None */ /* Return : TRUE if OK. */ /* FALSE if Wrong. */ /* -------------------------------------------------------------------------*/ bool spi_Close(void) { return(TRUE); } /* -------------------------------------------------------------------------*/ /* Function : spi_GetData */ /* Description: This function is used to Get data from SPI bus. */ /* Parameters : iRecvData -- Data pointer to be stored */ /* Return : TRUE if OK. */ /* FALSE if Wrong. */ /* -------------------------------------------------------------------------*/ bool spi_GetData(u16 * iRecvData) { s16 iCount = 0; #if USE_SPI_BUSY_PIN u32 i = 0; #endif *iRecvData = 0; // Make sure that the initialize status of SPI CLK is low hal_gpio_ClrBit(SPI_CLK_PIN); // Make sure that the initialize status of SPI DOUT is low hal_gpio_ClrBit(SPI_DOUT_PIN); spiDelay(10); #if USE_SPI_BUSY_PIN while (i < 0xfffff) { if(hal_gpio_GetVal(SPI_BUSY_PIN) == 0) break; i++; } if(i == 0xfffff) return (FALSE); #endif for(iCount = 15;iCount >= 0;iCount --) { hal_gpio_SetBit(SPI_CLK_PIN); spiDelay(10); if(hal_gpio_GetVal(SPI_DIN_PIN)) (*iRecvData)|=(1< hal_gpio_ClrBit(SPI_CLK_PIN); spiDelay(10); } return(TRUE); } /* -------------------------------------------------------------------------*/ /* Function : spi_SendData */ /* Description: This function is used to Send data to SPI bus. */ /* Parameters : iSendData -- 8 bit data to be sent */ /* Return : TRUE if OK. */ /* FALSE if Wrong. */ /* -------------------------------------------------------------------------*/ bool spi_SendData(u8 iSendData) { s8 iCount = 0; for(iCount=7; iCount>=0; iCount--) { if(iSendData & (1< } return (TRUE); } 用计算机并口模拟SPI通讯的C源程序 #define LPT_PORT 0x378 #define CLR_WCK(X) {X=X&(~(1<<0)); outportb(LPT_PORT,X); } // data.0 #define SET_WCK(X) {X=X | (1<<0) outportb(LPT_PORT,X); } #define CLR_BCK(X) {X=X&(~(1<<2)); outportb(LPT_PORT,X); } // data.2 #define SET_BCK(X) {X=X | (1<<2) outportb(LPT_PORT,X); } #define CLR_DATA(X) {X=X&(~(1<<3)); outportb(LPT_PORT,X); } // data.3 #define SET_DATA(X) {X=X | (1<<3) outportb(LPT_PORT,X); } #define FALSE 0 #define TRUE 1 void test_comm() { unsigned char data data = 0; printf("Please press enter to begin send data\\n"); getch(); printf("Pull down WCK data.0\\n"); CLR_WCK(data); getch(); printf("Pull up WCK data.0\\n"); SET_WCK(data); getch(); printf("Pull down BCK data.2\\n"); CLR_BCK(data); getch(); printf("Pull up BCK data.2\\n"); SET_BCK(data); getch(); printf("Pull down DATA data.3\\n"); CLR_DATA(data); getch(); printf("Pull up DATA data.3\\n"); SET_DATA(data); getch(); } // Note: the size of buffer to send must be dword multiple // size is the number of bytes to send void short_delay(int n) { int i; for(i=0;i {int temp =0;} } int send_spi_data(unsigned char *buffer, unsigned long size) { unsigned char buff[1024]; unsigned char *buf=buff; unsigned char data; int i,j,k; data =0; if((size%4)!=0) return FALSE; memcpy(buff,buffer,size); do{ SET_WCK(data); for(k=0;k<2;k++){ for(j=0;j<2;j++){ printf("."); for(i=0;i<8;i++){ if((*buf)&0x80){ SET_DATA(data); }else{ CLR_DATA(data); } short_delay(1); // delay(1); SET_BCK(data); short_delay(1); // delay(1); CLR_BCK(data); short_delay(1); // delay(1); *buf<<=1; } buf++; size--; } // buf++; // size--; CLR_WCK(data); } SET_WCK(data); }while(size>0); return TRUE; } /* void main() { int i; unsigned char tmpdata[4]; tmpdata[0] = 0x34; tmpdata[1] = 0x12; tmpdata[2] = 0x56; tmpdata[3] = 0x78; // for(i=0;i<500;i++) for(i=0;i<50;i++) { send_spi_data(tmpdata,4); } // test_comm(); } */ 运用4个普通I/O口模拟SPI程序源代码 /******************************************************************** 函 数 名:uchar SpiReadWrite(uchar dat) 功 能:SPI发送接收一个数据 说 明: 调 用: 入口参数: 出口参数: ***********************************************************************/ uchar SpiReadWrite(uchar dat) { uchar i,temp; temp=0; SCK=0; _nop_(); for(i=0;i<8;i++) { if(dat & 0x80) MOSI=1; else MOSI=0; dat<<=1; SCK=1; _nop_(); _nop_(); _nop_(); _nop_(); temp<<=1; if(MISO)temp++; SCK=0; _nop_(); _nop_(); _nop_(); _nop_(); } return temp; } 1、SPI总线速度: 波特率可以高达5Mbps,具体速度大小取决于SPI硬件。 例如,Xicor公司的SPI串行器件传输速度能达到5MHz; ATMEL的AT45DB021B,20 MHz Max Clock Frequency; LPC2214的SPI,最大数据位速率为输入时钟速率的1/8。 2、SPI简介: 同步外设接口(SPI)是由摩托罗拉公司开发的全双工同步串行总线,该总线大量用在与EEPROM、ADC、FLASH和显示驱动器之类的慢速外设器件通信。 SPI(Serial 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-数据位的时钟相位。CPOL和CPHA的设置决定了数据取样的时钟. IO口模拟SPI通信C51程序 2011-06-27 8:57 /************************** 文件所用资源 1.端口:P0.4,P0.5,P0.6,P0.7 2.调用delay_ms函数 **************************/ /************************* 模拟SPI接口I/O定义 *************************/ sbit spi_cs=P0^1; sbit spi_di=P0^2; sbit spi_clk=P0^3; sbit spi_do=P0^4; /******************************* 向SPI器件写入一个字节数据 *******************************/ void spi_write(unsigned char spi_dat) { unsigned char i; spi_cs=0; for (i=0;i<8;i++) { spi_clk=0; if((spi_dat & 0x80)==0x80)spi_di=1; else spi_di=0; spi_clk=1; spi_dat=(spi_dat<<1); } spi_cs=1; } /******************************** 从SPI器件读出一个字节数据 ********************************/ unsigned char spi_read() { unsigned char i,spi_dat; spi_cs=0; for (i=0;i<8;i++) { spi_clk=0; spi_dat=(spi_dat<<1); spi_clk=1; if(spi_do==1)spi_dat|=0x01; else spi_dat&=~0x01; } spi_cs=1; return spi_dat; }
