Chinaunix首页 | 论坛 | 博客
  • 博客访问: 284420
  • 博文数量: 52
  • 博客积分: 2586
  • 博客等级: 少校
  • 技术积分: 508
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-29 19:06
文章分类

全部博文(52)

文章存档

2022年(1)

2019年(1)

2018年(1)

2013年(1)

2012年(1)

2011年(10)

2010年(16)

2009年(13)

2008年(6)

2007年(2)

我的朋友

分类: WINDOWS

2009-04-24 16:14:53

一般操作步骤
  如果SPI控制寄存器SPCON已经设置过,则写数据发送寄存器SPTDAT启动发送。对SPI卡操作步骤如下:
  (1)设置预分频寄存器SPPRE;
  (2)设置控制寄存器SPCON;
  (3)设置一个GPIO引脚,使选中的MMC或SD卡的片选信号nSS有效;
  (4)向数据发送寄存器SPTDAT写10次0xFF,对MMC或SD卡初始化;
  (5)发送数据:先要查询Tx/Rx REDY是否为1,然后向数据发送寄存器SPTDAT写数据;
   (6)接收数据:
  一般方式(同时收发,TAGD=0):向数据发送寄存器SPTDAT写0xFF,查询并确认Rx REDY为1,然后从数据接收寄存器中读取数据。
  仅接收方式(TAGD=1):并确认Rx REDY为1,然后从数据接收寄存器中读取数据。读取数据的同时启动一次发送。
  (7)设置GPIO引脚,使选中的MMC或SD卡的片选信号nSS无效,结束传输。

 

基本上看了这些,再看一下E文,对于2440(与2410的一样)的SPI就应该没问题了

下面是我的代码,是在WIN CE5。0下用的

2440 SPI初使化代码(WIN CE驱动下)



//======================================================================
// Name      : InitSPI
//======================================================================
void InitSPI(void)             //初使化SPI
{
        unsigned 
int pclk = S2410PCLK;  // s2410.h define
                                                    
// #define S2410FCLK           (203 * 1000 * 1000)        // 203MHz (FCLK).
                                                   
// #define PCLKDIV             4                        // P-clock (PCLK) divisor.
                                                      
// #define S2410PCLK           (S2410FCLK / PCLKDIV)    // PCLK.

         RETAILMSG (
0, (TEXT("::: InitSPI ") ));
/*
    //Set GPH10(CLKOUT1) as TXEN,GPH9(CLKOUT0) as RXEN ,both is GPIO
    v_pIOPregs->rGPHCON &= ~(0xf << 18); 
       v_pIOPregs->rGPHCON |=(0x5 << 18);
    //init is low
    v_pIOPregs->rGPGDAT &=~ (0x3<< 9);
    
*/            

    v_pIOPregs
->rGPGCON   &= ~(0x3 << 14);            //Set GPF7(EINT15) as EINT
    v_pIOPregs->rGPGCON  |=  (0x2 << 14);
    v_pIOPregs
->rGPGUP =(0x1<<7);                    //disable up

    
//EINT15==GPG7==GDO2 and Init as in
//    v_pIOPregs->rGPGCON &= ~(0x3<<14); 
//       v_pIOPregs->rGPGCON |=(0x0<<14);
//    v_pIOPregs->rGPGUP &=~(0x1<<7);            //enable up
       
    v_pIOPregs
->rGPBCON &= ~((0x3 << 10)|(0x3<<20)); 
       v_pIOPregs
->rGPBCON |=((0x1 << 10)|(0x1<<20));
    
//init is low
    v_pIOPregs->rGPBDAT &=~((0x1<< 5)|(0x1<<10));
    
      
// Set I/O is SPI interface
      
// Config GPE11,12,13 is SPIMIO0,SPIMOSI0,SPICLK0,and disable pullup
      v_pIOPregs->rGPECON &= ~(0x3F << 22); 
      v_pIOPregs
->rGPECON |= (0x2A << 22);
      v_pIOPregs
->rGPEUP|=(0x7<<11);
      
      
// Config GPB7(also KEY_ROW1 SPICLK1) is Master SPI CS                                     
      v_pIOPregs->rGPBCON &= ~(0x3 << 14);                          
      v_pIOPregs
->rGPBCON |= (0x1 << 14);        //as out
      v_pIOPregs->rGPBUP &= ~(0x1 << 7);        //enable pullup for GPB7    
      
// Initialize CS is high      
      v_pIOPregs->rGPBDAT |= (0x1 << 7);

      v_pCLKPWRregs
->rCLKCON |=(1<<18);
    
    
// Baudrate = PCLK/2/(Prescaler value + 1)
    
// PCLK = 203000000/4 = 50750000 Hz
    
// Prescaler value = 0x18 = 24
    
// Baudrate = 50750000/2/(24 + 1) = 1015000 = 1.015MHz
    
// MCP41010 max clock frequency is 10MHz
    v_pSSPregs->rSPPRE0 = 0x18;//0x18;    
    
    
// Set SPCON0 to configure properly the SPI module.    
    
// Master  
    
// SCK enable
    
// polling mode
    
//v_pSSPregs->rSPCON0 =0x18;// 0x18;    //001 1000
    
    v_pSSPregs
->rSPPIN0=0x02;
    v_pSSPregs
->rSPCON0 |=(1<<4)|(1<<3)|(0<<2)|(0<<1);
//    v_pSSPregs->rSPCON0 =0;
    
// 0 Tx Auto Garbage Data mode enable (TAGD):Decide whether the receiving data only needs or not.
    
//                                           0 = normal mode, 1 = Tx auto garbage data mode
    
//                                           NOTE: In normal mode, if you only want to receive data,
    
//                                           you should transmit dummy 0xFF data.
    
// 1,2 It is possible to operate the devices in SPI modes 0,0and 1,1. (MCP41010 datasheet)
    
//     Set SPI mode is 0,0.
    
// 3 Set S3C2410 is Master.
    
// 4 SCK Enable (ENSCK)
    
// 5,6 Determine how and by what SPTDAT is read/written.
    
//     00 = polling mode, 01 = interrupt mode
    
//     10 = DMA mode, 11 = reserved
    
//     Set polling mode
    
    
    RETAILMSG (
0, (TEXT("::: InitSPI over ") ));
}

