S3C2410 SPI的使用(1) 中不知道怎么回事儿,POWERPOINT的东西发上来就变了形了,搞不懂,不过还是得发啊,不能半途而废啊。
Register
|
Address
|
R/W
|
Description
|
Reset Value
|
SPSTA0
|
0x59000004
|
R
|
SPI0
状态寄存器
|
0x01
|
SPSTA1
|
0x59000024
|
R
|
SPI1
状态寄存器
|
0x01
|
字段名
|
位
|
意
义
|
初值
|
reserved
|
7:3
|
保
留
|
|
Data Collision Error
Flag
(DCOL)
|
2
|
数据写碰撞
(
正在发送时写
SPTDAT)
错误标志。
0
:无错;
1
:碰撞错误
|
0
|
Multi Master Error
Flag
(MULF)
|
1
|
多主
SPI
错误标志。
0
:无错;
1
:多主
SPI
错误。
|
0
|
Transfer Ready
Flag (REDY)
|
0
|
收发就绪
标志
。
0
:未就绪;
1
:收或发就绪。
写
SPTDAT
后该位自动清
0
|
1
|
Register
|
Address
|
R/W
|
Description
|
Reset Value
|
SPPIN0
|
0x59000008
|
R/W
|
SPI0
引脚控制寄存器
|
0x02
|
SPPIN1
|
0x59000028
|
R/W
|
SPI1
引脚控制寄存器
|
0x02
|
字段名
|
位
|
意
义
|
初值
|
reserved
|
7:3
|
保
留
|
|
Multi Master error
detect Enable
(ENMUL)
|
2
|
引脚多主
SPI
错误测试设置。
0
:禁测;
1
:允许多主错误测试。
测试结果在
SPSTAn
中的
MULF
位
|
0
|
reserved
|
1
|
该位应该为
1
|
1
|
Master Out Keep
(KEEP)
|
0
|
1
字节发完后
MOSI
的控制与释放
0
:释放;
1
:保持
MOSI
原电平
|
0
|
剩下的寄存器也就没有什么了,大家自己看看吧
接着来点文字:
应用方法
一般操作步骤
如果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文,对于2410的SPI就应该没问题了
下面是我的代码,是在WIN CE5。0下用的
2410 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( 0 , sizeof (IOPreg), MEM_RESERVE, PAGE_NOACCESS);
v_pCLKPWRregs = ( volatile CLKPWRreg * )VirtualAlloc( 0 , sizeof (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);
}
看程序不能断章取义,这个是我的一部分代码,只是给大家参考一下,要是自己写的话还是得看明白文档,不过这个初使化还是可以拿来主义的。哈哈
最后说的:
一般到用SPI全是针对一个外器的初使化或者是数据读取和写入,SPI的协议只规定了他的基本时序,但是一个器件如果能正常的使用SPI还必需符合他自己的协议,比如CC1100的SPI数据操作时序就是先送地址,再送数据,其实一般的器件也都是这样的,1100是8位操作的,而用ILI9320IC的TFT液晶屏却是十六位的,而且还有一些其它的比如晶振的起振等,这样就要先看明白器件的手册再根据2410的SPI发送接收程序来写符合相当器件时序的SPI程序,ILI9320的介绍我将在其它的文章中介绍。
最最重要的,也是我遇到的弄了N天的点儿就是SPI各个时序信号的极性问题,这个可以从器件的手册上看到,在S3C2410 SPI的使用(1)中的那个表中有详细的介绍, 主要是CLK的时序和数据传输时序和匹配,一共四种,读者自己区别,2410的时序图和器件的时序图比较就可得到。
今天先写到这里,晚了,饿了,回家了。哦了