SDSC карта памяти для STM32F103C8T6
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
SDSC карта памяти для STM32F103C8T6
Доброго времени суток. Пытаюсь подключить Micro SD карточку на 256 МБ к STM32. Однако, оказалось это весьма не просто. Вообще, основная проблема в том, что карты бывают разных видов в зависимости от ёмкости - SDSC, SDHC, и т.д. К первому типу относятся карты до 2 ГБ (как раз мой случай), и все бы ничего, но большинство разработчиков забили на поддержку таких карт. Вроде есть проекты на другие МК, но портировать их в Cube IDE пока не удалось. Сложное это дело, карты памяти читать... Нашел проект, реализованный на Petit FatFS. Он вроде обещает работу с мелкими карточками, но на STM его нет, а вдумчивое чтение и перенос кода на Cube пока не принесло успехов.
Может, есть у кого собранный в Cube рабочий проект чтения карт памяти SDSC для STM32F103C8T6?
Может, есть у кого собранный в Cube рабочий проект чтения карт памяти SDSC для STM32F103C8T6?
- Реклама
- HardWareMan
- Мучитель микросхем
- Сообщения: 431
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: SDSC карта памяти для STM32F103C8T6
Я реализовал свой собственный инит карты по этому чарту:

А потом просто использовал FatFS от Чена, причём в моей версии пришлось исправлять ошибку преобразования адреса в сектор (и наоборот) потому что для XC должен использоваться uint64_t а Чен тогда использовал только uint32_t. Это было 10 лет назад, в современных версиях вроде как это уже пофикшено.

