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
- nrf51822蓝牙SPI对microSD卡读写
- nrf51822蓝牙之软件模拟spi各种模式
- nrf51822 --- spi 通信
- nRF51822 SPI 驱动 ADXL362
- 51单片机 指纹模块 MicroSD卡使用和SPI协议的使用5(1)
- 51单片机 指纹模块 MicroSD卡使用和SPI协议的使用5(2)
- 51单片机 指纹模块 MicroSD卡使用和SPI协议的使用5(3)
- 蓝牙4.0芯片 nRF51822
- BlueTooth: nRF51822蓝牙芯片
- nrf51822 --- 修改蓝牙名字
- 蓝牙nrf51822空中升级
- nrf51822 断开蓝牙连接
- 蓝牙nrf51822空中升级
- NRF51822制作蓝牙抓包器
- SPI对外部w25Q64的读写
- STM32 SPI读写SD卡
- 蓝牙4.0芯片nrf51822资料
- nrf51822蓝牙触摸屏驱动总结
- 一天一条Linux指令-perror
- Linux下比较全面的监控工具dstat
- my bank
- From表单提交刷新页面?
- Handler,MessageQueue,Message,Looper源码分析
- nrf51822蓝牙SPI对microSD卡读写
- js--事件--通用的事件侦听器函数
- cocoapods 使用
- make menuconfig错误的解决办法
- 我的docker笔记
- 数组去重和splice() 方法split()跟join()数组方法pop() push() unshift() shift()
- The APR based Apache Tomcat Native library ...异常
- 2016年提高组模拟试题(20161105) 方程式
- VMWare打开Ubuntu没反应