Ds1307 і avr

Розберемося з BCD форматом. BCD формат (Binary-Coded Decimal) це двійковій -десятічний формат, який може бути неупакований і упакований. При першому варіанті десяткова цифра займає цілий байт, недоліком при цьому є неекономічні використання пам'яті, тому що старший напівбайт завжди дорівнює 0. Плюсом є те що не виникає різночитань, тобто цифра в шістнадцятковому вигляді дорівнює в десятковому, також немає необхідності виконувати додаткових операцій.

Другий варіант упакований, і для зберігання десяткового числа використовує тетраду (ниббл, напівбайт), тобто чотири розряду. Оскільки пам'ять регістрів обмежена то, в даному випадку в старшому підлозі байті зберігається другого десяткового число. Так ось наші "годинник", як раз працюють в такому варіанті.

Пам'ятаємо, що внутрішні уявлення чисел в регістрах - бінарне. Тому упакований BCD формат дає унікальну можливість не тільки економити байти, а ще й поряд з виведеної інформацією з байта містити в собі настроювальні біти (рис. Нижче), наприклад в попередній статті (№29) в таблиці регістрів 2 -й регістр з виведення годин 6 і 5 біт, котрі містять конфігураційні біти. а вже 5 (в залежності від налаштувань 6) і 4-й містять 2-й і 1-й десяток годин відповідно, і інші 4 молодших біта - двійкове подання одиниць годин, звідси і BCD формат.

Хочеться також відзначити що деякі мікропроцесорні системи мають спеціальну інструкцію для корекції даного формату, але в AVR. такої інструкції немає. Але це не біда, як Ви побачите нижче, невеликими арифметичними операціями ми легко робитимемо конвертацію.

Розберемо додаткові операції для другого варіанту на прикладі. Наприклад необхідно записати десяткове число 37, в BCD форматі воно матиме вигляд 11 0111. Наприклад калькулятор витлумачить бінарний код, як десяткове 55. Або десяткове 37 як 10 0101. Тому необхідно провести наступні операції .:

- 37 ділимо на 10, в результаті отримуємо ціле число 3, все дробове відкидаємо, отримуємо в бінарному вигляді 0000 0011;
- зрушуємо молодшу частину полубайта, що містить 3 на 4 біта вліво. вже маємо вид 0011 0000;
- тепер застосовуємо розподіл по модулю 10 (% 10), тобто число 37% 10. В результаті отримуємо 7, в буфері маємо бінарний код 0000 0111;
- і останні - виробляємо складання 0011 0000+ 0000 0111 = 11 0111;
- все відправляємо даний код в годинник.

Нижче код з перетворення числа в двійковій десятковий формат:

time = ((time / 10)<<4) + time%10;
TWDR = time;

який вставляємо в функцію запису (яку розглянули в попередній статті №29), перед занесенням інформації в регістр даних.

void write_DS1307 (uint8_t reg, uint8_t time)
time = (((time 0xF0) >> 4) * 10) + (time 0x0F);

Спочатку виділяємо старший напівбайт, переносимо в молодший. множимо на 10 і отримуємо десятки. Далі виділяємо молодшу частину і все це складав і отримуємо результат.

Щодо попередньої статті (№29) в програму додані бібліотеки семи сегментного індикатора. А в головній функції, лічений і конвертоване час, годинник і хвилини, перекладаю і відправляю на індикацію наступним чином

m = read_DS1307 (0 × 01); // Новомосковськ хвилини
_delay_ms (100); // затримка необхідна для симулятора
h = read_DS1307 (0 × 02); // Новомосковськ годинник
_delay_ms (100); // затримка
i = h + (m * 0.01); / * Передаємо індикатору формат часу, для цього хвилини множимо на 0,01 і додаємо годинник, отримуємо наступний формат чч, мм * /
Display (i); // функція виведення на індикатор

Як бачите нічого складного. Вихідні тексти і проект викладені в кінці статті. Нижче результат в Proteus і в залозі. Напевно треба відзначити різницю між ними:

- для індикатора в протеус затримка на вимикання транзисторів 50 мс, в залозі 30;

- як бачите вище між функціями передачі прийому інформації для протеуса ставимо затримку 100мс. Для заліза можна і неставіть.

Ds1307 і avr
Ds1307 і avr

Вихідні тексти і проект

На цьому все. У наступній статті інтегруємо написаний код для годин в наш контролер збору даних. Підведемо підсумок. Заплануємо залишилася роботу для доведення проекту до кінця. Пробуйте, експериментуйте. Бувайте усі.

Здрастуйте, у мене є програма для DS1302 і з дозволу адміна хотів би викласти її тут, може вона комусь стане в нагоді. Не буду стверджувати, що вона ідеальна, так як я новачок в програмування, проте може хто то більш досвідчений підкаже як її оптимізувати. Почну з опису. Порт D підключений до семисегментний індикатор через резистори 330 Ом. PB6, PB7 - кнопки установки годин і хвилин, PC1 - кнопка при натисканні на яку (потрібно тримати постійно) програма переходить в установку часу. При віджиманні починається зчитування часу. Кнопки підтягнуті до плюса через резистор на 10 кОм. Думаю їх можна не ставити, якщо включати підтяжку на відповідних портах, але у мене вони стоять так я думаю надійніше. PB0, PB1, PB2, PB3 - порти які відповідають за включення відповідної цифри, включені через транзистори у мене це КП505. Між портом і затвором транзистора ставляться резистори на 3 кОм, між затвором і землею на 10 кОм (хоча це може і зайве). Исток підключений до землі, стік до відповідної цифри на індикаторі. DS1302 підключена наступним чином 5 - PC5 - rst, 6 - PC4 - I / O - дані, 7 - PC3 - sclk - синхроімпульсів. Підключення харчування до мікроконтролеру і ds1302 стандартно.

тут виробляємо визначення портів і призначаємо змінні