laocuo1142 发表于 2025-2-17 20:00

关于PIC24FJ256GB206读写sd卡的程序

有会mplab的吗,关于PIC24FJ256GB206读写sd卡的程序,网上没有找到教程,请问有会的吗

huahuagg 发表于 2025-2-21 18:14

/*------------------------- 硬件配置 -------------------------*/
#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_MISO11               // SDI1使用RP11
#define SPI_SCK   _RP9R = 0b0011   // SCK1映射到RP9

/*------------------------- SD驱动层 -------------------------*/
#define CMD00x40
#define CMD80x48
#define ACMD41 0x69
#define CMD160x50
#define CMD170x51
#define CMD240x58

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 = 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;
}

花间一壶酒sd 发表于 2025-2-23 00:12

如果读写失败,检查初始化流程是否正确。

heisexingqisi 发表于 2025-2-24 11:20

先搞清楚这个读写卡的底层函数,一般网上有IO口模拟的,可以先试试

guijial511 发表于 2025-2-24 21:00

SD卡不是SDIO接口吗?代码是用的SPI接口啊。

自动化陈稳 发表于 2025-4-27 01:12

SD卡通常使用 SPI 接口进行通信,因此你需要设置 SPI 和适当的文件系统(通常是 FAT16/32)来读写 SD 卡。

自动化陈稳 发表于 2025-4-27 01:15

FatFS 是一个开源库,支持在嵌入式系统中读取和写入 FAT 文件系统。

野玫瑰 发表于 2025-8-29 12:16

PIC24FJ256GB206 读写 SD 卡需配置 SPI 接口,初始化 SD 卡为 SPI 模式,发送 CMD 命令检测卡类型。读操作通过 CMD17 发送地址,接收数据块;写操作以 CMD24 发送地址和数据。需处理 CRC 校验,用中断或轮询循环检测状态,确保数据正确传输,可参考 Microchip 的 MPLAB Harmony 库示例。
页: [1]
查看完整版本: 关于PIC24FJ256GB206读写sd卡的程序