AVR Раздел по микроконтроллерам компании Atmel - AVR / ATtiny / ATmega / ATMega128 / ATxmega, вопросы по программированию в AVR studio и все, относящееся к AVR... |
24.10.2018, 13:31
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Подключение разных 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();
}
////////////////////////////////////////////////////////////////////////////////////////////////
} |
|
|
|
|
24.10.2018, 19:40
|
|
Прописка
Регистрация: 05.12.2008
Адрес: Россия, Омск
Сообщений: 145
Сказал спасибо: 39
Сказали Спасибо 29 раз(а) в 22 сообщении(ях)
|
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.
Причина: Код ломал спойлер кода
|
|
|
|
24.10.2018, 19:45
|
|
Частый гость
Регистрация: 19.05.2014
Сообщений: 48
Сказал спасибо: 5
Сказали Спасибо 11 раз(а) в 11 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
Почему не используешь железный SPI ? Может ошибки в нем ? Скорость SPI какая ?
Маленькие и старые карты в большинстве случев нормально инициализируются на больших скоростях, а вот SDHC нужно инициализовать на скоростях в несколько сот кГц.
Сам пользую SD-карты как внешнюю память к АТмеге328п, хорошо работает и с 16 Мб и с 2 Гб, но я и не думал цеплять SDHC, если надо могу кинуть свои процы, но они на CVAVR.
|
|
|
|
24.10.2018, 20:59
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
-Alan- спасибо, но смогу проверить только сегодня поздно вечером или завтра.
Paul74s, софтовый SPI потому что у человека который писал пример не получилось запустить на аппаратном.
Писать проекты надо под те карточки, что продаются в магазинах, самые дешевые SDHC от 4 гб. далее идут SD 2Гб их очень мало, и они дороже, выпускаются для совместимости со старыми устройствами, снимаются с производства!
Кто подскажет, посылать 74 импульса в начале инициализации надо при опущенной линии CS или при поднятой?
|
|
|
|
24.10.2018, 22:36
|
|
Частый гость
Регистрация: 19.05.2014
Сообщений: 48
Сказал спасибо: 5
Сказали Спасибо 11 раз(а) в 11 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
При поднятом, но достаточно и 1-2 байт по спи послать.
Железный спи может не запускаться если не используется вывод SS.
|
|
|
|
25.10.2018, 01:09
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
Я пока застрял на проблеме отображения сигнала SPI в Протеусе,
даже тему отдельную создал:
https://kazus.ru/forums/showthread.p...37#post1224937
потому как отлаживать в желе долго, и можно израсходовать ресурс записи
контроллера, и так ничего и не добиться, да и нормального физического осциллографа у меня нет.
|
|
|
|
25.10.2018, 02:00
|
|
Почётный гражданин KAZUS.RU
Регистрация: 20.06.2006
Адрес: Украина, Запорожье
Сообщений: 7,981
Сказал спасибо: 0
Сказали Спасибо 4,941 раз(а) в 2,370 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
Сообщение от Donker
|
можно израсходовать ресурс записи
контроллера
|
за несколько тысяч циклов?
Сообщение от Donker
|
нормального физического осциллографа у меня нет
|
китайский лог. анализатор стоимостью в несколько бутылок пива поможет
|
|
|
|
25.10.2018, 20:24
|
|
Прописка
Регистрация: 05.12.2008
Адрес: Россия, Омск
Сообщений: 145
Сказал спасибо: 39
Сказали Спасибо 29 раз(а) в 22 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
Сообщение от Donker
|
Кто подскажет, посылать 74 импульса в начале инициализации надо при опущенной линии CS или при поднятой?
|
Посылать нужно не менее 74 импульсов. Я читаю 10 байт при поднятом /CS.
Кстати, исправил код под спойлером.
Забавно...
Если убрать пробелы из строки (1 ‹‹ R1_ILL_COMMAND), то сообщение закончится после первого символа "‹".
|
|
|
|
26.10.2018, 03:09
|
|
Временная регистрация
Регистрация: 12.09.2018
Сообщений: 92
Сказал спасибо: 6
Сказали Спасибо 0 раз(а) в 0 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
Сделал задержки, сейчас 80 импульсов начала инициализации посылаются на 100кГц а посылка - приём байтов на 1мГц, до этого было везде 1,5...2мГц (см. переделанный ATmega328P + SD (2).zip)
Поведение в железе никак не изменилось, завтра буду разбираться с кодом -Alan-.
|
|
|
|
26.10.2018, 06:32
|
|
Частый гость
Регистрация: 19.05.2014
Сообщений: 48
Сказал спасибо: 5
Сказали Спасибо 11 раз(а) в 11 сообщении(ях)
|
Re: Подключение разных SD карт к ATmega328P, как?
всю процедуру инициализации проводи на частотах 100-600 кГц, а уже обмен на больших скоростях.
Некоторые устройства на низких частотах, например 100 кГц, могут не работать, а на 150 кГц уже работают нормально.
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 14:58.
|
|