SDSC карта памяти для STM32F103C8T6

Кто любит RISC в жизни, заходим, не стесняемся.
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

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

Re: SDSC карта памяти для STM32F103C8T6

Сообщение HardWareMan »

Я реализовал свой собственный инит карты по этому чарту:
Изображение
А потом просто использовал FatFS от Чена, причём в моей версии пришлось исправлять ошибку преобразования адреса в сектор (и наоборот) потому что для XC должен использоваться uint64_t а Чен тогда использовал только uint32_t. Это было 10 лет назад, в современных версиях вроде как это уже пофикшено.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Реклама
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

Вот где-то на этапе R1 resp все и заканчивается. Возвращает нули, хоть ты тресни :facepalm:
Сегодня, в 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

Сообщение HardWareMan »

А ты скорость понижаешь? Инит карты происходит строго на частоте ниже 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 временно не будет.
Реклама
Эиком - электронные компоненты и радиодетали
jcxz
Мудрый кот
Сообщения: 1727
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: SDSC карта памяти для STM32F103C8T6

Сообщение jcxz »

[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.
Реклама
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

Нашел таки логический анализатор, и вот что получилось. Да, CS ведет как в описании. Наверное, осциллограф чудит при отображении информации. Сперва карты здорового человека и рабочий проект, который делает тестовые чтение-запись. Переходят в режим SPI без проблем.
Изображение
А вот карточки на 256 МБ. Уже и 256 единичных байт подал после запуска, и частоту задавил аж до 16 кбит (меньше уже нельзя, так как кварц 8 МГц). Карты здорового человека все еще определяются, но возвращают ошибку при попытке записи. В ответ лишь одиночные импульсы в рандомный момент времени. Похоже, нет у них режима SPI. Надо сказать, что карточки новодельные - продаются на алике упаковками по 5-10 штук. Возможно, поддержку SPI в них не завезли. В нативном режиме, судя по всему, работают нормально, так как прекрасно работают в компе... Такой же результат выдала двухгиговая карточка от Silicon Power
Изображение
Реклама
jcxz
Мудрый кот
Сообщения: 1727
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: SDSC карта памяти для STM32F103C8T6

Сообщение jcxz »

[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692977#p4692977"]Возможно, поддержку SPI в них не завезли.[/uquote]Сомнительно. Думаете - для таких дешёвых станут разрабатывать свой собственный уникальный контроллер? Лишь для того, чтобы выкусить SPI?
Наверняка в них использован стандартный контроллер SD. А он ещё с былинных времён поддерживает SPI-режим.
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: SDSC карта памяти для STM32F103C8T6

Сообщение HardWareMan »

[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4692977#p4692977"]Изображение[/uquote]
А что за команда 0xA0 у вас в логе? А вообще, можете поделиться логами в бинарном формате а не картинками, чтобы изучить весь процесс?
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

[uquote="HardWareMan",url="/forum/viewtopic.php?p=4693055#p4693055"]А вообще, можете поделиться логами в бинарном формате а не картинками, чтобы изучить весь процесс?[/uquote]

Прикладываю файлы, созданные в PulseView.
В бинарниках 4 канала, 1 MSmp/s. Реальная частота шины 140,625 kBit/s
В "нормальной" флешке помимо инициализации код произвел чтение-запись
Вложения
PulseView.zip
(318.4 КБ) 1474 скачивания
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: SDSC карта памяти для STM32F103C8T6

Сообщение HardWareMan »

[uquote="Linuxoid91",url="/forum/viewtopic.php?p=4693129#p4693129"]Прикладываю файлы, созданные в PulseView.[/uquote]
Ааа, это ты забыл указать декодеру /SS. Там нормально 0х40.

Вот нормальный лог:
Изображение

Вот лог курильщика:
Изображение

Зачем ты продолжаешь долбить после команды?
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

[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-битных МК не напасешься, а новые стоят неприлично много. Проект, к счастью, не коммерческий
jcxz
Мудрый кот
Сообщения: 1727
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: SDSC карта памяти для STM32F103C8T6

Сообщение jcxz »

[uquote="HardWareMan",url="/forum/viewtopic.php?p=4693138#p4693138"]Вот нормальный лог:
Изображение[/uquote]Какой же он нормальный, если начинается с команды CMD40?
Вы же сами выше приводили блок-схему алгоритма инициализации, из которой видно, что первой должна идти команда CMD0?
А до неё ещё должны идти 74+ клоков при CS=high.
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

[uquote="jcxz",url="/forum/viewtopic.php?p=4693342#p4693342"]Какой же он нормальный, если начинается с команды CMD40?
Вы же сами выше приводили блок-схему алгоритма инициализации, из которой видно, что первой должна идти команда CMD0?
А до неё ещё должны идти 74+ клоков при CS=high.[/uquote]
Все команды имеют формат 01хххххх. То есть, сами команды 6-битные, к которым в качестве старших битов дописывается 01. Таким образом, CMD0=0100000 или 0х40
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: SDSC карта памяти для STM32F103C8T6

Сообщение HardWareMan »

[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.
Последний раз редактировалось HardWareMan Пт мар 14, 2025 10:41:04, всего редактировалось 1 раз.
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

Покуда придумываю, как бы мне заменить SPI на SDIO, нашел STM32F411 и мертвый DFPlayer в качестве слота Micro SD карты. И обнаружил, что на плеере не распаяны выводы 1,2 и 8 (фото в цвете). То есть, в режиме SDIO оборваны линии DAT1,2,3, а в режиме SPI - линия CS... Выходит, либо SD карточки работают по SPI безо всяких CS, либо по SDIO можно припаять всего один выход данных? :shock: Карты на 256 МБ в них прекрасно работают.
Буду пробовать примерно через неделю, не раньше :solder:
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: SDSC карта памяти для STM32F103C8T6

Сообщение HardWareMan »

SDIO может работать в 1, 4 и 8 битном режимах.
Изображение
Вложения
Снимок.PNG
(88.98 КБ) 1697 скачиваний
Репозиторий STM32: https://cloud.mail.ru/public/2i19/Y4w8kKEiZ
Актуальность репозитория: 22 апреля 2026 года
Если чего-то не хватает с сайта st.com - пишите, докачаю.
/!\ Обновлений для STM32PowerMon и STM32PowerMon-UCPD временно не будет.
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

Странно, что SD карты поддерживают 8-битный SDIO. Ведь у Micro SD всего 8 пинов... Теоретически, конечно, можно себе это представить, но сложно
Аватара пользователя
HardWareMan
Мучитель микросхем
Сообщения: 431
Зарегистрирован: Ср сен 02, 2015 07:47:20

Re: SDSC карта памяти для STM32F103C8T6

Сообщение HardWareMan »

Это может быть для 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 временно не будет.
jcxz
Мудрый кот
Сообщения: 1727
Зарегистрирован: Вт авг 15, 2017 10:51:13

Re: SDSC карта памяти для STM32F103C8T6

Сообщение jcxz »

SDIO - это просто интерфейс. Не только SD-карты могут по нему подключаться. Есть микросхемы eMMC - они как раз используют 8 бит SDIO.
Также встречал WiFi-чипы, подключающиеся по SDIO: TiWi-R2 (хотя в нём всего 4-битный SDIO).
https://www.ezurio.com/part/450-0037
Аватара пользователя
Linuxoid91
Грызет канифоль
Сообщения: 295
Зарегистрирован: Вс дек 18, 2011 14:41:24
Откуда: Ангарск

Re: SDSC карта памяти для STM32F103C8T6

Сообщение Linuxoid91 »

Нашел такую схему организации 1-битного SDIO посредством SPI. Однако, главный вопрос - а не сгорит? Ведь насколько мне известно, SPI не является интерфейсом с открытым коллектором, и в режиме простоя на нем единица... Смущает, правда, название RSPI... Из того, что я понял, его подключение ничем не отличается от SPI, и R в названии - не подтягивающий резистор... Но кажется, все будет работать, если запаять резистор последовательно с сигналом MOSI, а подтяжку к плюсу у D0 убрать... Правда, на STM так, похоже, никто не делал, либо я не нашел.
Вообще, необходимость подтягивающих резисторов и двунаправленность больше напоминает интерфейс I2C.

Изображение
Ответить

Вернуться в «ARM»