- /*------------------------- 硬件配置 -------------------------*/
- #include <xc.h>
- #include <stdint.h>
- #pragma config FNOSC = FRCPLL // 使用FRC振荡器+PLL
- // SPI引脚配置(使用RP引脚重映射)
- #define SD_CS _LATB9 // CS: RB9
- #define SD_CS_TRIS _TRISB9
- #define SPI_MOSI _RP10R = 0b0011 // SDO1映射到RP10
- #define SPI_MISO 11 // SDI1使用RP11
- #define SPI_SCK _RP9R = 0b0011 // SCK1映射到RP9
- /*------------------------- SD驱动层 -------------------------*/
- #define CMD0 0x40
- #define CMD8 0x48
- #define ACMD41 0x69
- #define CMD16 0x50
- #define CMD17 0x51
- #define CMD24 0x58
- uint8_t SD_SendCmd(uint8_t cmd, uint32_t arg) {
- SPI1_Transfer(cmd);
- SPI1_Transfer(arg >> 24);
- SPI1_Transfer(arg >> 16);
- SPI1_Transfer(arg >> 8);
- SPI1_Transfer(arg);
- SPI1_Transfer((cmd == CMD0) ? 0x95 : (cmd == CMD8) ? 0x87 : 0x01);
- for(uint8_t retry=0; retry<10; retry++) {
- uint8_t res = SPI1_Transfer(0xFF);
- if((res & 0x80) == 0) return res;
- }
- return 0xFF;
- }
- uint8_t SD_Init(void) {
- SD_CS_TRIS = 0; // 配置CS为输出
- SD_CS = 1; // CS置高
-
- // SPI初始化(主模式,8MHz)
- SPI1CON1 = 0;
- SPI1CON1bits.MSTEN = 1; // 主模式
- SPI1CON1bits.MODE16 = 0; // 8位模式
- SPI1CON1bits.PPRE = 3; // 预分频 1:1
- SPI1CON1bits.SPRE = 6; // 主分频 1:2
- SPI1STATbits.SPIEN = 1; // 使能SPI
-
- // 发送至少74个时钟脉冲
- for(uint8_t i=0; i<10; i++) SPI1_Transfer(0xFF);
-
- // CMD0复位
- if(SD_SendCmd(CMD0, 0) != 0x01) return 1;
-
- // 初始化流程(支持SDv2)
- uint8_t resp = SD_SendCmd(CMD8, 0x1AA);
- if(resp == 0x01) {
- for(uint8_t i=0; i<4; i++) SPI1_Transfer(0xFF); // 丢弃响应
- do {
- resp = SD_SendCmd(ACMD41, 0x40000000);
- } while(resp != 0x00);
- } else return 2;
-
- // 设置块长度(512字节)
- if(SD_SendCmd(CMD16, 512) != 0x00) return 3;
-
- return 0;
- }
- /*------------------------- FatFs集成 ------------------------*/
- #include "ff.h" // FatFs R0.15
- DSTATUS disk_initialize (BYTE pdrv) {
- return (SD_Init() == 0) ? 0 : STA_NOINIT;
- }
- DRESULT disk_read (BYTE pdrv, BYTE* buff, LBA_t sector, UINT count) {
- SD_CS = 0;
- for(UINT i=0; i<count; i++) {
- if(SD_SendCmd(CMD17, sector+i) != 0x00) {
- SD_CS = 1;
- return RES_ERROR;
- }
- while(SPI1_Transfer(0xFF) != 0xFE); // 等待数据令牌
- for(uint16_t j=0; j<512; j++) buff[j] = SPI1_Transfer(0xFF);
- SPI1_Transfer(0xFF); // 丢弃CRC
- SPI1_Transfer(0xFF);
- }
- SD_CS = 1;
- return RES_OK;
- }
- /*------------------------- 使用示例 ------------------------*/
- void main(void) {
- FATFS fs;
- FIL fil;
-
- if(f_mount(&fs, "", 1) == FR_OK) {
- f_open(&fil, "test.txt", FA_WRITE | FA_CREATE_ALWAYS);
- f_printf(&fil, "PIC24 SD Card Test @2025");
- f_close(&fil);
- }
- while(1);
- }
- // SPI数据传输函数(必须内联优化)
- static inline uint8_t SPI1_Transfer(uint8_t data) {
- SPI1BUF = data;
- while(!SPI1STATbits.SPIRBF);
- return SPI1BUF;
- }
|