nrf51822蓝牙SPI对microSD卡读写

来源:互联网 发布:手机网页小游戏源码 编辑:程序博客网 时间:2024/05/28 11:50

          基于nrf51822 SDK10的蓝牙串口工程 ,增加SPI的资源文件到工程,定义SPI0使能,以及定义IO口,和CS引脚电平,新建drv_sd_api.c文件如下即可在主函数调用接口函数对SD卡进行操作,此接口函数是官方提供的一个我只是修改一下,使用前对SD卡的指令以及一些注意事项说明如下:

SD卡的命令格式如下,6字节共48位,传输时最高位(MSB)先传输:


    SD卡的command(命令)占6 bit,一般叫CMDx或ACMDx,比如CMD1就是1,CMD13就是13,ACMD41就是41,依此类推。Command Argument(命令参数)占4 byte,并不是所有命令都有参数,没有参数的话该位一般就用置0。最后一个字节由7 bit CRC校验位和1 bit停止位组成。在SPI模式下,CRC是被忽略的,可以都置1或置0.但是发送CMD0时要记得加上CRC,即最后1字节为0x95,因为发送CMD0时还未进入SPI模式。


常用的指令解释如下:


关于SD卡SPI和command的发送要注意以下几点:
    1.SD卡的SPI总线,在读入数据时SD卡的SPI是CLK的上升沿输入锁存,输出数据也是在上升沿。 
    2.向SD卡写入一个CMD或者ACMD指令的过程是这样的: 首先使CS为低电平,SD卡使能;其次在SD卡的Din写入指令;写入指令后还要附加8个填充时钟,是SD卡完成内部操作;之后在SD卡的Dout上接受回应;回应接受完毕使CS为低电平,再附加8个填充时钟。 

    3.在SD卡的Din没有数据写入时,应使Din保持高电平。



