初学56F8366之SD卡读写(基于SPI模式)

来源:互联网 发布:数据结构算法 编辑:程序博客网 时间:2024/06/05 12:27

8366片内资源非常丰富,有两路SPI。其实之前一用过的一些单片机也有SPI接口,也调过一些所谓的SPI总线结构的IC,但那个时候都是用IO进行模拟的。比如,周立功的矩阵键盘管理芯片ZLG7289,这个有三个端口,SS、CLK、DIO,其IO口是双向的。这个我目前不知道如何处理,用SPI资源,只是用模拟IO口用着。再比如,U盘读写芯片CH375,这个当时是用SPCE061A调的,SPCE061A是没有SPI口的,然后还是比较偏的单片机,库什么的都没。

       SD卡是一个非常典型的SPI接口,尽管它可以工作在SD模式下。这个就要说了,SD卡(安全数码卡),9脚,总线宽度可以是1位和4位。理论可以进行104M/S的传输(SD 3.0协议)。而SPI模式下就不需要很多的引脚,按照下图接入就好。

初学56F8366之SD卡读写(基于SPI模式) - wehat1148158886 - 子诺
       上图为8个脚,其实这个卡槽为MicroSD卡的卡槽。MicroSD卡,也就是以前常说的TF卡,之后改名为MicroSD卡,其协议与SD完全兼容。可以用卡套转换为标准的9脚SD卡。上图RP6为限流电阻,觉得3.3K有些大的话,可以换为1K左右的就好。注意其供电电源为3.3V,其实SD卡的驱动电压在2.0~3.6V之间都可以。但是为了单片这边方便,一般选用3.3V。SD卡一般都会与MMC卡(多媒体卡)混淆,这个区别办法有很多,大家注意就好。
 
       首先,为了能使用SD卡,得了解下8366的SPI接口的寄存器。8366的SPI接口的寄存器有如下几个:
       SPI0_SCR  : SPI0的状态与控制寄存器。其低4为状态控制器(也就是标志位),其他为控制寄存器。控制寄存器也是一些常用
                            的。 比如,时钟极性,时钟频率,MSB方式还是LSB方式等等。
       SPI0_DSR  : SPI0的数据长度寄存器。
       SPI0_DTR  : SPI0的发送寄存器。
       SPI0_DRR  : SPI0的接受寄存器。
 
        只需要初始化这几个寄存器,就可以做到SD的读操作与写操作。经过资料的查询,SD卡一般一个数据的长度为8位,且为MSB模式(首先发送数据高位),时钟常态为高(下降沿捕捉信号)。而且,这个系统就仅有一个主机,所以要把SS口配置为GPIO口,自己进行SD的使能与禁能,且SD为低使能。基于以上资料,就可以给出SPI的初始化函数。查询SD卡资料时候,初始化SD卡时候,需要低速初始化,所以这里设定时钟为234Hz左右。然后后面写了个高速SD卡模式。
      
//低速初始化
void SPI_Init(void)
{
    GPIO_E_PER &= ~(SD_SS);   //SS端口开启为GPIO
   
    GPIO_E_PUR |=  SD_SS + SD_CLK + SD_MOSI + SD_MISO;       //上拉电阻
    GPIO_E_DDR |=  SD_SS + SD_CLK + SD_MOSI;   //输出
    GPIO_E_DDR &= ~SD_MISO;     //输入
   
    GPIO_E_DR  |=  SD_CLK + SD_MOSI;   //时钟与数据均拉高
    GPIO_E_DR  |=  SD_SS;        //使能拉高,禁止
  
    SPI0_SCR   &= ~0x0020;       //SPI禁能
    SPI0_DSR    =  0x0007;       //数据长度为8位
    SPI0_SCR    =  0xE180;       //主机模式,时钟常态高,接收中断关闭,MSB方式发送,256分频
    (void)SPI0_SCR;
    (void)SPI0_DRR;              //刷新标志位与接收寄存器
    SPI0_SCR   |=  0x0020;       //SPI使能  
}
     
//设置到高速模式
void SPI_High_Speed(void)
{
    SPI0_SCR   &= ~0xC000;       //设置波特率为15M,总线4分频 
}
 
还有SD卡读写函数,我没采用中断式的。
//数据发送
void SPI_Send_Date(unsigned int Data)
{
    while(!(SPI0_SCR & SPI0_SCR_SPTE_MASK));   //等待发射缓存区空
    SPI0_DTR = Data;
}
 
//数据接收
unsigned char SPI_Get_Date(void)
{
    while(!(SPI0_SCR & SPI0_SCR_SPTE_MASK));   //等待发射缓存区空
    SPI0_DTR = 0xFF;
    while(!(SPI0_SCR & SPI0_SCR_SPRF_MASK));   //等待接收区
    return SPI0_DRR; 
}

 这样就可以完成SD卡的最基本的读写函数了。

 

待续......

原创粉丝点击