WIN CE 下的SPI口地址映射

 



//======================================================================
// Name      : InitSPI addr
//
//======================================================================
BOOL
SPI_InitAddrIO(VOID)        
//IO口地址映射
{
        BOOL    RetValue 
= TRUE;
        
        v_pIOPregs 
= (volatile IOPreg *)VirtualAlloc(0sizeof(IOPreg), MEM_RESERVE, PAGE_NOACCESS);
        
        v_pCLKPWRregs = (volatile CLKPWRreg *)VirtualAlloc(0sizeof(CLKPWRreg), MEM_RESERVE, PAGE_NOACCESS);
        VirtualCopy((PVOID)v_pCLKPWRregs, (PVOID)(CLKPWR_BASE), 
sizeof(CLKPWRreg), PAGE_READWRITE | PAGE_NOCACHE);
        
        
if (v_pIOPregs == NULL) 
        {
                
            RETAILMSG(
1,(TEXT("For SPI_IOPregs : VirtualAlloc failed! ")));
            RetValue 
= FALSE;
        }
        
else 
        {
            
if (!VirtualCopy((PVOID)v_pIOPregs, (PVOID)(IOP_BASE), sizeof(IOPreg), PAGE_READWRITE | PAGE_NOCACHE)) 
            {
                RETAILMSG(
1,(TEXT("For SPI_IOPregs: VirtualCopy failed! ")));
                RetValue 
= FALSE;
            }
        }
    
        
if (!RetValue) 
        {
            RETAILMSG (
1, (TEXT("::: SPI_InitializeAddresses - Fail!! ") ));
            
if (v_pIOPregs) 
            {
                VirtualFree((PVOID) v_pIOPregs, 
0, MEM_RELEASE);
            }
            v_pIOPregs 
= NULL;
        }
        
else 
        {
        
            RETAILMSG (
0, (TEXT("::: SPI_InitializeAddresses - Success ") ));
        }

        
return(RetValue);
}

 

看程序不能断章取义,这个是我的一部分代码,只是给大家参考一下,要是自己写的话还是得看明白文档,不过这个初使化还是可以拿来主义的。哈哈

 

 

网上的那个mdd.c和spi.c有好多错误,首先是没有v_pCLKPWRregs->rCLKCON |=(1<<18);
这一句,设置SPI的寄存器没用,其次就是SPI的地址映射 v_pCLKPWRregs = (volatile CLKPWRreg *)VirtualAlloc(0sizeof(CLKPWRreg), MEM_RESERVE, PAGE_NOACCESS);
        VirtualCopy((PVOID)v_pCLKPWRregs, (PVOID)(CLKPWR_BASE), 
sizeof(CLKPWRreg), PAGE_READWRITE | PAGE_NOCACHE);

这一段要加上,还有一个地方就是这个函数