А потом просто использовал FatFS от Чена, причём в моей версии пришлось исправлять ошибку преобразования адреса в сектор (и наоборот) потому что для XC должен использоваться uint64_t а Чен тогда использовал только uint32_t. Это было 10 лет назад, в современных версиях вроде как это уже пофикшено.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
Вот где-то на этапе R1 resp все и заканчивается. Возвращает нули, хоть ты тресни
Сегодня, в 4-й день моего "приключения на 15 минут" я, все же, решил посмотреть осциллографом сигналы, которые подает код, работающий с картами от 2 гигов.
Описаний как инициализировать карту, множество. Вот например.
Дословно читаем процесс перевода карты в режим SPI.
- Подать единицу на CS.
- Подать единицу на MOSI.
- Подать 74 или более импульсов на линию CLK.
Однако, фактически CS выставляется в 0 в начальный момент времени, и всегда в единице все оставшееся время. То есть, инициализация SPI происходит при выставлении НУЛЯ на CS и ЕДИНИЦЫ во время операций чтения-записи. А в описании все наоборот... Да и по логике работы SPI CS должно быть в нуле во время обращения к устройству, а в SD картах, выходит, все строго наоборот
Сегодня, в 4-й день моего "приключения на 15 минут" я, все же, решил посмотреть осциллографом сигналы, которые подает код, работающий с картами от 2 гигов.
Описаний как инициализировать карту, множество. Вот например.
Дословно читаем процесс перевода карты в режим SPI.
- Подать единицу на CS.
- Подать единицу на MOSI.
- Подать 74 или более импульсов на линию CLK.
Однако, фактически CS выставляется в 0 в начальный момент времени, и всегда в единице все оставшееся время. То есть, инициализация SPI происходит при выставлении НУЛЯ на CS и ЕДИНИЦЫ во время операций чтения-записи. А в описании все наоборот... Да и по логике работы SPI CS должно быть в нуле во время обращения к устройству, а в SD картах, выходит, все строго наоборот
- HardWareMan
- Мучитель микросхем
- Сообщения: 431
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: SDSC карта памяти для STM32F103C8T6
А ты скорость понижаешь? Инит карты происходит строго на частоте ниже 400кГц. А ещё, я подаю не 74CLK а 256 байт (т.е. 256*8 CLK). Некоторым картам мало всего лишь 74 такта.
Спойлер
Вот мой код для 030 из этого проекта, для понимания сути, может на что-то натолкнёт:Код: Выделить всё
// Константы команд SD карты
#define CMD_LENGTH ((uint32_t) 6 ) // Размер команды
#define CARD_DATA_TOKEN ((uint8_t) 0xFE ) // Токен начала данных
#define CARD_CMD17 ((uint8_t) 0x51 ) // Команда чтения блока
#define CARD_CMD24 ((uint8_t) 0x58 ) // Команда записи блока
// CMD0: GO_IDLE_STATE
static const uint8_t CARD_CMD0[ CMD_LENGTH ] = { 0x40, 0x00, 0x00, 0x00, 0x00, 0x95 };
// CMD8: SEND_IF_COND
static const uint8_t CARD_CMD8[ CMD_LENGTH ] = { 0x48, 0x00, 0x00, 0x01, 0xAA, 0x87 };
// CMD16: SET_BLOCKLEN
static const uint8_t CARD_CMD16[ CMD_LENGTH ] = { 0x50, 0x00, 0x00, 0x02, 0x00, 0xFF };
// ACMD55: APP_CMD
static const uint8_t CARD_CMD55[ CMD_LENGTH ] = { 0x77, 0x00, 0x00, 0x00, 0x00, 0xFF };
// CMD58: READ_OCR
static const uint8_t CARD_CMD58[ CMD_LENGTH ] = { 0x7A, 0x00, 0x00, 0x00, 0x00, 0xFF };
// ACMD41: APP_SEND_OP_COND
static const uint8_t CARD_ACMD41[ CMD_LENGTH ] = { 0x69, 0x40, 0x00, 0x00, 0x00, 0xFF };
// Посылаем команду и ждём окончания передачи
void Card_SendCMD(const uint8_t *Buf, uint32_t Size )
{ // Локальная переменная
uint16_t Data;
// Если есть данные
while ( Size > 0 )
{ // Первым делом формируем данные, с учётом пакинга для оптимизации
Data = *(Buf); Buf++; Size--;
if ( Size > 0 )
{ // Забираем второй байт тоже
Data += (*(Buf) * 0x100); Buf++; Size--;
}
// Данные сформированы, ожидаем готовности буфера передачи
while ( (SPI1->SR & SPI_SR_TXE) == 0 ) {}
// Передаём данные
SPI1->DR = Data;
}
// Ожидаем опустошения очереди передачи
while ( (SPI1->SR & SPI_SR_FTLVL) != 0 ) { Data = SPI1->DR; }
// Ждём завершения последней транзакции
while ( (SPI1->SR & SPI_SR_BSY) != 0 ) { Data = SPI1->DR; }
// Опусташаем буфер приёма
while ( (SPI1->SR & SPI_SR_FRLVL) != 0 ) { Data = SPI1->DR; }
}
// Посылаем байт и ждём ответ
uint8_t Card_SPI( uint8_t Data )
{ // Локальная переменная
uint8_t Res;
// Ожидаем готовности передатчика
while ( (SPI1->SR & SPI_SR_FTLVL) != 0 ) { }
// Посылаем слово
*((__IO uint8_t *)&SPI1->DR) = Data;
// Ожидаем готовности приёмника
while ( (SPI1->SR & SPI_SR_RXNE) == 0 ) { }
// Вычитываем
Res = *((__IO uint8_t *)&SPI1->DR);
// Выход
return Res;
}
// Ожидаем ответ
uint8_t Card_WaitResp( uint32_t *OCR, FunctionalState R7, uint8_t Count )
{ // Локальная переменная
uint8_t Res,Cnt;
// Инит переменной
*(OCR) = 0xFFFFFFFF;
// Поиск первого байта ответа
do
{ // Получаем данные
Res = Card_SPI( 0xFF );
// И уменьшаем счётчик
Count--;
}
while ( ((Res & 0xC0) != 0) && (Count > 0) );
// Проверяем, требуется ли догрузка ещё 4х байт?
if ( R7 == ENABLE )
{ // Догружаем ещё 4 байт (всего 40 бит вместе с Res)
for (Cnt = 0; Cnt < 4;Cnt++)
{ // Готовим место под байт
*(OCR) <<= 8; *(OCR) &= 0xFFFFFF00;
// Получаем данные
*(OCR) += Card_SPI( 0xFF );
}
}
// Ожидаем как минимум 1 байт с 0xFF
while ( Card_SPI( 0xFF ) != 0xFF ) { }
// Выход
return Res;
}
// Инициализация карты памяти
TCardType Card_Init( void )
{ // Локальные переменные
TCardType Res;
uint32_t Cnt,OCR;
uint8_t Dat, Resp;
// Отключаем карту
CARD_OFF; Res = ctNone;
// Настраиваем SPI на медленную скорость PCLK/128: 48/128 = 0,375МГц
SPI1->CR1 &= ~SPI_CR1_SPE;
SPI1->CR1 = SPI_CR1_MSTR | SPI_LOW_SPEED;
SPI1->CR1 |= SPI_CR1_SPE;
// Топчемся на месте
HAL_Delay( 1 );
// Посылаем инит 256 байт
for (Cnt = 0;Cnt < 256;Cnt++ )
{ // Послыаем слово
Card_SPI( 0xFF );
}
// Начинаем инициализацию карты
CARD_ON;
// Ожидаем готовности карты
do
{ // Посылаем 0xFF
Dat = Card_SPI( 0xFF );
} while ( Dat != 0xFF );
// CMD0: GO_IDLE_STATE
Card_SendCMD( &CARD_CMD0[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( &OCR, DISABLE, 128 );
// Какой ответ получен?
if ( Resp == 0x01 )
{ // Карта вошла в IDLE_STATE, посылаем CMD8: SEND_IF_COND
Card_SendCMD( &CARD_CMD8[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( &OCR, ENABLE, 128 );
// Если был дан адекватный респонс
if ( Resp != 0x01 )
{ // Это ветка SDv1/MMC
do
{ // Посылаем ACMD41: APP_SEND_OP_COND
Card_SendCMD( &CARD_ACMD41[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( &OCR, ENABLE, 128 );
} while ( Resp == 0x01 );
// Каков был ответ?
if ( Resp == 0x00 )
{ // Обнаружена карта SD v1
Res = ctSD1;
}
else
{ // Это ветка MMC, нам её некуда втыкать
Res = ctUnknown;
}
}
else
{ // Это ветка SDv2
if ( (OCR & 0x0001FF) == 0x0001AA )
{ // Это карта SDv2
do
{ // Посылаем ACMD55: APP_CMD
Card_SendCMD( &CARD_CMD55[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( &OCR, DISABLE, 128 );
// Если ответ правильный
if ( Resp == 0x01 )
{ // Посылаем ACMD41: APP_SEND_OP_COND
Card_SendCMD( &CARD_ACMD41[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( &OCR, ENABLE, 128 );
}
} while ( Resp == 0x01 );
// Каков был ответ?
if ( Resp == 0x00 )
{ // Посылаем CMD58: READ_OCR
Card_SendCMD( &CARD_CMD58[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( &OCR, ENABLE, 128 );
// Каков ответ?
if ( Resp == 0x00 )
{ // Анализируем OCR
if ( (OCR & 0x40000000) == 0x00000000 )
{ // Карта обычной ёмкости
Res = ctSD2;
}
else
{ // Карта повышенной ёмкости
Res = ctSD3;
}
}
else
{ // Эта карта неисправна
Res = ctUnknown;
}
}
else
{ // Эта карта неисправна
Res = ctUnknown;
}
}
else
{ // Эта карта неисправна
Res = ctUnknown;
}
}
}
else
{ // Карта ответила неправильно
if ( Res != 0xFF ) { Res = ctUnknown; }
}
// Только для карт обычной ёмкости
if ( (Res == ctSD1) || (Res == ctSD2) )
{ // Устанавливаем размер блока 512 байт
// CMD16: SET_BLOCKLEN
Card_SendCMD( &CARD_CMD16[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( &OCR, DISABLE, 128 );
// Каков ответ?
if ( Resp != 0x00 )
{ // Эта карта неисправна
Res = ctUnknown;
}
}
// Выключаем карту
while ( (SPI1->SR & SPI_SR_BSY) != 0x0000 ) { }
CARD_OFF;
// Если карта инициализирована
if ( (Res != ctNone) && (Res != ctUnknown) )
{ // Настраиваем SPI на быструю скорость PCLK/2: 48/2 = 24МГц
SPI1->CR1 &= ~SPI_CR1_SPE;
SPI1->CR1 = SPI_CR1_MSTR;
SPI1->CR1 |= SPI_CR1_SPE;
}
// Выходим
return Res;
}
// Чтение сектора карты памяти без DMA
FunctionalState Card_Read( TCardType CardType, uint8_t *Buf, uint32_t *Loaded, uint32_t Addr )
{ // Локальные переменные
FunctionalState Res;
uint8_t Cmd[ 6 ];
uint8_t Dat,Resp;
uint32_t Cnt;
// Инит
Res = DISABLE;
// Посмотрим, у нас в буфере уже загружено?
if ( *(Loaded) != Addr )
{ // Сохраняем новый номер сектора
*(Loaded) = Addr;
// Корректируем адрес для старых карт
if ( (CardType == ctSD1) || (CardType == ctSD2) )
{ // У старых карт адрес вместо LBA
Addr *= 0x00000200;
}
// Работаем
while ( 1 )
{ // Если тип карты неправильный - выходим
if ( CardType == ctNone ) { break; }
if ( CardType == ctUnknown ) { break; }
// Готовим команду на чтение сектора
Cmd[ 0 ] = CARD_CMD17;
Cmd[ 1 ] = Addr >> 24;
Cmd[ 2 ] = Addr >> 16;
Cmd[ 3 ] = Addr >> 8;
Cmd[ 4 ] = Addr;
Cmd[ 5 ] = 0xFF;
// Включаем карту
CARD_ON;
// Ожидаем готовности карты
do
{ // Посылаем 0xFF
Dat = Card_SPI( 0xFF );
} while ( Dat != 0xFF );
// Посылаем команду чтения
Card_SendCMD( &Cmd[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( (uint32_t *)&Cmd[ 0 ], DISABLE, 128 );
// Анализируем ответ на команду
if ( Resp != 0x00 ) { break; }
// Ожидаем токен данных
Cnt = 2048;
do
{ // Считываем данные
Dat = Card_SPI( 0xFF );
// Считаем
Cnt--;
} while ( (Dat == 0xFF) && (Cnt > 0) );
// Таймаут?
if ( Cnt == 0 ) { break; }
// Ошибка в токене?
if ( Dat != CARD_DATA_TOKEN ) { break; }
// Начались данные, загружаем
for (Cnt = 0;Cnt < 512;Cnt++)
{ // Считываем данные
*(Buf) = Card_SPI( 0xFF ); Buf++;
}
// Дочитываем CRC
Cmd[ 0 ] = Card_SPI( 0xFF );
Cmd[ 1 ] = Card_SPI( 0xFF );
// Без ошибок
Res = ENABLE;
// Выход
break;
}
}
else
{ // Без ошибок
Res = ENABLE;
}
// Выключаем карту
while ( (SPI1->SR & SPI_SR_BSY) != 0x0000 ) { }
CARD_OFF;
// Если была ошибка, обнулим номер
if ( Res == DISABLE ) { *(Loaded) = 0xFFFFFFFF; }
// Выход
return Res;
}
// Запись сектора карты памяти без DMA
FunctionalState Card_Write( TCardType CardType, uint8_t *Buf, uint32_t *Loaded, uint32_t Addr )
{ // Локальные переменные
FunctionalState Res;
uint8_t Cmd[ 6 ];
uint8_t Dat,Resp;
uint32_t Cnt;
// Инит
Res = DISABLE;
// Корректируем адрес для старых карт
if ( (CardType == ctSD1) || (CardType == ctSD2) )
{ // У старых карт адрес вместо LBA
Addr *= 0x00000200;
}
// Работаем
while ( 1 )
{ // Если тип карты неправильный - выходим
if ( CardType == ctNone ) { break; }
if ( CardType == ctUnknown ) { break; }
// Готовим команду на чтение сектора
Cmd[ 0 ] = CARD_CMD24;
Cmd[ 1 ] = Addr >> 24;
Cmd[ 2 ] = Addr >> 16;
Cmd[ 3 ] = Addr >> 8;
Cmd[ 4 ] = Addr;
Cmd[ 5 ] = 0xFF;
// Включаем карту
CARD_ON;
// Ожидаем готовности карты
do
{ // Посылаем 0xFF
Dat = Card_SPI( 0xFF );
} while ( Dat != 0xFF );
// Посылаем команду чтения
Card_SendCMD( &Cmd[ 0 ], CMD_LENGTH ); Resp = Card_WaitResp( (uint32_t *)&Cmd[ 0 ], DISABLE, 128 );
// Анализируем ответ на команду
if ( Resp != 0x00 ) { break; }
// Посылаем токен данных
Card_SPI( CARD_DATA_TOKEN );
// Посылаем данные в цикле
// Начались данные, загружаем
for (Cnt = 0;Cnt < 512;Cnt++)
{ // Считываем данные
Card_SPI( *(Buf) ); Buf++;
}
// Досылаем CRC
Card_SPI( 0xFF );
Card_SPI( 0xFF );
// Без ошибок
Res = ENABLE;
// Выход
break;
}
// Выключаем карту
while ( (SPI1->SR & SPI_SR_BSY) != 0x0000 ) { }
CARD_OFF;
// Успешно?
if ( Res == ENABLE )
{ // Сохраняем новый номер сектора
*(Loaded) = Addr;
}
else
{ // Обнуляем
*(Loaded) = 0xFFFFFFFF;
}
// Выход
return Res;
}Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Re: SDSC карта памяти для STM32F103C8T6
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692690#p4692690"]Описаний как инициализировать карту, множество. Вот например.[/uquote]Имхо - здесь описание лучше: http://elm-chan.org/docs/mmc/mmc_e.html
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692690#p4692690"]Однако, фактически CS выставляется в 0 в начальный момент времени, и всегда в единице все оставшееся время.[/uquote]В смысле? Не понял вашу фразу.
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692690#p4692690"]То есть, инициализация SPI происходит при выставлении НУЛЯ на CS и ЕДИНИЦЫ во время операций чтения-записи. А в описании все наоборот... Да и по логике работы SPI CS должно быть в нуле во время обращения к устройству, а в SD картах, выходит, все строго наоборот[/uquote]Ничего там не наоборот. Начальные 74+ клока при CS=high - нужны очевидно для завершения возможных незавершённых сдвигов в машине состояний схемы карты. Если предыдущий цикл работы устройства оборвался во время передачи команды (МК неожиданно пересбросился). Вот чтобы вы-flush-ить все буфера и счётчики клоков карты и нужно, до начала работы с картой, при CS=high подать множество циклов.
А штатная работа карты - естественно - при CS=low. На вышеприведённой ссылке это видно. Параграф "Cosideration on Multi-slave Configuration".
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692690#p4692690"]Вот где-то на этапе R1 resp все и заканчивается.[/uquote]Значит что-то не так делаете. Проверку занятости делаете (как описано по ссылке выше)?
PS: Реализовывал обмен с картами по этому описанию (давно правда) - работало со всеми картами. В том числе и с имевшейся тогда MMC на 256MB.
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692690#p4692690"]Однако, фактически CS выставляется в 0 в начальный момент времени, и всегда в единице все оставшееся время.[/uquote]В смысле? Не понял вашу фразу.
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692690#p4692690"]То есть, инициализация SPI происходит при выставлении НУЛЯ на CS и ЕДИНИЦЫ во время операций чтения-записи. А в описании все наоборот... Да и по логике работы SPI CS должно быть в нуле во время обращения к устройству, а в SD картах, выходит, все строго наоборот[/uquote]Ничего там не наоборот. Начальные 74+ клока при CS=high - нужны очевидно для завершения возможных незавершённых сдвигов в машине состояний схемы карты. Если предыдущий цикл работы устройства оборвался во время передачи команды (МК неожиданно пересбросился). Вот чтобы вы-flush-ить все буфера и счётчики клоков карты и нужно, до начала работы с картой, при CS=high подать множество циклов.
А штатная работа карты - естественно - при CS=low. На вышеприведённой ссылке это видно. Параграф "Cosideration on Multi-slave Configuration".
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692690#p4692690"]Вот где-то на этапе R1 resp все и заканчивается.[/uquote]Значит что-то не так делаете. Проверку занятости делаете (как описано по ссылке выше)?
PS: Реализовывал обмен с картами по этому описанию (давно правда) - работало со всеми картами. В том числе и с имевшейся тогда MMC на 256MB.
- Реклама
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
Нашел таки логический анализатор, и вот что получилось. Да, CS ведет как в описании. Наверное, осциллограф чудит при отображении информации. Сперва карты здорового человека и рабочий проект, который делает тестовые чтение-запись. Переходят в режим SPI без проблем.

А вот карточки на 256 МБ. Уже и 256 единичных байт подал после запуска, и частоту задавил аж до 16 кбит (меньше уже нельзя, так как кварц 8 МГц). Карты здорового человека все еще определяются, но возвращают ошибку при попытке записи. В ответ лишь одиночные импульсы в рандомный момент времени. Похоже, нет у них режима SPI. Надо сказать, что карточки новодельные - продаются на алике упаковками по 5-10 штук. Возможно, поддержку SPI в них не завезли. В нативном режиме, судя по всему, работают нормально, так как прекрасно работают в компе... Такой же результат выдала двухгиговая карточка от Silicon Power


А вот карточки на 256 МБ. Уже и 256 единичных байт подал после запуска, и частоту задавил аж до 16 кбит (меньше уже нельзя, так как кварц 8 МГц). Карты здорового человека все еще определяются, но возвращают ошибку при попытке записи. В ответ лишь одиночные импульсы в рандомный момент времени. Похоже, нет у них режима SPI. Надо сказать, что карточки новодельные - продаются на алике упаковками по 5-10 штук. Возможно, поддержку SPI в них не завезли. В нативном режиме, судя по всему, работают нормально, так как прекрасно работают в компе... Такой же результат выдала двухгиговая карточка от Silicon Power

Re: SDSC карта памяти для STM32F103C8T6
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692977#p4692977"]Возможно, поддержку SPI в них не завезли.[/uquote]Сомнительно. Думаете - для таких дешёвых станут разрабатывать свой собственный уникальный контроллер? Лишь для того, чтобы выкусить SPI?
Наверняка в них использован стандартный контроллер SD. А он ещё с былинных времён поддерживает SPI-режим.
Наверняка в них использован стандартный контроллер SD. А он ещё с былинных времён поддерживает SPI-режим.
- HardWareMan
- Мучитель микросхем
- Сообщения: 431
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: SDSC карта памяти для STM32F103C8T6
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692977#p4692977"]
[/uquote]
А что за команда 0xA0 у вас в логе? А вообще, можете поделиться логами в бинарном формате а не картинками, чтобы изучить весь процесс?
[/uquote]А что за команда 0xA0 у вас в логе? А вообще, можете поделиться логами в бинарном формате а не картинками, чтобы изучить весь процесс?
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4693055#p4693055"]А вообще, можете поделиться логами в бинарном формате а не картинками, чтобы изучить весь процесс?[/uquote]
Прикладываю файлы, созданные в PulseView.
В бинарниках 4 канала, 1 MSmp/s. Реальная частота шины 140,625 kBit/s
В "нормальной" флешке помимо инициализации код произвел чтение-запись
Прикладываю файлы, созданные в PulseView.
В бинарниках 4 канала, 1 MSmp/s. Реальная частота шины 140,625 kBit/s
В "нормальной" флешке помимо инициализации код произвел чтение-запись
- Вложения
-
- PulseView.zip
- (318.4 КБ) 1474 скачивания
- HardWareMan
- Мучитель микросхем
- Сообщения: 431
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: SDSC карта памяти для STM32F103C8T6
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4693129#p4693129"]Прикладываю файлы, созданные в PulseView.[/uquote]
Ааа, это ты забыл указать декодеру /SS. Там нормально 0х40.
Вот нормальный лог:

Вот лог курильщика:

Зачем ты продолжаешь долбить после команды?
Ааа, это ты забыл указать декодеру /SS. Там нормально 0х40.
Вот нормальный лог:

Вот лог курильщика:

Зачем ты продолжаешь долбить после команды?
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4693138#p4693138"][uquote="Linuxoid91",url="/forum/viewtopic.php?p=4693129#p4693129"]Зачем ты продолжаешь долбить после команды?[/uquote]
Это чей-то скачанный с гитхаба пример. Уже не помню, какой конкретно - я их несколько скачал. Этот инициализирует карту, затем работает уже с FATFS - измеряет емкость, записывает и стирает файл, и т.д. Самое главное, что он выдает результат работы в UART, и сразу видно, что работа программы ведется. Единственное, что поменял в его работе - это увеличил количество стартовых байт с 10 до 255. Дальше код не менял
Добавлено after 35 minutes 1 second:
В любом случае, курильщик холоден к попыткам связи его через SPI. Вообще, конечно, вряд ли китайцы специально вырезали протокол SPI, просто мне попалась версия с тем самым контроллером, где его нет. Однако, назрела необходимость заказать МК с интерфейсом SDIO, например, STM32F411. Смешно, но Bluepill ждали своего часа более 5 лет, ибо задачи для него достойной не находилось. Нужда пришла откуда не ждали - устройство должно стать мелкосерийным, а значит, старых запасов 8-битных МК не напасешься, а новые стоят неприлично много. Проект, к счастью, не коммерческий
Это чей-то скачанный с гитхаба пример. Уже не помню, какой конкретно - я их несколько скачал. Этот инициализирует карту, затем работает уже с FATFS - измеряет емкость, записывает и стирает файл, и т.д. Самое главное, что он выдает результат работы в UART, и сразу видно, что работа программы ведется. Единственное, что поменял в его работе - это увеличил количество стартовых байт с 10 до 255. Дальше код не менял
Добавлено after 35 minutes 1 second:
В любом случае, курильщик холоден к попыткам связи его через SPI. Вообще, конечно, вряд ли китайцы специально вырезали протокол SPI, просто мне попалась версия с тем самым контроллером, где его нет. Однако, назрела необходимость заказать МК с интерфейсом SDIO, например, STM32F411. Смешно, но Bluepill ждали своего часа более 5 лет, ибо задачи для него достойной не находилось. Нужда пришла откуда не ждали - устройство должно стать мелкосерийным, а значит, старых запасов 8-битных МК не напасешься, а новые стоят неприлично много. Проект, к счастью, не коммерческий
Re: SDSC карта памяти для STM32F103C8T6
[uquote="HardWareMan",url="/forum/viewtopic.php?p=4693138#p4693138"]Вот нормальный лог:
[/uquote]Какой же он нормальный, если начинается с команды CMD40?
Вы же сами выше приводили блок-схему алгоритма инициализации, из которой видно, что первой должна идти команда CMD0?
А до неё ещё должны идти 74+ клоков при CS=high.
[/uquote]Какой же он нормальный, если начинается с команды CMD40?Вы же сами выше приводили блок-схему алгоритма инициализации, из которой видно, что первой должна идти команда CMD0?
А до неё ещё должны идти 74+ клоков при CS=high.
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
[uquote="jcxz",url="/forum/viewtopic.php?p=4693342#p4693342"]Какой же он нормальный, если начинается с команды CMD40?
Вы же сами выше приводили блок-схему алгоритма инициализации, из которой видно, что первой должна идти команда CMD0?
А до неё ещё должны идти 74+ клоков при CS=high.[/uquote]
Все команды имеют формат 01хххххх. То есть, сами команды 6-битные, к которым в качестве старших битов дописывается 01. Таким образом, CMD0=0100000 или 0х40
Вы же сами выше приводили блок-схему алгоритма инициализации, из которой видно, что первой должна идти команда CMD0?
А до неё ещё должны идти 74+ клоков при CS=high.[/uquote]
Все команды имеют формат 01хххххх. То есть, сами команды 6-битные, к которым в качестве старших битов дописывается 01. Таким образом, CMD0=0100000 или 0х40
- HardWareMan
- Мучитель микросхем
- Сообщения: 431
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: SDSC карта памяти для STM32F103C8T6
[uquote="jcxz",url="/forum/viewtopic.php?p=4693342#p4693342"]Какой же он нормальный, если начинается с команды CMD40?[/uquote]
"Нормальный" он по классификации ТСа (так подписан файл лога) а не по сути.
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4693358#p4693358"]Все команды имеют формат 01хххххх. То есть, сами команды 6-битные, к которым в качестве старших битов дописывается 01. Таким образом, CMD0=0100000 или 0х40[/uquote]
Я лишь добавлю, что команда CMD40 существует. Её код это 0х68, потому что на интерфейсе ходит HEX а в названиях используется DEC.
"Нормальный" он по классификации ТСа (так подписан файл лога) а не по сути.
[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4693358#p4693358"]Все команды имеют формат 01хххххх. То есть, сами команды 6-битные, к которым в качестве старших битов дописывается 01. Таким образом, CMD0=0100000 или 0х40[/uquote]
Я лишь добавлю, что команда CMD40 существует. Её код это 0х68, потому что на интерфейсе ходит HEX а в названиях используется DEC.
Последний раз редактировалось HardWareMan Пт мар 14, 2025 10:41:04, всего редактировалось 1 раз.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
Покуда придумываю, как бы мне заменить SPI на SDIO, нашел STM32F411 и мертвый DFPlayer в качестве слота Micro SD карты. И обнаружил, что на плеере не распаяны выводы 1,2 и 8 (фото в цвете). То есть, в режиме SDIO оборваны линии DAT1,2,3, а в режиме SPI - линия CS... Выходит, либо SD карточки работают по SPI безо всяких CS, либо по SDIO можно припаять всего один выход данных?
Карты на 256 МБ в них прекрасно работают.
Буду пробовать примерно через неделю, не раньше
Буду пробовать примерно через неделю, не раньше
- HardWareMan
- Мучитель микросхем
- Сообщения: 431
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: SDSC карта памяти для STM32F103C8T6
SDIO может работать в 1, 4 и 8 битном режимах.

- Вложения
-
- Снимок.PNG
- (88.98 КБ) 1697 скачиваний
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
Странно, что SD карты поддерживают 8-битный SDIO. Ведь у Micro SD всего 8 пинов... Теоретически, конечно, можно себе это представить, но сложно
- HardWareMan
- Мучитель микросхем
- Сообщения: 431
- Зарегистрирован: Ср сен 02, 2015 07:47:20
Re: SDSC карта памяти для STM32F103C8T6
Это может быть для MMC предназначено. У них есть 8 бит варианты, в том числе и eMMC, а контроллер SDIO у STM это общий интерфейс для карт памяти.

- Вложения
-
- 15-04-29-MMC-Karte-RalfR-dscf4734-d.jpg
- (171.42 КБ) 1227 скачиваний
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Re: SDSC карта памяти для STM32F103C8T6
SDIO - это просто интерфейс. Не только SD-карты могут по нему подключаться. Есть микросхемы eMMC - они как раз используют 8 бит SDIO.
Также встречал WiFi-чипы, подключающиеся по SDIO: TiWi-R2 (хотя в нём всего 4-битный SDIO).
https://www.ezurio.com/part/450-0037
Также встречал WiFi-чипы, подключающиеся по SDIO: TiWi-R2 (хотя в нём всего 4-битный SDIO).
https://www.ezurio.com/part/450-0037
- Linuxoid91
- Грызет канифоль
- Сообщения: 295
- Зарегистрирован: Вс дек 18, 2011 14:41:24
- Откуда: Ангарск
Re: SDSC карта памяти для STM32F103C8T6
Нашел такую схему организации 1-битного SDIO посредством SPI. Однако, главный вопрос - а не сгорит? Ведь насколько мне известно, SPI не является интерфейсом с открытым коллектором, и в режиме простоя на нем единица... Смущает, правда, название RSPI... Из того, что я понял, его подключение ничем не отличается от SPI, и R в названии - не подтягивающий резистор... Но кажется, все будет работать, если запаять резистор последовательно с сигналом MOSI, а подтяжку к плюсу у D0 убрать... Правда, на STM так, похоже, никто не делал, либо я не нашел.
Вообще, необходимость подтягивающих резисторов и двунаправленность больше напоминает интерфейс I2C.

Вообще, необходимость подтягивающих резисторов и двунаправленность больше напоминает интерфейс I2C.



