Підключення карти sd до avr

Далі перейдемо безпосередньо до розгляду карти.
Secure Digital Memory Card (SD) - формат карт пам'яті, розроблений для використання в основному в портативних пристроях. Щоб розібратися в її роботі ми будемо використовувати специфікацію, яка описує даний стандарт і називається SD Specifications ver3.01.
Перше що нам необхідно, так це розібратися як працювати з цією картою, як підключити та інше. Спочатку виберемо карту. Для експериментів я взяв microSD ємністю 2Гб, стандарт ємності SDSC. Шина карти може працювати по двох протоколах SD і SPI. Хочеться відзначити що дана карта це свого роду модифікація карти MMC, де (в карті SD) основна увага була приділена системі безпеки. Тому алгоритм роботи по протоколу SPI такий же, ну і звичайно ж вони односторонньо сумісні. Тобто ми можемо в слот SD карти вставити MMC, але не навпаки.

На малюнку нижче представлена ​​схема підключення карти SD по протоколу SPI.
Даний інтерфейс дозволяє обмінюватися даними на високій швидкості, задіявши при цьому мінімальна кількість висновків мікроконтролера, які оснащені

Підключення карти sd до avr
модулем SPI. З цього моменту почнемо використовувати специфікацію. Перше що нас інтересует- вибір режиму. Розберемося в тонкощах на рис. нижче з розділу 6.4.1.1 представлена ​​діаграма напруги харчування і послідовність посилки команди. Тут чітко видно що після включення карти необхідно почекати кілька мілісекунд (1мс + від 0.1 до 35 мс (наростання)) на стабілізацію. Протягом цього часу на CS, MOSI лінії повинна бути подана 1. Далі відбувається затримка ініціалізації максимум 1 мс, при подачі на вхід CLK 74 імпульсів (тактів), після чого повинна йти команда CMD0. Перейдемо до глави 7 де чітко описана послідовність дій.

Діаграма напруги харчування
Підключення карти sd до avr

В процесі скидання, карта повинна відповісти 0 × 01, що відповідає першому біту.

У специфікації є чітка послідовність ініціалізації для SPI. Для чого використовується команда CMD8 для перевірки робочого стану карти, де відбувається досить не простий алгоритм перевірки. Далі команда CMD58 для визначення типу карти SDSD або SDHC і SDXC. А також команда CMD41 для запуску та перевірки ініціалізації. Досить не простий процес ініціалізації з перевірками, але я думаю що для простого запису даних можна використовувати більш спрощений процес. У розділі 7.2.7. йдеться, що в режимі очікування єдино допустимі команди для картки CMD41, CMD8, CMD58, CMD59. а також для карт (товстих 2.1мм) пам'яті SD CMD1, який ідентичний команді CMD41. У стандарті ця команда вважається забороненою для ініціалізації, і використовується виключно для відмінності карт 1,4мм і 2,1 мм.
Підемо більш простим шляхом і використовуємо команду CMD1. Все вище описане відобразимо в коді у функції ініціалізації, але перед цим розглянемо формат команди. Кожна команда або блок даних складаються з восьми бітних байтів, які вирівнюються по сигналу CLK. Тобто кожна команда вирівнюється по межі 8 тактів. Повідомлення SPI складаються з команди, відповіді і даних. Вся зв'язок контролюється мікро контролером. Всі команди мають довжину 6 байт. Передача починається з першого лівого біта.

На малюнку нижче представлений формат команди.
Старт біт - з 0 починається будь-яка команда. Рухаючись біт - теж завжди дорівнює 1.
Індекс - безпосередньо передається команда.
Аргумент- для кожної команди аргумент вказано в таблиці специфікації.
CRC - перевірка надмірності коду. За замовчуванням в режимі SPI вона відключена. Тому ми її використовуємо тільки для команди CMD0, яка надсилається до входу в режим і має значення CRC 0 × 95.
Стоп біт - кінець переданої команди.
Що ж приступимо до написання коду.
Почнемо з необхідних 2-х функцій: передача і прийом байта.
1. Передача байта карті.
void trans_byte_sd (unsigned char data) // передаємо масив бітів
for (unsigned char i = 0; i<8;i++) //Перебираем байт
if ((data0 × 80) == 0 × 00) // Якщо старший біт = 0
return data; // Повертаємо відповідь
3.Передача команди.
long int i = 0; // змінна для лічильника
unsigned char r1; // відповідь карти
trans_byte_sd (CMD); // команда
trans_byte_sd (0 × 00);
trans_byte_sd (0 × 00);
trans_byte_sd (0 × 00);
trans_byte_sd (0 × 95); // Передача CRC
/ * Після передачі команди чекаємо відповіді формату R1.Каждой команді відповідає своя відповідь * /
/ * Цикл для очікування отримання відповіді за певний час * /
r1 = receive_byte_sd ();
> While (((r10 × 80)! = 0 × 00) (i<0xffff)); /* Как только старший бит байта не равен 0 и i не превышает 65 535 тактов*/
return r1; // Повертаємо відповідь
4. І ніціалізація карти.