BOOL
SPI_InitAddrSPI(void)
{
  BOOL RetValue = TRUE;

//  RETAILMSG (1, (TEXT("SPI_InitializeAddresses \r\n") ));

  v_pSSPregs = (volatile SSPreg *)VirtualAlloc(0, sizeof(UART2reg), MEM_RESERVE, PAGE_NOACCESS);
  if (v_pSSPregs == NULL)
  {
//   ERRORMSG(1,(TEXT("For SPI_UART2regs : VirtualAlloc failed!\r\n")));
   RetValue = FALSE;
  }
  else
  {
   if (!VirtualCopy((PVOID)v_pSSPregs, (PVOID)(UART2_BASE), sizeof(UART2reg), PAGE_READWRITE | PAGE_NOCACHE))
   {
//    ERRORMSG(1,(TEXT("For SPI_UART2regs: VirtualCopy failed!\r\n")));
    RetValue = FALSE;
   }
  }
 
  if (!RetValue)
  {
//   RETAILMSG (1, (TEXT("::: SPI_InitializeAddresses - Fail!!\r\n") ));
   if (v_pSSPregs)
   {
    VirtualFree((PVOID) v_pSSPregs, 0, MEM_RELEASE);
   }
   v_pSSPregs = NULL;
  }
  else
  {
   ;
//   RETAILMSG (1, (TEXT("SPI_InitializeAddresses - Success\r\n") ));
  
return(RetValue);
}
要改为

BOOL
SPI_InitAddrSPI(void)
{
  BOOL RetValue = TRUE;

//  RETAILMSG (1, (TEXT("SPI_InitializeAddresses \r\n") ));

  v_pSSPregs = (voSSPregslatile SSPreg *)VirtualAlloc(0, sizeof(SSPregs), MEM_RESERVE, PAGE_NOACCESS);
  if (v_pSSPregs == NULL)
  {
//   ERRORMSG(1,(TEXT("For SPI_UART2regs : VirtualAlloc failed!\r\n")));
   RetValue = FALSE;
  }
  else
  {
   if (!VirtualCopy((PVOID)v_pSSPregs, (PVOID)(SSP_BASE), sizeof(SSPregs), PAGE_READWRITE | PAGE_NOCACHE))
   {
//    ERRORMSG(1,(TEXT("For SPI_UART2regs: VirtualCopy failed!\r\n")));
    RetValue = FALSE;
   }
  }
 
  if (!RetValue)
  {
//   RETAILMSG (1, (TEXT("::: SPI_InitializeAddresses - Fail!!\r\n") ));
   if (v_pSSPregs)
   {
    VirtualFree((PVOID) v_pSSPregs, 0, MEM_RELEASE);
   }
   v_pSSPregs = NULL;
  }
  else
  {
   ;
//   RETAILMSG (1, (TEXT("SPI_InitializeAddresses - Success\r\n") ));
  }
  return(RetValue);
}

就这么几个错误搞了我半个月,还有我在61ic上重了3块钱,其实那个程序也是错的,并且是我原来在pudn上下的那个,那个骗人的网站,晕呀!

阅读(2021) | 评论(4) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2010-08-19 11:06:10

时钟没有明白TAGD位的作用。 在该位位1是,是在什么时机来触发接收的呢? 如果是通过上次读取寄存器来触发,是不是很不灵活呢?

chinaunix网友2010-07-21 01:50:13

谢谢共享,现在正在做wince spi 主从通信,不知道最高通信波特率可以达到多少?

chinaunix网友2010-03-21 13:24:49

你好,我用的是wince,这是驱动程序,不用操作系统直接裸机跑SPI肯定是可以的,那就是把ARM单单片机用了,至于你的程序为什么不好使,应该是你的时序没写对,你是在ADS上编译的吧,你再好好看看你的时序写对了没有,写对了的话应该是有数据出来的。

chinaunix网友2010-01-16 22:47:18

我现在也在做2410的SPI方面,有个疑问想向你请教一下。 2410的SPI程序非得是在LINUX或者WINCE下么?不带系统不行么?我是初学者,还玩不转系统,只是照着书的寄存器设定之类的参考资料写的。但是结果就是SPI的输入输出口子上都没有数据。不明白是不是自己哪里出错,麻烦您帮我看看程序好么? ------------------ #include "config.h" void DelayNS(uint32 dly) { uint32 i; for(; dly>0; dly--) for(i=0; i<50000; i++); } int num1; char rec_data[128]; void spi_init() { rSPPRE1=24; rSPCON1=0x02; rSPPIN1=0x03; rGPGCON = rGPGCON & ~0xFCF3 | 0xFCF1; rGPGDAT = rGPGCON & ~1; //使GPG0输出0 } int main(vo