Реклама на сайте English version  DatasheetsDatasheets

KAZUS.RU - Электронный портал. Принципиальные схемы, Datasheets, Форум по электронике

Новости электроники Новости Литература, электронные книги Литература Документация, даташиты Документация Поиск даташитов (datasheets)Поиск PDF
  От производителей
Новости поставщиков
В мире электроники

  Сборник статей
Электронные книги
FAQ по электронике

  Datasheets
Поиск SMD
Он-лайн справочник

Принципиальные схемы Схемы Каталоги программ, сайтов Каталоги Общение, форум Общение Ваш аккаунтАккаунт
  Каталог схем
Избранные схемы
FAQ по электронике
  Программы
Каталог сайтов
Производители электроники
  Форумы по электронике
Помощь проекту

AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR...

 
Опции темы
Непрочитано 24.10.2018, 13:31  
Donker
Временная регистрация
 
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Donker на пути к лучшему
По умолчанию Подключение разных SD карт к ATmega328P, как?

Хочу разобраться как подключать разные типы SD карт, в том числе SDHC к AVR, взял за основу этот пример:
http://narodstream.ru/avr-urok-33-sp...d-fat-chast-1/
для начала хотя бы освоить чтение запись в сектора карты, а потом уже разбираться с файловой системой.

Написал проект
https://radiokot.ru/forum/download/file.php?id=316766
(Atmel Studio 7 + эмуляция Proteus 8.7 + схема) и собрал макетку
https://radiokot.ru/forum/download/file.php?id=316767
, от примера отличается - с секторами я пытаюсь работать сразу на ATmega328P а не на ATmega8A и экран у меня работает через I2C шину, а не напрямую, в качестве разъёма карточки - припаял переходник SD-microSD, т.е. работать
предполагается только с форматом microSD.

В Протеусе работает нормально, в железе нет.

Алгоритм работы макетной платы: по очереди бесконечно зажигаюnся светодиоды D1...D3, выводятся тестовые строки на экран, запускается таймер1, в нем опрашивается кнопка S3 на PC0, нажатие кнопки на S3 очищает экран, в первой строке
экрана выводятся три числа с номерами ошибок, если ошибок нет то все числа нули, во второй строке четыре байта адреса
начала сектора 512 байт в шестнадцатеричном формате, начиная с сектора 4096, в третьей строке начало буфера чтения забитого символами "c", в четвёртой строке начало буфера чтения после считывание туда сектора из карточки, если всё нормально, видно начало тестового паттерна, каждое следующие нажатие на кнопку увеличивает адрес на один сектор.

Проверял на четырёх карточках:

1) microSD на 64Мб - первое нажатие на кнопку ошибка инициализации 3, последующие пишется-читается нормально

2) microSD на 1Гб - всегда ошибка инициализации 3

3) microSD на 2Гб - первое нажатие на кнопку ошибка инициализации 3, последующие пишется-читается нормально

4) microSDHC на 4Гб - всегда ошибка инициализации 4

Какие будут идеи ?

Есть подозрение что проблемма только в неправильной инициализации карточек.

Листинг файла main.cpp:
Нажмите, чтобы открыть спойлер
Код:
//**************************************************  *****************************
#include "main.h"
//**************************************************  *****************************
#define MOSI   3
#define MISO   4
#define SCK  5
#define SS   2
//**************************************************  *****************************
char buffer[512] = "SD test SD test SD яяяяяяяя1111111199999999яяяяяяяя1111111199999999яя  яяяяяя1111111199999999яяяяяяяя1111111199999999яяяя  яяяя1111111199999999яяяяяяяя1111111199999999яяяяяя  яя1111111199999999яяяяяяяя1111111199999999яяяяяяяя  1111111199999999яяяяяяяя1111111199999999яяяяяяяя11  11111199999999яяяяяяяя1111111199999999яяяяяяяя1111  111199999999яяяяяяяя1111111199999999яяяяяяяя111111  1199999999яяяяяяяя1111111199999999яяяяяяяя11111111  99999999яяяяяяяя1111111199999999яяяяяяяя1111111199  999999яяяяяяяя1111111199999999яяяяяяяя1111"; //Буфер данных для записи/чтения
char buffer2[512] ={}; //Буфер данных для чтения
//**************************************************  *****************************
signed char stethik_kn = 0;
uint32_t SD_adr = 2097152; // будем записывать сектора по 512 байт начиная с сектора 4096
//**************************************************  *****************************