Тепер ми можемо прописати ініціалізацію карти. Коротко програма описується наступним чином: перше що необхідно, так це перевести карту в режим SPI. При подачі живлення карта встановлюється в режим SD. Для вибору режиму SPI на вхід CS подається логічний 0, в цей же час подається команда скидання CMD0 і ініціалізації CMD1 на вхід карти MOSI. Звернемо увагу що команда починається від шістнадцятирічного 0 × 40, до якого необхідно додати номер команди CMD в шістнадцятковому вигляді.

unsigned char spi_card_init (void) // функція повертає відповідь
unsigned char r1; // змінна для прийому відповіді
long int i = 0; // змінна для лічильника
_delay_ms (10); // невелика затримка для стабілізації напруга.
PORTB | = _BV (PB1); // CS, встановлюємо 1, при подачі тактів
PORTB | = _BV (PB3); // лінія подачі команд - 1 MOSI (DI)
for (unsigned char i = 0; i<80;i++) // посылаем более 74 импульса
PORTB | = _BV (PB5); // CLK - 1
asm ( «nop»); // затримка в один такт
PORTB =

_BV (PB5); // CLK - 0

PORTB =

_BV (PB1); / * Умова для входу в режим SPI лінія CS повинна бути дорівнює 0 * /

if (r1! = 0 × 01) return 4; // коди помилок можете ставити будь-які
trans_byte_sd (0xff); / * Посилаємо стрибає, своєрідна пауза перед прийомом відповіді * /
do // цикл прослухати відповідь від карти
r1 = comand_sd (0 × 41,0 × 00); / * Посилаємо команду ініціалізації * /
trans_byte_sd (0xff); // пауза
i ++; // лічильник
> While ((r1! = 0) (i<65535)); /*пока не получен ответ 0 и количество циклов не превышает 0xffff */
if (i> = 0xffff) return 5; / * Повертаємо помилку якщо перевищило час опитування * /
return 0; // Повертаємо 0 в разі успішної ініціалізації

Наступний важливий момент, в специфікації пишеться, що інформація передається блоками, по 512 біт, причому якщо карта SDSC як в нашому випадку, то довжину блоку можн0 встановити від 1 до 512 біт командою CMD16. За замовчуванням 512 біт. Далі опишемо дві функції прийому і передачі блоків. У специфікації дані блок-діаграми, спираючись на які ми напишемо код.

Передача блоку інформації на карту.

За передачу ЄДИНОГО блоку відповідає команда CMD24. Після подачі команди, чекаємо відповідь після чого слід стартовий байт, який готує контроллер карти до прийому інформації, по закінченню карта відповідає байтом про стан передачі, який описаний в главі 7.3.3.1. Тобто правильна відповідь повинна бути = 5. Також чекаємо звільнення шини для подальшої передачі.

Підключення карти sd до avr

Байт відкликання про стан передачі.

У розділі 7.3.3.2 описується формат переданого блоку

Підключення карти sd до avr

5. Передача блоку інформації.
long int i; // лічильник
unsigned char r1; // відповідь
r1 = comand_sd (0 × 58, arg); // CMD24
if (r1! = 0 × 00) return 6; // вихід якщо відповідь не 0
trans_byte_sd (0xff); // невелика пауза
trans_byte_sd (0xfe); // передаємо стартовий байт
for (int i = 0; i<512;i++) //передаем данные
trans_byte_sd (block [i]);
trans_byte_sd (0xff); // байт CRC
trans_byte_sd (0xff); // байт CRC
r1 = receive_byte_sd (); // отримуємо байт підтвердження
if ((r10 × 05)! = 0 × 05) return 7; // перевірку на правильну передачу
do // Чекаємо звільнення шини
r1 = receive_byte_sd ();
> While ((r1! = 0xff) (i<65535));
if (i> = 0xffff) return 8;
return 0; // повертаємо 0 в разі успішної передачі

6. І остання функція - читання блоку. Процедура в принципі та ж що і з передачею, тільки на прийом: спочатку стартовий байт, далі 512 біт і 2 байта на перевірку коду. Пам'ятайте, навіть якщо CRC відключено ми все одно зобов'язані відправляти і приймати 2 байта. Такий формат блоку.

Підключення карти sd до avr

long int i = 0;
unsigned char r1;
r1 = comand_sd (0X51, arg); // CMD17
if (r1! = 0 × 00) return 5; // Вийти, якщо відповідь не 0 × 00
trans_byte_sd (0xff);
do // Чекаємо початку пакета даних
r1 = receive_byte_sd ();
> While ((r1! = 0xfe) (i<65535));
if (i> = 0xffff) return 5;
for (int i = 0; i<512;i=i+1) //прием данных
block [i] = receive_byte_sd ();
receive_byte_sd (); // байт CRC
receive_byte_sd (); // байт CRC
return 0;

