打印
[PIC32/SAM]

关于PIC24FJ256GB206读写sd卡的程序

[复制链接]
675|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
laocuo1142|  楼主 | 2025-2-17 20:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
有会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_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;
}

使用特权

评论回复
板凳
花间一壶酒sd| | 2025-2-23 00:12 | 只看该作者
如果读写失败,检查初始化流程是否正确。

使用特权

评论回复
地板
heisexingqisi| | 2025-2-24 11:20 | 只看该作者
先搞清楚这个读写卡的底层函数,一般网上有IO口模拟的,可以先试试

使用特权

评论回复
5
guijial511| | 2025-2-24 21:00 | 只看该作者
SD卡不是SDIO接口吗?代码是用的SPI接口啊。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1283

主题

6007

帖子

14

粉丝