各位大虾:
小弟近日调试SD,使用912的SPI访问,遇到了麻烦!自己修改了一个网上下的驱动(周立功的),修改了相关的接口函数.可是,SD就是没有回应.
谁有相关的经验,帮帮我!或者把你的源代码发到我邮箱:fdy_001@163.com
不甚感激!
还是说说你是如何做的吧;不然自己用示波器看看波形自己
即使有人给了你个源程序,你还是可能遇到这样的问题,到时候可能还是不知所措;不如趁这个机会提高一下自己。
另STF好像做过,你不妨提出些问题,也许它能帮你。
spi访问SD,用什么模式?
我访问EEPROM m95080可以,但是访问SD卡不行,SD没有回应,估计是数据格式不对!需要怎么设置?
我没有找到SD协议的时序.
你不是有源程序吗?分析跟踪一下应该能找到答案吧
我们还没有做过,暂时帮不上忙。
有其他网友做过吗?
问题应该不大!
我们的SD卡接口已经调试成功了,用SSP接口(SPI模式),移植的是ZLG的SD卡模块.配置
的时候要注意的几个问题.
1.配置SSP时SSP0_CLK,SSP0_MOSI不要设置GPIO_IPConnected_Enable,而SSP0_MISO一定要设置.否则收发数据可能会有问题.这个问题在用nSS线去做SD卡片选时肯定会有.
2.SD卡初始化时要按要求设低SSP的速率<400K
3.SSP收数据时要注意先清除FIFO,因为ZLG的SD卡读写模块是用于LPC系列,而LPC系列SPI接口很多都是没有FIFO的,所以他们的软件包里没有这个问题.
4.可以参考Keil for ARM工具附带的例程中的一个SD文件系统的例程.在下面这个目录
C:KeilARMRV30RTLBoardsKeilMCBSTR9SD_File
希望你把问题描述更清楚一些,是初始化不成功?命令无响应?还是其他的现象.这样他们STF的人就好分析问题.
高手帮忙看看,我把代码贴出来,具体现象也描述了一下
我采用买开发板自带的SSP访问SPI口EEPROM的例子时,可以正确访问EEPROM.说明SSP口正常.
当我接上SD卡,发送CMD0,应该收到0x01,实际收到的尽是0xFF.
于是不停的发数据,用示波器观察,SCLK为328KHz,MOSI有数据输出.波形为时钟的上升沿数据稳定,便于SD卡锁存.
硬件是这样连接的:SCLK,MISO,MOSI分别对应接SD.5,SD.7,SD.2, NSS接到SD.1.
我是将NSS配置为普通IO片选的.
是不是应该将 NSS配置为NSS,接到3.3V,然后用另外的一个IO来做片选?
IO配置程序如下:
/* SSP0 pins Config */
GPIO_DeInit(GPIO5);
/*Gonfigure SSP0_CLK, SSP0_MOSI pins */
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
//GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt2 ;
GPIO_Init (GPIO5, &GPIO_InitStructure);
/*Configure P5.7*/
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinOutput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull ;
GPIO_InitStructure.GPIO_Alternate = GPIO_OutputAlt1 ;
GPIO_Init (GPIO5, &GPIO_InitStructure);
GPIO_WriteBit(GPIO5,GPIO_Pin_7,(BitAction)1);
/*Gonfigure SSP0_MISO pin GPIO5.6*/
GPIO_StructInit(&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Direction = GPIO_PinInput;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStructure.GPIO_Type = GPIO_Type_PushPull;
GPIO_InitStructure.GPIO_IPConnected = GPIO_IPConnected_Enable;
GPIO_InitStructure.GPIO_Alternate = GPIO_InputAlt1;
GPIO_Init (GPIO5, &GPIO_InitStructure);
SSP配置:
/* SSP0 configuration */
SSP_DeInit(SSP0);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master;
SSP_InitStructure.SSP_CPOL = SSP_CPOL_High;
// SSP_InitStructure.SSP_CPOL = SSP_CPOL_Low;
SSP_InitStructure.SSP_CPHA = SSP_CPHA_2Edge;
SSP_InitStructure.SSP_DataSize = SSP_DataSize_8b;
SSP_InitStructure.SSP_ClockRate = 100;
SSP_InitStructure.SSP_ClockPrescaler = 2; // must be even
SSP_Init(SSP0, &SSP_InitStructure);
/* SSP0 enable */
SSP_Cmd(SSP0, ENABLE);
SYSCLK配置:
SCU_MCLKSourceConfig(SCU_MCLK_OSC);
SCU_PLLFactorsConfig(N,M,P);
SCU_PLLCmd(ENABLE);
while(!(SCU->SYSSTATUS&SCU_FLAG_LOCK));
SCU_MCLKSourceConfig(SCU_MCLK_PLL);//MCLK=48M
SCU_RCLKDivisorConfig(SCU_RCLK_Div4);//RCLK=12M
SCU_PCLKDivisorConfig(SCU_PCLK_Div8);//PCLK=12M/8
很奇怪了!
很奇怪了!在使用SSP功能时,NSS线可以做普通IO来用.如果你确定你的SCLK为328KHz
的话,可能就是SSP的读写出现了问题.不知到你对它的Rx FIFO是怎么处理的,如果想
收一个数据,最好先清除Rx FIFO再发送一个0xFF后读SSP0->DR就收到数据了.也有可
能是你对SD的初始化操作出现了问题,不知你是否曾经调试过SPI模式下的SD卡?先确认你的读写程序是否是对的?我在发送CMD0命令前有一个置位CS线的操作(见下).在
SD_SPIDelay()函数中不断发送0XFF,还有你可以试着将SPI的速率调得更低一点.
SPI_CS_Assert(); /* 1. 置CS为低 assert CS */
SD_SPIDelay(25); /* 2. 至少延时 74 clock delay more than 74clock*/
SPI_CS_Deassert(); /* 3. 置CS为高 dessert CS */
SD_SPIDelay(2); /* 4. 延时2(8 clock) delay 2(8 clock) */
发送CMD0命令
可以用口线模拟SPI口试一下!
如果怀疑是SSP导致的问题的话,可以考虑用I/O口线模拟SPI试一下!我也是用这种方法找到问题的.
我的配置!
我们的CPHA CPOL和速率跟你不一样.你的初始速率有些高
/* SSP0 configuration */
SSP_DeInit(SSP0);
SSP_InitStructure.SSP_FrameFormat = SSP_FrameFormat_Motorola;
SSP_InitStructure.SSP_Mode = SSP_Mode_Master; // 主从选择
SSP_InitStructure.SSP_CPOL = SSP_CPOL_High; // CPOL 时钟输出极性,仅SPI模式有效
SSP_InitStructure.SSP_CPHA = SSP_CPHA_2Edge; // CPHA 时钟输出相位,仅SPI模式有效
SSP_InitStructure.SSP_DataSize = SSP_DataSize_8b; // 数据长度为8位
SSP_InitStructure.SSP_SlaveOutput = SSP_SlaveOutput_Enable;
SSP_InitStructure.SSP_ClockPrescaler = 0xFE;
SSP_Init(SSP0, &SSP_InitStructure);
SSP_Cmd(SSP0, ENABLE);
可以初始化,写数据还是有问题!
非常的感谢hq1025,stf的帮助!
我更改了端口的初始化程序,使用周立功的代码,可以读出SD的容量,扇区数等信息,可是写了数据读出来全是0xFF或者0x00.这是为什么?
1,关于NSS,如hq1025说的,初始化为NSS后,它可做普通的IO来实现CS.这一点已
证明可以.
2,如hq1025说的,我改了接收函数为:
INT8U SPI_RecByte(void)
{
SSP_ClearFlag(SSP0, SSP_FLAG_RxTimeOut);
SSP_ClearFlag(SSP0,SSP_FLAG_RxOverrun);
SSPx->SR &= 0xFB; //
SPI_SendByte(0xFF);
/* loop while Receive FIFO is empty */
while(SSP_GetFlagStatus(SSP0,SSP_FLAG_RxFifoNotEmpty) == RESET);
//for(u16 i=0; i<65535; i++);
/* return the byte read from the SPI bus */
return((u8)SSP_ReceiveData(SSP0));//>>8);
}
3,按照STF的修改了IO口的设置.
4,初始化成功说明,通信应该没有问题.问题在于命令!
我写了512个字节到第0 块,然后读出来总是0或者0xFF.不明白究竟是写有问题,还是读有问题.我没有使用CRC.
程序如下:
for(i=0; i<512; i++)
{
Tx_Buffer = i;
}
SD_WriteBlock(0,Tx_Buffer);
//此函数发送CMD24.
SD_ReadBlock(0,Rx_Buffer);
//此函数发送CMD17.
请问:读写的时候,还应该注意什么?
是不是WP的问题?
我好像没有碰到这样的问题,是不是WP的问题?ZLG_SD软件包里面的SD_ChkCardWP()会检测WP信号,写块时如果不通过的话就会跳出来,写操作不会完成.你读出来的数据是不是一直固定为0xFF或0x00?还是不确定的数据?如果前面的初始化命令可以成功,那么同样的软件包里面的其他命令没有理由不能操作.试一下这个SPI操作函数:
void SPI_SendByte(INT8U byte)
{
while ((SSP0->SR & TNF) == 0);
SSP0->DR = byte;
/* Wait if RNE cleared, Rx FIFO is empty. */
while ((SSP0->SR & RNE) == 0);
byte = SSP0->DR;
}
INT8U SPI_RecByte(void)
{
u8 byte;
/* Wait if TNF cleared, Tx FIFO is full. */
while ((SSP0->SR & TNF) == 0);
SSP0->DR = 0xFF;
/* Wait if RNE cleared, Rx FIFO is empty. */
while ((SSP0->SR & RNE) == 0);
byte = SSP0->DR;
return (byte);
}
已经成功了,谢谢啊!
现在已经可以读写了!
哎,原来还是发送接受函数的问题!多谢多谢!
再请教一下:
现在没有用CRC,我在读数据的时候,有时候读出来的数据是错误的,差不多3到4次错一次.这正常吗?
应该怎么办? 使用CRC校验吗?