AVR128DB28与SD卡SPI通信异常问题求助
AVR128DB28与SD卡SPI通信CMD0响应异常问题
开发背景与问题现象
使用Microchip Studio以C语言开发AVR128DB28单片机与SD卡的SPI通信,通过MPLAB SNAP经UPDI完成编程。程序改编自SD卡SPI接口教程,核心异常点如下:
- 发送CMD0(用于将SD卡切换至空闲状态)后,预期获得R1格式的
0x01响应,实际返回0 - 断电重启SD卡后,返回值为
0b00010111,对应标志位包括:擦除序列错误、非法命令、擦除重置、处于空闲状态
完整代码
/* * AVR128_sdcardTEST.c * * Created: 15.04.2024 14:52:31 * Author : Komputer_3 */ #include <avr/io.h> #include <avr/delay.h> #include <stdint-gcc.h> #define SPI_PORT PORTA #define MOSI PIN4_bm #define MISO PIN5_bm #define SCK PIN6_bm #define CS PIN7_bm #define CS_ENABLE() SPI_PORT.OUTCLR = CS #define CS_DISABLE() SPI_PORT.OUTSET = CS #define CMD0 0 #define CMD0_ARG 0x00000000 #define CMD0_CRC 0x94 uint8_t SPI_transfer(uint8_t data){ SPI0.DATA = data; while (!(SPI0.INTFLAGS & SPI_IF_bm)); return SPI0.DATA; } void SDC_powerUp(void){ CS_DISABLE(); _delay_ms(1); for(uint8_t i=0; i<10; i++){ SPI_transfer(0xff); } CS_DISABLE(); SPI_transfer(0xff); } void SDC_command(uint8_t cmd, uint32_t arg, uint8_t crc){ SPI_transfer((cmd & 127) | 64); //0b01xxxxxx SPI_transfer((uint8_t)(arg >> 24)); SPI_transfer((uint8_t)(arg >> 16)); SPI_transfer((uint8_t)(arg >> 8)); SPI_transfer((uint8_t)(arg)); SPI_transfer(crc | 1); //0bxxxxxxx1 } uint8_t SDC_readRes1(){ uint8_t i = 0, res1; // 轮询直到收到有效数据 while((res1 = SPI_transfer(0xFF)) == 0xFF){ // 异常:返回0而非预期的1 i++; // 若连续8字节无数据则退出 if(i > 8) break; } return res1; } uint8_t SD_goIdle(){ // 拉低CS前发送空字节 SPI_transfer(0xFF); CS_ENABLE(); SPI_transfer(0xFF); // 发送CMD0命令 SDC_command(CMD0, CMD0_ARG, CMD0_CRC); // 读取响应 uint8_t res1 = SDC_readRes1(); // 释放CS后发送空字节 SPI_transfer(0xFF); CS_DISABLE(); SPI_transfer(0xFF); return res1; } int main(void) { _PROTECTED_WRITE(CLKCTRL.OSCHFCTRLA, (CLKCTRL.OSCHFCTRLA & (~CLKCTRL_FRQSEL_gm)) | CLKCTRL_FRQSEL_24M_gc); SPI_PORT.DIRSET = MOSI | SCK | CS; SPI_PORT.DIRCLR = MISO; PORTD.DIRSET = PIN1_bm | PIN2_bm | PIN3_bm | PIN4_bm | PIN5_bm; SPI0.CTRLA = (1 << SPI_MASTER_bp) | // 主机模式 (0 << SPI_DORD_bp) | /* 数据发送方向: 0-MSB优先, 1-LSB优先 */ (1 << SPI_CLK2X_bp) | /* 双倍速度模式 */ SPI_PRESC_DIV4_gc | /* 预分频器配置 */ SPI_ENABLE_bm; /* 使能SPI模块 */ SPI0.CTRLB = SPI_SSD_bm | SPI_MODE_0_gc; /* 配置Slave Disable引脚:非多主机模式下需设置此位,此时CS/SS引脚不受SPI寄存器自动控制,由手动引脚电平切换实现片选 */ _delay_ms(500); SDC_powerUp(); uint8_t res1 = SD_goIdle(); if(res1 == 1){ PORTD.OUTSET = PIN5_bm; } else{ PORTD.OUTSET = res1 & 0b00001111; _delay_ms(1500); PORTD.OUTCLR = 0b00001111; PORTD.OUTSET = (res1 >> 4) & 0b00001111; } while (1) { } }
参考文档
AVR128DB28官方芯片数据手册
内容的提问来源于stack exchange,提问作者n0rmi
相关产品推荐
相关产品推荐