void port_ini(void) //настройка четырёх выводов порта для софтового SPI
{
PORTB|=(1‹‹SS)|(1‹‹MISO)|(1‹‹MOSI);
DDRB|=(1‹‹SS)|(1‹‹MOSI)|(1‹‹SCK);
}

void SPI_SendByte (unsigned char byte)
{
/////////////////////////////////////////////////////////////////////////
for (unsigned char i=0; i‹8; i++) //движемся по битам байта
  {
  if ((byte&0x80)==0x00)//проверяем левый бит
  PORTB&=~(1‹‹MOSI); //если 0, то выставляем 0 на шине
  else PORTB|=(1‹‹MOSI); //если 1, то выставляем 1
  byte‹‹=1; //сдвигаем влево, в сторону старшего для проверки следующего бита
  PORTB|=(1‹‹SCK); //фронт на ножке SCK
  asm("nop"); //1 такт подождём
//   asm("nop"); //1 такт подождём
//   asm("nop"); //1 такт подождём
  PORTB&=~(1‹‹SCK); //спад на ножке SCK
  }
/////////////////////////////////////////////////////////////////////////
}

unsigned char SPI_ReceiveByte (void)
{
//////////////////////////////////////////////////////////////////////////////
unsigned char result=0;
for(unsigned char i=0; i‹8; i++)
  {
  PORTB|=(1‹‹SCK); //фронт на ножке SCK
  result‹‹=1; //сдвигаем влево, чтобы записать новый бит
  if ((PINB&(1‹‹MISO))!=0x00) //запишем новый бит (в младший разряд)
  result=result|0x01; //Считать бит данных
  PORTB&=~(1‹‹SCK); //спад на ножке SCK
  asm("nop"); //1 такт подождём
//   asm("nop"); //1 такт подождём
//   asm("nop"); //1 такт подождём
  }
return result;
/////////////////////////////////////////////////////////////////////////////
}

unsigned char SD_cmd(char dt0, char dt1, char dt2, char dt3, char dt4, char dt5) //передача команды (пример даташит стр 40)
{
////////////////////////////////////////////////////////////////////////////
unsigned char result;
long int cnt;
SPI_SendByte (dt0);		//Индекс
SPI_SendByte (dt1);		//Аргумент
SPI_SendByte (dt2);
SPI_SendByte (dt3);
SPI_SendByte (dt4);
SPI_SendByte (dt5);		//контрольная сумма
cnt=0;
do   //Ждем ответ в формате R1 (даташит стр 109)
  {				
  result=SPI_ReceiveByte();
  cnt++;
  }
  while ( ((result&0x80)!=0x00)&&(cnt‹0xFFFF) );
return result;
////////////////////////////////////////////////////////////////////////////
}

unsigned char SD_Init(void)
{
///////////////////////////////////////////////////////////////////////////////////////////
unsigned char temp;
long int cnt;
for (unsigned char i=0; i‹10; i++)	{ SPI_SendByte(0xFF); }		//80 импульсов (не менее 74) Даташит стр 94
PORTB&=~(1‹‹SS);			//опускаем SS
temp=SD_cmd (0x40,0x00,0x00,0x00,0x00,0x95); // CMD0 Даташит стр 102 и 96
if (temp!=0x01) { return 3;}	//Выйти, если ответ не 0х01 (результат
SPI_SendByte (0xFF);
cnt=0;
do
  {
  temp=SD_cmd (0x41,0x00,0x00,0x00,0x00,0x95);	//CMD1 (аналогично CMD0, только индекс меняется)
  SPI_SendByte (0xFF);
  cnt++;
  }
  while ( (temp!=0x00)&&(cnt‹0xFFFF) );		//Ждем ответа R1
if (cnt›=0xFFFF) {return 4;}
return 0;
////////////////////////////////////////////////////////////////////////////////////////////
}