Перед тим як використовувати програму, розглянемо апаратну частину. Як ми говорили, вище, що карта сумісна з мікро контролером в режимі SPI. Відзначимо наступні нюанси роботи з картою:
1. Сполучення логічних рівнів, необхідно при різній напрузі живлення SD-карти і мікроконтролера AVR. Можна використовувати резистивний дільник напруги, який є лінійним, тобто. напруга на виході залежить від напруги на вході. А можна паралельний параметричний стабілізатор напруги на стабілітроні, теж що і перший варіант, тільки в нижньому плечі використовується стабілітрон, який є нелінійним дільником, і стежить за опорною напругою за рахунок своїх властивостей при підвищенні вхідної напруги зменшувати внутрішній опір, і навпаки.
Я використовував другий варіант. У схемі нижче на сигнальній лінії опору є баластними (токоогранічітелі), на вхід дільника надходить напруга 4,5 - 5 В, а вихідна знімається з нижнього плеча дільника. Токоогранічітелі необхідні для захисту карти і іншої периферії при збоях мікроконтролера. При добре налагодженому пристрої в них немає необхідності.
Зауважте, що лінія MISO не потребує узгодження, тому що працює тільки в одну сторону від карти до мікроконтролеру.
2. Другий момент, я не використовую перевірку наявності картки і захисту записи. У кого тобто ці контакти в слотах, у кого то немає.
3. Останній момент-харчування. Або ВИ маєте 3.3 вольта всю схему, включно з мікро контролером, або ставите дільник на вхід схеми, не дуже надійно. Або стабілізатор 3.3 вольта, як я і зробив на мікросхемі LP2980. Важливим моментом тут є електролітичний (танталовий) конденсатор, який захищає мікроконтролер від скидання при просадках напруги.
Нижче представлена ​​програма і результат. Як завжди, я намагаюся використовувати одну програму постійно її змінюючи. Даний код взятий зі статті №5 (семисегментний індикатор).

#include
#include
#include
#include
// макроси для роботи з індикатором
#define a 128
#define b 32
#define c 8
#define d 2
#define e 1
#define f 64
#define g 16
#define dp 4
char block [512] =<>; // буфер запису / читання даних на карту
short unsigned int j, k = 0; // в макросі переривання
unsigned char Slot [11]; // Масив чисел для відображення на індикаторі
void trans_byte_sd (unsigned char data); // функція передачі байта
unsigned char receive_byte_sd (void); // Функція прийому байта
unsigned char comand_sd (char, char); // функція передачі команди
unsigned char spi_card_init (void); // Функція ініціалізації карти пам'яті
unsigned char receive_block_sd (char * block, char arg); // Функція прийому блоку
unsigned char trans_block_sd (char * block, char arg); // Функція передачі блоку
// Ініціалізації індикатора
void Slot_init ()
// Висновок на індикатор
ISR (TIMER0_OVF_vect)

Важливий момент - це тайм-аути. Важливо стежити за часом читання записи і стирання карти, так як може зависнути мікроконтролер в режимі очікування відповіді карти. У специфікації чітко описані таймаут карти. Простий карти триває 5 мс, після чого переходить в енергозберігаючий режим, в якому припустимі наступні команди CMD0, CMD1, CMD41 і CMD58. Тому при перевищенні ліміту простою передаємо CMD1, відповідь і далі працюємо з картою.
Внизу представлено два скріншота з програми WinHex. за допомогою якої ми можемо подивитися вміст комірок пам'яті. Програма працює наступним чином: Записуємо дані в буфер, оговтується карті, Обнуляємо буфер, зчитуємо дані з карти в буфер і виводимо на дисплей тим самим переконуємося в передачі даних мапі. Дивимося вміст карти, Обнуляємо буфер, записуємо 0 в карту і знову відкриваємо вміст карти, тим самим переконуємося в працездатності програми і схеми. Як завжди незабутній про дрібниці, таких що не допайка, не великі трещенкі в доріжках і ін. Що може забрати левову частку часу. Тому якщо є під руками осцилограф, то неодмінно використовуйте його для налагодження. У статті №24 я привів невеличкий приклад діагностики карти на всіх етапах її роботи.

Підключення карти sd до avr

Підключення карти sd до avr

Підключення карти sd до avr
Ну ось в принципі і все. У наступній статті, перед тим як описувати файлову систему і створювати логгер ми познайомимося з датчиком вологості і температури DHT11. Після чого почнемо записувати дані (температуру і вологість) в текстовий файл, своєрідну базу даних. Поки на цьому все. Бувайте усі.

Схожі статті