#include "nrf_gpio.h"#include "nrf_drv_spi.h"#include "nrf_drv_common.h"#include "nrf_assert.h"#include "app_util_platform.h"#include "bsp.h"#include "app_trace.h"#include "string.h"#define TX_RX_MSG_LENGTH         100#define GO_IDLE_STATE            0#define SEND_OP_COND             1#define SEND_CSD                 9#define STOP_TRANSMISSION        12#define SEND_STATUS              13#define SET_BLOCK_LEN            16#define READ_SINGLE_BLOCK        17#define READ_MULTIPLE_BLOCKS     18#define WRITE_SINGLE_BLOCK       24#define WRITE_MULTIPLE_BLOCKS    25#define ERASE_BLOCK_START_ADDR   32#define ERASE_BLOCK_END_ADDR     33#define ERASE_SELECTED_BLOCKS    38#define CRC_ON_OFF               59#define MMCSD_PIN_SELECT   30#define ON     1#define OFF    0uint8_t sd_cmd1[9]  = {0xFF,0x40,0x00,0x00,0x00,0x00,0x95,0xFF,0xFF};uint8_t sd_cmd2[13] = {0xFF,0x48,0x00,0x00,0x01,0xAA,0x87,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};uint8_t sd_cmd3[8]  = {0xFF,0x77,0x00,0x00,0x00,0x00,0xFF,0xFF};uint8_t sd_cmd4[9]  = {0xFF,0x69,0x40,0x00,0x00,0x00,0xFF,0xFF,0xFF};uint8_t sd_cmd5[10] = {0xFF,0x7A,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF};uint32_t *SDCard_spi;uint32_t startBlock;uint32_t totalBlocks;   #if (SPI0_ENABLED == 1)static const nrf_drv_spi_t m_spi_master_0 = NRF_DRV_SPI_INSTANCE(0);#endifstatic void spi_master_init(nrf_drv_spi_t const * p_instance, bool lsb){    uint32_t err_code = NRF_SUCCESS;    nrf_drv_spi_config_t config =    {        .ss_pin       = NRF_DRV_SPI_PIN_NOT_USED,        .irq_priority = APP_IRQ_PRIORITY_LOW,        .orc          = 0xCC,        .frequency    = NRF_DRV_SPI_FREQ_500K,        .mode         = NRF_DRV_SPI_MODE_0,        .bit_order    = (lsb ?            NRF_DRV_SPI_BIT_ORDER_LSB_FIRST : NRF_DRV_SPI_BIT_ORDER_MSB_FIRST),    };    #if (SPI0_ENABLED == 1)    if (p_instance == &m_spi_master_0)    {        config.sck_pin  = SPIM0_SCK_PIN;        config.mosi_pin = SPIM0_MOSI_PIN;        config.miso_pin = SPIM0_MISO_PIN;        err_code = nrf_drv_spi_init(p_instance, &config,        NULL);    }    else    #endif // (SPI0_ENABLED == 1)    APP_ERROR_CHECK(err_code);}static void spi_send_recv(nrf_drv_spi_t const * p_instance,                          uint8_t * p_tx_data,                          uint8_t * p_rx_data,                          uint16_t  len){//     // Initalize buffers.//     init_buf(p_tx_data, p_rx_data, len);    uint32_t err_code = nrf_drv_spi_transfer(p_instance,        p_tx_data, len, p_rx_data, len);    APP_ERROR_CHECK(err_code);}uint8_t spi_xfer(uint8_t data){uint8_t spi_txbuf[1];uint8_t spi_rxbuf[1];spi_txbuf[0]=data;spi_send_recv(&m_spi_master_0 , spi_txbuf, spi_rxbuf,1);return spi_rxbuf[0];}void mmcsd_select(){   nrf_gpio_pin_clear(MMCSD_PIN_SELECT);}void mmcsd_deselect(){   nrf_gpio_pin_set(MMCSD_PIN_SELECT);   spi_xfer( 0xFF);}uint8_t send_spi(uint8_t spi_msg){   static uint8_t spi_rcv;   spi_rcv=spi_xfer( spi_msg);      return spi_rcv;}uint8_t Send_Command(uint8_t cmd[], uint8_t size){   static uint8_t p;   static uint8_t resp;   //mmcsd_select();   for(p=0;p<size;p++)   {      resp=send_spi(cmd[p]);   }   //mmcsd_deselect();   return resp;}uint8_t SD_sendCommand(uint8_t cmd, uint32_t arg){uint8_t response, retry=0;mmcsd_select(); spi_xfer((cmd & 0x3f )| 0x40); //send command, first two bits always '01'spi_xfer(arg>>24);spi_xfer(arg>>16);spi_xfer(arg>>8);spi_xfer(arg);spi_xfer(0x95);while((response = spi_xfer(0xFF)) == 0xff) //wait response if(retry++ > 0xfe) break; //time out errorreturn response; //return state} uint8_t SD_init(void){uint8_t i, response, retry=0 ; mmcsd_deselect();     for(i=0;i<16;i++)            {                //SPI_transmit(0xff);                spi_xfer(0xFF);            }             mmcsd_select(); do{ response = SD_sendCommand(GO_IDLE_STATE, 0);//send 'reset & go idle' command retry++; if(retry>0xfe)            {                  mmcsd_deselect();               printf("\rSD init fail..");               return 1;            }//time out} while(response != 0x01);mmcsd_deselect();                 mmcsd_select();retry = 0;do{response = SD_sendCommand(SEND_OP_COND, 0); //activate card's initialization processresponse = SD_sendCommand(SEND_OP_COND, 0); //resend command (for compatibility with some cards)retry++;if(retry>0xFE) return 1; //time out}while(response);SD_sendCommand(CRC_ON_OFF, OFF); //disable CRC; deafault - CRC disabled in SPI modeSD_sendCommand(SET_BLOCK_LEN, 512); //set block size to 512return 0; //normal return    }        bool Initialize_SDHC(void){bool done=0;static uint8_t rcv;static uint16_t count=0;//Send Dummys nrf_gpio_pin_set(MMCSD_PIN_SELECT);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   spi_xfer( 0xFF);   nrf_gpio_pin_clear(MMCSD_PIN_SELECT);   mmcsd_deselect();mmcsd_select();Send_Command(sd_cmd1,9);mmcsd_deselect();mmcsd_select();Send_Command(sd_cmd2,13);mmcsd_deselect();while(!done){ mmcsd_select(); rcv=Send_Command(sd_cmd3,8); if (rcv == 0x00 ){done=1;} else{ mmcsd_deselect();}  mmcsd_select(); rcv=Send_Command(sd_cmd4,9); if (rcv == 0x00 ){done=1;} else{ mmcsd_deselect();}  count++; if(count==5000){return 1;}}mmcsd_select();if(Send_Command(sd_cmd5,10) == 0xC0){ send_spi(0xFF); send_spi(0xFF); send_spi(0xFF); send_spi(0xFF);  return 0;}else {mmcsd_deselect(); return 1;}}    uint8_t SD_Card_Initialize(void){spi_master_init(&m_spi_master_0,false);nrf_gpio_cfg_output(MMCSD_PIN_SELECT);nrf_gpio_pin_set(MMCSD_PIN_SELECT);if(SD_init()){if(Initialize_SDHC())return 0;else return 2;//SDHC card}else return 1;// SD card}uint8_t SD_writeSingleBlock(uint32_t startBlock,const uint8_t *data){uint8_t response;uint16_t i, retry=0;response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock<<9); //write a Block commandif(response != 0x00) //check for SD status: 0x00 - OK (No flags set)return response;mmcsd_select(); //spi_xfer( 0xFF)spi_xfer(0xfe);     //Send start block token 0xfe (0x11111110)for(i=0; i<512; i++)    //send 512 bytes data{            printf("%c",*(data+i));           spi_xfer(*(data+i));     }spi_xfer(0xff);     //transmit dummy CRC (16-bit), CRC is ignored herespi_xfer(0xff);response = spi_xfer( 0xFF);if( (response & 0x1f) != 0x05) //response= 0xXXX0AAA1 ; AAA='010' - data accepted{                              //AAA='101'-data rejected due to CRC errormmcsd_deselect();              //AAA='110'-data rejected due to write errorreturn response;}while(!spi_xfer( 0xFF)) //wait for SD card to complete writing and get idleif(retry++ > 0xfffe){mmcsd_deselect(); return 1;}mmcsd_deselect();spi_xfer(0xFF);   //just spend 8 clock cycle delay before reasserting the CS linemmcsd_select();          //re-asserting the CS line to verify if card is still busywhile(!spi_xfer( 0xFF)) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe){mmcsd_deselect(); return 1;}mmcsd_deselect();return 0;}uint8_t SD_readSingleBlock(uint32_t startBlock,uint8_t *data){uint8_t response;uint16_t i, retry=0;response = SD_sendCommand(READ_SINGLE_BLOCK, startBlock<<9); //read a Block command//block address converted to starting address of 512 byte Blockif(response != 0x00) //check for SD status: 0x00 - OK (No flags set)return response;mmcsd_select(); while(spi_xfer( 0xFF) != 0xFE) //wait for start block token 0xfe (0x11111110)if(retry++ > 0xfffe){mmcsd_deselect(); return 1;} //return if time-outfor(i=0; i<512; i++) //read 512 bytes{*data = spi_xfer( 0xFF);            printf("%c",*data);             data++;       }spi_xfer( 0xFF); //receive incoming CRC (16-bit), CRC is ignored herespi_xfer( 0xFF);spi_xfer( 0xFF); //extra 8 clock pulsesmmcsd_deselect();return 0;}uint8_t SD_WriteMultiBlock(uint32_t startBlock,const uint8_t *data ,uint32_t count){uint8_t response;uint16_t i, retry=0;response = SD_sendCommand(WRITE_SINGLE_BLOCK, startBlock<<9); //write a Block commandif(response != 0x00) //check for SD status: 0x00 - OK (No flags set)return response;    do{mmcsd_select(); //spi_xfer( 0xFF)spi_xfer(0xfc);     //Send start block token 0xfcfor(i=0; i<512; i++)    //send 512 bytes dataspi_xfer(*(data+i));spi_xfer(0xff);     //transmit dummy CRC (16-bit), CRC is ignored herespi_xfer(0xff);response = spi_xfer( 0xFF);if( (response & 0x1f) != 0x05) //response= 0xXXX0AAA1 ; AAA='010' - data accepted{                              //AAA='101'-data rejected due to CRC errormmcsd_deselect();              //AAA='110'-data rejected due to write errorreturn response;}while(!spi_xfer( 0xFF)) //wait for SD card to complete writing and get idleif(retry++ > 0xfffe){mmcsd_deselect(); return 1;}    }while(--count);mmcsd_deselect();spi_xfer(0xFd);   //just spend 8 clock cycle delay before reasserting the CS linemmcsd_select();          //re-asserting the CS line to verify if card is still busywhile(!spi_xfer( 0xFF)) //wait for SD card to complete writing and get idle if(retry++ > 0xfffe){mmcsd_deselect(); return 1;}mmcsd_deselect();return 0;}uint8_t SD_ReadMultiBlock(uint32_t startBlock, uint8_t* data, uint32_t count){uint8_t response;uint16_t i, retry=0;response = SD_sendCommand(READ_MULTIPLE_BLOCKS, startBlock<<9); //block address converted to starting address of 512 byte Blockif(response != 0x00) //check for SD status: 0x00 - OK (No flags set)return response;            do{mmcsd_select(); while(spi_xfer( 0xFF) != 0xFE) //wait for start block token 0xfe (0x11111110)if(retry++ > 0xfffe){mmcsd_deselect(); return 1;} //return if time-out                    retry=0;            for(i=0; i<512; i++) //read 512 bytes        {            *data = spi_xfer( 0xFF);            printf("%c",*data);            data++;        }   spi_xfer( 0xFF); //receive incoming CRC (16-bit), CRC is ignored here   spi_xfer( 0xFF);    }while( --count );           retry=0;         response = SD_sendCommand(STOP_TRANSMISSION, 0);    if(response!=0x00)    {             printf("SD_ReadMultiBlock  fail....");    }//spi_xfer( 0xFF); //extra 8 clock pulsesmmcsd_deselect();return 0;}uint8_t SD_GetCSD(uint8_t *csd_data){    uint8_t r1;    uint16_t i, retry=0;        r1=SD_sendCommand(SEND_CSD,0);//·¢CMD9ÃüÁ¶ÁCSD    if(r1)return r1;  //û·µ»ØÕýÈ·Ó¦´ð£¬ÔòÍ˳ö£¬±¨´í  mmcsd_select(); while(spi_xfer( 0xFF) != 0xFE) //wait for start block token 0xfe (0x11111110)if(retry++ > 0xfffe){mmcsd_deselect(); return 1;} //return if time-outfor(i=0; i<16; i++) //read 16  bytes{*(csd_data+i) = spi_xfer( 0xFF);}spi_xfer( 0xFF); //receive incoming CRC (16-bit), CRC is ignored herespi_xfer( 0xFF);spi_xfer( 0xFF); //extra 8 clock pulsesmmcsd_deselect();    return 0;}  uint32_t SD_GET_SD_SIZE(void){    uint8_t csd[16];    uint32_t Capacity;    uint8_t r1;    uint16_t i;uint16_t temp;      //È¡CSDÐÅÏ¢£¬Èç¹ûÆÚ¼ä³ö´í£¬·µ»Ø0    if(SD_GetCSD(csd)!=0) return 0;        //Èç¹ûΪSDHC¿¨£¬°´ÕÕÏÂÃ淽ʽ¼ÆËã    if((csd[0]&0xC0)==0x40)    {      Capacity=((uint32_t)csd[8])<<8;Capacity+=(uint32_t)csd[9]+1;         Capacity = (Capacity)*1024;//µÃµ½ÉÈÇøÊýCapacity*=512;//µÃµ½×Ö½ÚÊý       }    else    {        i = csd[6]&0x03;    i<<=8;    i += csd[7];    i<<=2;    i += ((csd[8]&0xc0)>>6);        //C_SIZE_MULT    r1 = csd[9]&0x03;    r1<<=1;    r1 += ((csd[10]&0x80)>>7);     r1+=2;//BLOCKNR    temp = 1;    while(r1)    {    temp*=2;    r1--;    }    Capacity = ((uint32_t)(i+1))*((uint32_t)temp);         // READ_BL_LEN    i = csd[5]&0x0f;        //BLOCK_LEN    temp = 1;    while(i)    {    temp*=2;    i--;    }        //The final result    Capacity *= (uint32_t)temp;//×Ö½ÚΪµ¥Î»       }    return (uint32_t)Capacity;}




0 0