Работа с DS1307:
DS1307.c
#include "TWI.h"
#define DS1307 0xD0 // адрес шины I2C для микросхемы DS1307 RTC
#define SECONDS_REGISTER 0x00
#define MINUTES_REGISTER 0x01
#define HOURS_REGISTER 0x02
#define DAYOFWK_REGISTER 0x03
#define DAYS_REGISTER 0x04
#define MONTHS_REGISTER 0x05
#define YEARS_REGISTER 0x06
#define CONTROL_REGISTER 0x07
#define RAM_BEGIN 0x08
#define RAM_END 0x3F
void DS1307_GetTime(byte *hours, byte *minutes, byte *seconds)
// Подпрограмма вернет часы, минуты, секунды в формате BCD.
{
*hours = I2C_ReadRegister(DS1307,HOURS_REGISTER);
*minutes = I2C_ReadRegister(DS1307,MINUTES_REGISTER);
*seconds = I2C_ReadRegister(DS1307,SECONDS_REGISTER);
}
вывод на LCD-экран:
// LCD_Init инициализирует контроллер LCD
// LCD_Cmd посылает команду контроллеру
// LCD_Char посылает один символ ASCII на экран LCD
// LCD_Clear очищает экран LCD и возвращает курсор в исходную позицию
// LCD_Home возвращает курсор на экране LCD в исходную позицию
// LCD_Goto помещает курсор в позицию (x,y)
// LCD_Line помещает курсор в начало строки (x)
// LCD_Hex отображает шестнадцатиричное значение
// LCD_Integer отображает целочисленное значение
// LCD_String отображает строку
#include "settings.h"
#include "misc.h"
// Для подключения модуля LCD требуется 6 выводов портов GPIO: 2 для сигналов
// управления и 4 для передачи данных.
// Порт B используется для обмена данными с контроллером HD44780 LCD.
// Следующие определения указывают, к каким выводам портов микроконтроллера AVR
// подключен индикатор LCD:
#define LCD_RS 0 // ножка для LCD R/S (PB0)
#define LCD_E 1 // ножка для сигнала разрешения LCD
#define DAT4 2 // ножка для d4
#define DAT5 3 // ножка для d5
#define DAT6 4 // ножка для d6
#define DAT7 5 // ножка для d7
// Следующие определения задают команды для контроллера HD44780.
#define CLEARDISPLAY 0x01
#define SETCURSOR 0x80
void PulseEnableLine ()
// Генерирует импульс лог. 1 на выводе разрешения шины индикатора LCD.
{
SetBit(PORTB,LCD_E); // LCD enable переводится в лог. 1
_delay_us(40); // ожидание 40 мкс
ClearBit(PORTB,LCD_E); // LCD enable переводится в лог. 0
}
void SendNibble(byte data)
// Подпрограмма посылает ниббл через шину данных.
{
PORTB &= 0xC3; // 1100.0011 = очистка 4 линий данных
if (data & _BV(4)) SetBit(PORTB,DAT4);
if (data & _BV(5)) SetBit(PORTB,DAT5);
if (data & _BV(6)) SetBit(PORTB,DAT6);
if (data & _BV(7)) SetBit(PORTB,DAT7);
PulseEnableLine(); // этот импульс передает 4 бита в контроллер
}
void SendByte (byte data)
// Подпрограмма посылает байт через шину данных.
{
SendNibble(data); // послать старшие 4 бита
SendNibble(data<<4); // послать младшие 4 бита
ClearBit(PORTB,5); // включить светодиод LED
}
void LCD_Cmd (byte cmd)
// Подпрограмма посылает команду контроллеру LCD.
{
ClearBit(PORTB,LCD_RS); // сигнал R/S = 0, что означает данные команды
SendByte(cmd); // отправка команды
}
void LCD_Char (byte ch)
// Подпрограмма посылает символ контроллеру LCD для отображения.
{
SetBit(PORTB,LCD_RS); // сигнал R/S = 1, что означает данные символа
SendByte(ch); // отправка символа
}
void LCD_Init()
// Подпрограмма инициализирует контролер дисплея.
{
LCD_Cmd(0x33); // инициализация контроллера LCD
LCD_Cmd(0x32); // перевод контроллера в 4-битный режим шины данных
LCD_Cmd(0x28); // 2 строки, матрица символа 5x7
LCD_Cmd(0x0C); // выключить курсор (0x0E чтобы разрешить)
LCD_Cmd(0x06); // направление курсора: вправо
LCD_Cmd(0x01); // очистка дисплея
msDelay(3); // ожидание завершения инициализации LCD
}
void LCD_Clear()
// Подпрограмма очищает дисплей.
{
LCD_Cmd(CLEARDISPLAY);
msDelay(3); // ожидания завершения обработки команды LCD
}
void LCD_Home()
// Подпрограмма перемещает курсор LCD в "домашнюю" позицию
// (без очистки дисплея).
{
LCD_Cmd(SETCURSOR);
}
void LCD_Goto(byte x, byte y)
// Подпрограмма перемещает курсор LCD в указанную позицию экрана.
{
byte addr = 0; // строка 0 начинается с адреса 0x00
switch (y)
{
case 1: addr = 0x40; break; // строка 1 начинается с адреса 0x40
case 2: addr = 0x14; break;
case 3: addr = 0x54; break;
}
LCD_Cmd(SETCURSOR+addr+x); // обновить позицию курсора
}
void LCD_Line(byte row)
// Подпрограмма перемещает курсор LCD в начало указанной строки экрана.
{
LCD_Goto(0,row);
}
void LCD_String(const char *text)
// Подпрограмма отобразит строку на экране LCD в текущей позиции.
{
while (*text) // цикл, пока не появится символ /0
LCD_Char(*text++); // послать символ и обновить указатель
}
void LCD_Hex(int data)
// Подпрограмма отобразит HEX-значение данных на экране LCD
// в текущей позиции курсора.
{
char st[8] = ""; // массив для хранения результата
itoa(data,st,16); // конвертация числа в hex-строку ASCII
//LCD_Message("0x"); // если нужно, можно добавить префикс "0x"
LCD_String(st); // отобразить строку на LCD
}
void LCD_Integer(int data)
// Подпрограмма отобразит целое число на экране LCD
// в текущей позиции курсора.
{
char st[8] = ""; // массив для хранения результата
itoa(data,st,10); // преобразование числа в строку ASCII
LCD_String(st); // отобразить строку на LCD
}
и главная программа:
#include "settings.h"
#include "HD44780.h"
#include "TWI.h"
#include "DS1307.h"
#include "misc.h"
void ShowDevices()
// Сканирует шину I2C и отображает адреса всех найденных устройств.
{
LCD_Line(1); LCD_String("Found:");
byte addr = 1;
while (addr>0)
{
LCD_Char(' ');
addr = I2C_FindDevice(addr);
if (addr>0) LCD_Hex(addr++);
}
}
void LCD_TwoDigits(byte data)
// Вспомогательная функция для WriteDate().
// На входе получает 2 цифры в формате BCD.
// Выводит эти цифры на дисплей LCD в текущую позицию курсора.
{
byte temp = data>>4;
LCD_Char(temp+'0');
data &= 0x0F;
LCD_Char(data+'0');
}
void WriteDate()
{
byte months, days, years;
DS1307_GetDate(&months,&days,&years);
LCD_TwoDigits(months);
LCD_Char('/');
LCD_TwoDigits(days);
LCD_Char('/');
LCD_TwoDigits(years);
}
void WriteTime()
{
byte hours, minutes, seconds;
DS1307_GetTime(&hours,&minutes,&seconds);
LCD_TwoDigits(hours);
LCD_Char(':');
LCD_TwoDigits(minutes);
LCD_Char(':');
LCD_TwoDigits(seconds);
}
void LCD_TimeDate()
{
LCD_Line(0); WriteTime();
LCD_Line(1); WriteDate();
}
// ---------------------------------------------------------------------------
// Главный цикл программы.
void MainLoop()
{
while(1)
{
LCD_TimeDate(); // отображение на LCD времени и даты
msDelay(1000); // между обновлениями ожидание 1 секунда
}
}
// ---------------------------------------------------------------------------
// Основная программа: тело функции main.
int main(void)
{
InitAVR(); // настройка портов GPIO микроконтроллера
LCD_Init(); // инициализация контроллера HD44780 дисплея LCD
I2C_Init(); // настройка шины I2C (с установкой её тактовой частоты)
LCD_String("Ready.");
ShowDevices(); // показать, что шина I2C работает нормально
msDelay(4000);
LCD_Clear();
MainLoop(); // отображает время
}
LCD-экран работает с указателями "DS1307_GetTime(&hours,&minutes,&seconds);", которые я ещё не изучил (не добрался ещё до этого типа экрана, а в моргании диодом или АПЦ это не используется), поэтому я пытаюсь вывести данные с DS1307 на 7LED-дисплей. Не выходит. Две недели уже мучаюсь.