unsigned char SD_Write_Block (char* bf, unsigned char dt1, unsigned char dt2, unsigned char dt3, unsigned char dt4)
{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned char result;
long int cnt;
result=SD_cmd(0x58,dt1,dt2,dt3,dt4,0x95);		//CMD24 даташит стр 51 и 97-98
if (result!=0x00) return 6;			//Выйти, если результат не 0x00
SPI_SendByte (0xFF);
SPI_SendByte (0xFE);				//Начало буфера
for (cnt=0;cnt‹512;cnt++)	SPI_SendByte(bf[cnt]); //Данные
SPI_SendByte (0xFF);				//Котрольная сумма
SPI_SendByte (0xFF);
result=SPI_ReceiveByte();
if ((result&0x05)!=0x05) return 6;		//Выйти, если результат не 0x05 (Даташит стр 111)
cnt=0;
do   //Ждем окончания состояния BUSY
  {						
  result=SPI_ReceiveByte();
  cnt++;
  }
  while ( (result!=0xFF)&&(cnt‹0xFFFF) );
if (cnt›=0xFFFF) return 6;
return 0;
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

unsigned char SD_Read_Block (char* bf, unsigned char dt1, unsigned char dt2, unsigned char dt3, unsigned char dt4)
{
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
unsigned char result;
long int cnt;
result=SD_cmd (0x51,dt1,dt2,dt3,dt4,0x95);		//CMD17 даташит стр 50 и 96
if (result!=0x00) return 5;			//Выйти, если результат не 0x00
SPI_SendByte (0xFF);
cnt=0;
do     //Ждем начала блока
  {						
  result=SPI_ReceiveByte();
  cnt++;
  }
  while ( (result!=0xFE)&&(cnt‹0xFFFF) );
if (cnt›=0xFFFF) return 5;
for (cnt=0;cnt‹512;cnt++)	bf[cnt]=SPI_ReceiveByte(); //получаем байты блока из шины в буфер
SPI_ReceiveByte();					//Получаем контрольную сумму
SPI_ReceiveByte();
return 0;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
}

void SD_work (void)  //основная функция чтения-записи SD
{
//-----------------------------------------------------------------
unsigned char result;
char str[20];

unsigned char SD_adr_0 = 0;
unsigned char SD_adr_1 = 0;
unsigned char SD_adr_2 = 0;
unsigned char SD_adr_3 = 0;

// SD_adr_0 =  SD_adr & 0xff;
// SD_adr_1 = (SD_adr & 0xff00) ›› 8;
// SD_adr_2 = (SD_adr & 0xff0000) ›› 16;
// SD_adr_3 = (SD_adr & 0xff000000) ›› 24;

SD_adr_0 = SD_adr;            //разбивка адреса uint32_t на 4 байта 
SD_adr_1 = SD_adr ›› 8;
SD_adr_2 = SD_adr ›› 16;
SD_adr_3 = SD_adr ›› 24;

sprintf(str,"adr: %02x %02x %02x %02x",SD_adr_3, SD_adr_2, SD_adr_1, SD_adr_0);  //вывод адреса начала блока во 2 сторку экрана
clearlcd();//очистим дисплей
setpos(0,1);
str_lcd(str);

for (unsigned int i=0; i‹512; i++) //затирание buffer2 символами "с" и вывод первых 19 в 3 строку экрана
  {
  buffer2[i] = 'c';
  }
for (unsigned char i=0; i‹=19; i++)
  {
  str[i] = buffer2[i];
  }
setpos(0,2);
str_lcd(str);

port_ini();    //инициализация SD карты, вывод номера ошибки в первую строку экрана (первое число) 0 - нет ошибки
result=SD_Init();
sprintf(str,"error: %d",result);
//clearlcd();//очистим дисплей
setpos(0,0);
str_lcd(str);

result=SD_Write_Block(buffer,SD_adr_3,SD_adr_2,SD_  adr_1,SD_adr_0);//Запишем блок из буфера, вывод номера ошибки в первую строку экрана (второе число) 0 - нет ошибки
sprintf(str,"%d",result);
setpos(9,0);
str_lcd(str);

result=SD_Read_Block(buffer2,SD_adr_3,SD_adr_2,SD_  adr_1,SD_adr_0);	//Считаем блок в буфер, вывод номера ошибки в первую строку экрана (третье число) 0 - нет ошибки
sprintf(str,"%d",result);
setpos(11,0);
str_lcd(str);
//_delay_ms(1000);
for (unsigned char i=0; i‹=19; i++) //вывод первых 19 символолв из буффера в 4 строку экрана
  {
  str[i] = buffer2[i];
  }
buffer2[19] = '\0';
setpos(0,3);
str_lcd(str);
//_delay_ms(1000);

SD_adr = SD_adr + 512;
//-----------------------------------------------------------------
}
//-----------------------------------------------------------------------------------------------------------------------------------
void bibip (uint32_t time_ms, uint32_t freq_hz) //пишание пьезодинамиком на PD0 (время в милисикундах, частота а Герцах)
{
//////////////////////////////////////////////////////////////
uint32_t cycles = 0;
uint32_t period = 0;
period = F_CPU / (24 * freq_hz); //24 - подобранный коэфициент в Протеусе для ATmega328P
cycles = (833 * time_ms)/period; //833 - подобранный коэфициент в Протеусе для ATmega328P
for (unsigned int i =0; i ‹= cycles; i++)
  {
  PORTD |= (1‹‹0);
  for (unsigned int q = 0; q ‹= period; q++){asm("nop");}		
  PORTD &= ~(1‹‹0);
  for (unsigned int q = 0; q ‹= period; q++){asm("nop");}						
  }
///////////////////////////////////////////////////////////////
}

void migalka (void) //мигание светодиодами под пишалку для отладки
{
///////////////////////////////////////////////
PORTB |= (1‹‹0);
bibip(50,500);
_delay_ms(500);
PORTB &= ~(1‹‹0);
PORTB |= (1‹‹1);
bibip(50,1000);
_delay_ms(500);
PORTB &= ~(1‹‹1);
PORTD |= (1‹‹1);
bibip(50,2000);
_delay_ms(500);
PORTD &= ~(1‹‹1);
///////////////////////////////////////////
}
//-----------------------------------------------------------------------------------------------------------------------------------
void timers_ini(void) //настройка таймера1 на 10 ms
{
///////////////////////////////////////////////////////////////////////////
TCCR1B = 0;
TCCR1A = 0;
TCCR1B |= (1‹‹WGM12); // устанавливаем режим СТС (сброс по совпадению) для первого таймера
// 	OCR1AH = 0xFF; //записываем в регистр число для сравнения - старшый байт
// 	OCR1AL = 0x7F; //записываем в регистр число для сравнения - младший байт
OCR1A = 196; //записываем в регистр число для сравнения

TCCR1B |= ( 1 ‹‹ CS12 ) | ( 1 ‹‹ CS10 );//устанавливаем предделитель на 1024
TIMSK1 |= (1‹‹OCIE1A);   // Разрешить прерывание по совпадению OCR1A
//TIMSK1 |= (1‹‹OCIE1B);   // Разрешить прерывание по совпадению OCR1B
//TIMSK1 |= (1‹‹TOIE1);    // Разрешить прерывание по переполнению	
/////////////////////////////////////////////////////////////////////////////
}

ISR (TIMER1_COMPA_vect ) //прерывание таймера1
{
//////////////////дрыгаем PC1 для отладки таймера в протеусе/////////
if ((PINC&0b00000010)) //проверяем состояние PC1
  {
  PORTC &= ~(1‹‹1); //записать в PC1 ноль
  }
  else
   {
   PORTC |= (1‹‹1); //записать в PC1 единицу
   }
///////////////////////антидребезговый код кнопки на PC1/////////////////////
if (0 == (PINC&0b00000001))
  {
  stethik_kn++;
  }
  else
    {
	if (stethik_kn ‹ 0)
	  {
	  stethik_kn++; return;
	  }
    }
if ((stethik_kn › 2)  && (0 == (PINC&0b00000001)))
  {
  stethik_kn = -100;
  bibip(50,1200);
  cli(); //запрещаем прерывание
  SD_work();  
  sei();//разрешить прерывания
  }
///////////////////////////////////////////////////////////////////
}
//-----------------------------------------------------------------------------------------------------------------------------------
int main(void)
{
////////////////////////////////////////////////////////////////////////////////////////////////////	
DDRB |= (1‹‹0); //записать в PC0 единицу (что бы выставить его на выход)
PORTB &= ~(1‹‹0); //записать в PC0 ноль
DDRB |= (1‹‹1); 
PORTB &= ~(1‹‹1);

DDRD |= (1‹‹0);
PORTD &= ~(1‹‹0);
DDRD |= (1‹‹1);
PORTD &= ~(1‹‹1);

DDRC &= ~(1‹‹0); //записать в PC0 ноль (что бы выставить его на вход)
PORTC |= (1‹‹0); //записать в PC0 единицу, для включения резистора подтяжки
DDRC |= (1‹‹1); //записать в PC1 единицу (что бы выставить его на выход)
PORTC &= ~(1‹‹1); //записать в PC1 ноль
//**************************************************  **************************************************  *
timers_ini();
sei();//разрешить прерывания

migalka();

//-----------------------------------------------------------------

	I2C_Init();//инициализируем TWI
	LCD_ini();  //инициализируем дисплей
	clearlcd();//очистим дисплей
	setpos(0,0);
	str_lcd("Hello World!");
	setpos(2,1);
	str_lcd("String 2");
	setpos(4,2);
	str_lcd("String 3");
	setpos(6,3);
	str_lcd("String 4");

//-----------------------------------------------------------------
while(1)
  {					
  migalka();	
  }
////////////////////////////////////////////////////////////////////////////////////////////////
}
Реклама:
Donker вне форума  
Непрочитано 24.10.2018, 19:40  
-Alan-
Прописка
 
Аватар для -Alan-
 
Регистрация: 05.12.2008
Адрес: Россия, Омск
Сообщений: 145
Сказал спасибо: 39
Сказали Спасибо 29 раз(а) в 22 сообщении(ях)
-Alan- на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

Какой у Вас интересный SD_Init()
Всего из полутора десятков строк.

Попробуйте более подробный
Нажмите, чтобы открыть спойлер

Код:
#define R_OK	0
#define R_ERR	1

/* CMD0: response R1 */
#define CMD_GO_IDLE_STATE 0x00
/* CMD1: response R1 */
#define CMD_SEND_OP_COND 0x01
/* CMD8: response R7 */
#define CMD_SEND_IF_COND 0x08
/* CMD9: response R1 */
#define CMD_SEND_CSD 0x09
/* CMD10: response R1 */
#define CMD_SEND_CID 0x0a
/* CMD12: response R1 */
#define CMD_STOP_TRANSMISSION 0x0c
/* CMD13: response R2 */
#define CMD_SEND_STATUS 0x0d
/* CMD16: arg0[31:0]: block length, response R1 */
#define CMD_SET_BLOCKLEN 0x10
/* CMD17: arg0[31:0]: data address, response R1 */
#define CMD_READ_SINGLE_BLOCK 0x11
/* CMD18: arg0[31:0]: data address, response R1 */
#define CMD_READ_MULTIPLE_BLOCK 0x12
/* CMD24: arg0[31:0]: data address, response R1 */
#define CMD_WRITE_SINGLE_BLOCK 0x18
/* CMD25: arg0[31:0]: data address, response R1 */
#define CMD_WRITE_MULTIPLE_BLOCK 0x19
/* CMD27: response R1 */
#define CMD_PROGRAM_CSD 0x1b
/* CMD28: arg0[31:0]: data address, response R1b */
#define CMD_SET_WRITE_PROT 0x1c
/* CMD29: arg0[31:0]: data address, response R1b */
#define CMD_CLR_WRITE_PROT 0x1d
/* CMD30: arg0[31:0]: write protect data address, response R1 */
#define CMD_SEND_WRITE_PROT 0x1e
/* CMD32: arg0[31:0]: data address, response R1 */
#define CMD_TAG_SECTOR_START 0x20
/* CMD33: arg0[31:0]: data address, response R1 */
#define CMD_TAG_SECTOR_END 0x21
/* CMD34: arg0[31:0]: data address, response R1 */
#define CMD_UNTAG_SECTOR 0x22
/* CMD35: arg0[31:0]: data address, response R1 */
#define CMD_TAG_ERASE_GROUP_START 0x23
/* CMD36: arg0[31:0]: data address, response R1 */
#define CMD_TAG_ERASE_GROUP_END 0x24
/* CMD37: arg0[31:0]: data address, response R1 */
#define CMD_UNTAG_ERASE_GROUP 0x25
/* CMD38: arg0[31:0]: stuff bits, response R1b */
#define CMD_ERASE 0x26
/* ACMD41: arg0[31:0]: OCR contents, response R1 */
#define CMD_SD_SEND_OP_COND 0x29
/* CMD42: arg0[31:0]: stuff bits, response R1b */
#define CMD_LOCK_UNLOCK 0x2a
/* CMD55: arg0[31:0]: stuff bits, response R1 */
#define CMD_APP 0x37
/* CMD58: arg0[31:0]: stuff bits, response R3 */
#define CMD_READ_OCR 0x3a
/* CMD59: arg0[31:1]: stuff bits, arg0[0:0]: crc option, response R1 */
#define CMD_CRC_ON_OFF 0x3b 

/* command responses */
/* R1: size 1 byte */
#define R1_IDLE_STATE 0
#define R1_ERASE_RESET 1
#define R1_ILL_COMMAND 2
#define R1_COM_CRC_ERR 3
#define R1_ERASE_SEQ_ERR 4
#define R1_ADDR_ERR 5
#define R1_PARAM_ERR 6
/* R1b: equals R1, additional busy bytes */
/* R2: size 2 bytes */
#define R2_CARD_LOCKED 0
#define R2_WP_ERASE_SKIP 1
#define R2_ERR 2
#define R2_CARD_ERR 3
#define R2_CARD_ECC_FAIL 4
#define R2_WP_VIOLATION 5
#define R2_INVAL_ERASE 6
#define R2_OUT_OF_RANGE 7
#define R2_CSD_OVERWRITE 7
#define R2_IDLE_STATE (R1_IDLE_STATE + 8)
#define R2_ERASE_RESET (R1_ERASE_RESET + 8)
#define R2_ILL_COMMAND (R1_ILL_COMMAND + 8)
#define R2_COM_CRC_ERR (R1_COM_CRC_ERR + 8)
#define R2_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 8)
#define R2_ADDR_ERR (R1_ADDR_ERR + 8)
#define R2_PARAM_ERR (R1_PARAM_ERR + 8)
/* R3: size 5 bytes */
#define R3_OCR_MASK (0xffffffffUL)
#define R3_IDLE_STATE (R1_IDLE_STATE + 32)
#define R3_ERASE_RESET (R1_ERASE_RESET + 32)
#define R3_ILL_COMMAND (R1_ILL_COMMAND + 32)
#define R3_COM_CRC_ERR (R1_COM_CRC_ERR + 32)
#define R3_ERASE_SEQ_ERR (R1_ERASE_SEQ_ERR + 32)
#define R3_ADDR_ERR (R1_ADDR_ERR + 32)
#define R3_PARAM_ERR (R1_PARAM_ERR + 32)
/* Data Response: size 1 byte */
#define DR_STATUS_MASK 0x0e
#define DR_STATUS_ACCEPTED 0x05
#define DR_STATUS_CRC_ERR 0x0a
#define DR_STATUS_WRITE_ERR 0x0c

/* status bits for card types */
#define SD_RAW_SPEC_1 0
#define SD_RAW_SPEC_2 1
#define SD_RAW_SPEC_SDHC 2 


uint8_t sd_raw_card_type;

uint8_t SPI_Rd_Byte(void) {
	SPDR = 0xFF;
	while(!(SPSR & (1‹‹SPIF)));
	return SPDR;
};
void SPI_Wr_Byte(uint8_t DataByte) {
	while(!(SPSR & (1‹‹SPIF)));
	SPDR = DataByte;
};
uint8_t SPI_Ex_Byte(uint8_t DataByte) {
	SPDR = DataByte;
	while(!(SPSR & (1‹‹SPIF)));
	return SPDR;
};
uint8_t SPI_SD_SendCMD(uint8_t command, uint32_t arg) {
	uint8_t response;
	/* wait some clock cycles */
	SPI_Rd_Byte();	// DUMMY
	SPI_Rd_Byte();	// DUMMY
	SPI_Wr_Byte(0x40 | command);
	SPI_Wr_Byte((arg ›› 24) & 0xFF);
	SPI_Wr_Byte((arg ›› 16) & 0xFF);
	SPI_Wr_Byte((arg ›› 8) & 0xFF);
	SPI_Wr_Byte((arg ›› 0 )& 0xFF);
	switch(command)
	{
	case CMD_GO_IDLE_STATE:
		SPI_Wr_Byte(0x95);
		break;
	case CMD_SEND_IF_COND:
		SPI_Wr_Byte(0x87);
		break;
	default:
		SPI_Wr_Byte(0xff);
		break;
	};
	 /* receive response */
	for(uint8_t i = 0; i ‹ 10; ++i)
	{
		response = SPI_Rd_Byte();
		if(response != 0xff)
			break;
	};
	return response;
};

uint8_t SPI_SD_CardInit(void) {
	uint8_t response;
	SPI_Init();  // Логично, что инициализация SPI интерфейса. Удалить, если уже выполнено
	/* initialization procedure */ 
	sd_raw_card_type = 0;
	SPI_UnSelect_CARD(); // Поднимаем пин /CS
	for(uint8_t i = 0; i ‹ 10; ++i)
	{
		SPI_Rd_Byte();
	};
	for(uint16_t i = 0; ; ++i)
	{
		SPI_Select_CARD(); // Аналогично, опускаем пин
		response = SPI_SD_SendCMD(CMD_GO_IDLE_STATE, 0);	// Card.State-›IDLE..
		SPI_UnSelect_CARD();  // Снова поднимаем пин
		if (response == (1 ‹‹ R1_IDLE_STATE))
			break;
		if (i == 0x1ff)
			return R_ERR;					// Таймаут...
	};
	SPI_Select_CARD();
	response = SPI_SD_SendCMD(CMD_SEND_IF_COND, 0x100 /* 2.7V - 3.6V */ | 0xaa /* test pattern */);
	if((response & (1 ‹‹ R1_ILL_COMMAND)) == 0)
	{
		SPI_Rd_Byte();
		SPI_Rd_Byte();
		if ((SPI_Rd_Byte() & 0x01) == 0)
			return R_ERR;		// Card operation voltage range doesn't match
		if (SPI_Rd_Byte() != 0xaa)
			return R_ERR;		// Wrong test pattern.
		sd_raw_card_type |= (1 ‹‹ SD_RAW_SPEC_2);
		SPI_UnSelect_CARD();
	} else {
		/* determine SD/MMC card type */
		SPI_UnSelect_CARD();
		SPI_Select_CARD();
		SPI_SD_SendCMD(CMD_APP, 0);
		SPI_UnSelect_CARD();
		SPI_Select_CARD();
		response = SPI_SD_SendCMD(CMD_SD_SEND_OP_COND, 0);
		SPI_UnSelect_CARD();
		if((response & (1 ‹‹ R1_ILL_COMMAND)) == 0)
		{
			/* card conforms to SD 1 card specification */
			sd_raw_card_type |= (1 ‹‹ SD_RAW_SPEC_1);
		} else {
			// MMC card
		};
	};
	SPI_UnSelect_CARD();
	SPI_Select_CARD();
	/* wait for card to get ready */
	for(uint16_t i = 0; ; ++i)
	{
		if(sd_raw_card_type & ((1 ‹‹ SD_RAW_SPEC_1) | (1 ‹‹ SD_RAW_SPEC_2)))
		{
			uint32_t arg = 0;
			if(sd_raw_card_type & (1 ‹‹ SD_RAW_SPEC_2))
				arg = 0x40000000;
			SPI_SD_SendCMD(CMD_APP, 0);
			response = SPI_SD_SendCMD(CMD_SD_SEND_OP_COND, arg);
		} else {
			response = SPI_SD_SendCMD(CMD_SEND_OP_COND, 0);
		};
		if((response & (1 ‹‹ R1_IDLE_STATE)) == 0)
			break;
		if(i == 0x7fff)
		{
			SPI_UnSelect_CARD();
			return R_ERR;
		};
	};
	SPI_UnSelect_CARD();
	SPI_Select_CARD();
	if(sd_raw_card_type & (1 ‹‹ SD_RAW_SPEC_2))
	{
		if(SPI_SD_SendCMD(CMD_READ_OCR, 0))
		{
			SPI_UnSelect_CARD();
			return R_ERR;
		};
		if(SPI_Rd_Byte() & 0x40)
			sd_raw_card_type |= (1 ‹‹ SD_RAW_SPEC_SDHC);
		SPI_Rd_Byte();
		SPI_Rd_Byte();
		SPI_Rd_Byte();
	};
	SPI_UnSelect_CARD();
	SPI_Select_CARD();
	if(SPI_SD_SendCMD(CMD_SET_BLOCKLEN, 512))
	{
		SPI_UnSelect_CARD();
		return R_ERR;
	};
	/* deaddress card */
	SPI_UnSelect_CARD();
	SPI_SetFast();
#if !USE_EXT_BUF
	raw_block_buffered = 1;
	SPI_SD_READ_SECTOR(0);
#endif
	return R_OK;
};

Последний раз редактировалось -Alan-; 25.10.2018 в 20:22. Причина: Код ломал спойлер кода
-Alan- вне форума  
Непрочитано 24.10.2018, 19:45  
Paul74s
Частый гость
 
Регистрация: 19.05.2014
Сообщений: 48
Сказал спасибо: 5
Сказали Спасибо 11 раз(а) в 11 сообщении(ях)
Paul74s на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

Почему не используешь железный SPI ? Может ошибки в нем ? Скорость SPI какая ?
Маленькие и старые карты в большинстве случев нормально инициализируются на больших скоростях, а вот SDHC нужно инициализовать на скоростях в несколько сот кГц.
Сам пользую SD-карты как внешнюю память к АТмеге328п, хорошо работает и с 16 Мб и с 2 Гб, но я и не думал цеплять SDHC, если надо могу кинуть свои процы, но они на CVAVR.
Paul74s вне форума  
Непрочитано 24.10.2018, 20:59  
Donker
Временная регистрация
 
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Donker на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

-Alan- спасибо, но смогу проверить только сегодня поздно вечером или завтра.

Paul74s, софтовый SPI потому что у человека который писал пример не получилось запустить на аппаратном.

Писать проекты надо под те карточки, что продаются в магазинах, самые дешевые SDHC от 4 гб. далее идут SD 2Гб их очень мало, и они дороже, выпускаются для совместимости со старыми устройствами, снимаются с производства!

Кто подскажет, посылать 74 импульса в начале инициализации надо при опущенной линии CS или при поднятой?
Donker вне форума  
Непрочитано 24.10.2018, 22:36  
Paul74s
Частый гость
 
Регистрация: 19.05.2014
Сообщений: 48
Сказал спасибо: 5
Сказали Спасибо 11 раз(а) в 11 сообщении(ях)
Paul74s на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

При поднятом, но достаточно и 1-2 байт по спи послать.
Железный спи может не запускаться если не используется вывод SS.
Paul74s вне форума  
Непрочитано 25.10.2018, 01:09  
Donker
Временная регистрация
 
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Donker на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

Я пока застрял на проблеме отображения сигнала SPI в Протеусе,
даже тему отдельную создал:
https://kazus.ru/forums/showthread.p...37#post1224937

потому как отлаживать в желе долго, и можно израсходовать ресурс записи
контроллера, и так ничего и не добиться, да и нормального физического осциллографа у меня нет.
Donker вне форума  
Непрочитано 25.10.2018, 02:00  
jump
Почётный гражданин KAZUS.RU
 
Регистрация: 20.06.2006
Адрес: Украина, Запорожье
Сообщений: 7,981
Сказал спасибо: 0
Сказали Спасибо 4,941 раз(а) в 2,370 сообщении(ях)
jump на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

Сообщение от Donker Посмотреть сообщение
можно израсходовать ресурс записи
контроллера
за несколько тысяч циклов?
Сообщение от Donker Посмотреть сообщение
нормального физического осциллографа у меня нет
китайский лог. анализатор стоимостью в несколько бутылок пива поможет
jump вне форума  
Сказали "Спасибо" jump
mike-y-k (25.10.2018)
Непрочитано 25.10.2018, 20:24  
-Alan-
Прописка
 
Аватар для -Alan-
 
Регистрация: 05.12.2008
Адрес: Россия, Омск
Сообщений: 145
Сказал спасибо: 39
Сказали Спасибо 29 раз(а) в 22 сообщении(ях)
-Alan- на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

Сообщение от Donker Посмотреть сообщение
Кто подскажет, посылать 74 импульса в начале инициализации надо при опущенной линии CS или при поднятой?
Посылать нужно не менее 74 импульсов. Я читаю 10 байт при поднятом /CS.

Кстати, исправил код под спойлером.

Забавно...
Если убрать пробелы из строки (1 ‹‹ R1_ILL_COMMAND), то сообщение закончится после первого символа "‹".
-Alan- вне форума  
Непрочитано 26.10.2018, 03:09  
Donker
Временная регистрация
 
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
Donker на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

Сделал задержки, сейчас 80 импульсов начала инициализации посылаются на 100кГц а посылка - приём байтов на 1мГц, до этого было везде 1,5...2мГц (см. переделанный ATmega328P + SD (2).zip)

Поведение в железе никак не изменилось, завтра буду разбираться с кодом -Alan-.
Вложения:
Тип файла: zip ATmega328P + SD (2).zip (221.6 Кб, 0 просмотров)
Donker вне форума  
Непрочитано 26.10.2018, 06:32  
Paul74s
Частый гость
 
Регистрация: 19.05.2014
Сообщений: 48
Сказал спасибо: 5
Сказали Спасибо 11 раз(а) в 11 сообщении(ях)
Paul74s на пути к лучшему
По умолчанию Re: Подключение разных SD карт к ATmega328P, как?

всю процедуру инициализации проводи на частотах 100-600 кГц, а уже обмен на больших скоростях.
Некоторые устройства на низких частотах, например 100 кГц, могут не работать, а на 150 кГц уже работают нормально.
Paul74s вне форума  
 

Закладки
Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Схемотехническое обозначение элементов разных стран и разных годов. johanh Электроника - это просто 17 05.01.2017 03:15
Вопрос по коммутации нескольких SIM карт в GSM модуле Sim900D Flopix Автоматика и аппаратура связи 13 27.10.2016 20:17
Просто pictures from the Internet with comments ... bocem Отвлекитесь, эмбеддеры! 14042 26.04.2015 10:47
Доработка встроенных звуковых карт bober87 Делимся опытом 58 07.06.2012 23:13
[Решено] Ишю принципиальную схему жёскоо диска или карт ридера отчаевшийся студент Делимся опытом 1 20.10.2005 12:39


Часовой пояс GMT +4, время: 14:58.


Powered by vBulletin® Version 3.8.4
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot