Меню сайта
Администрация
579-010-666
Или воспользуйтесь формой обратной связи.
Разделы
Автолюбителям [13]
Таймер NE555 [11]
Конструктор схем [11]
Измерительная аппаратура [5]
Осциллографы [2]
На микрухах [10]
Роботы [0]
Световые эффекты [1]
Термостат [0]
Обучение PIC с нуля [17]
Чат
500
Наш опрос
Оцените мой сайт

Результат опроса Результаты Все опросы нашего сайта Архив опросов

Всего голосовало: 148
Статистика



Онлайн всего: 1
Гостей: 1
Пользователей: 0
Главная » Статьи » Обучение PIC с нуля

15 Часы реального времени DS1307
Мне прилетели из Китая микросхемы и я начал над ними издеваться в целях исследования перед внедрением в будущие часы. Предупреждаю — в данной статье я исследовал только работу со временем, дата и прочие приблуды этих часов меня мало интересовали и я не терял на это время.

Задача: Запись значения времени/чтение значения времени и вывод через USART из микросхемы DS1307.

Исходный материал: PIC16f628a, DS1307, MAX232 level converter, devboard, proteus.

Микросхема DS1307 — модуль часов реального времени, которым можно управлять по шине данных I2C. Можно конечно было реализовать RTC на базе лишь одного микроконтроллера, но проще подцепить DS1307 + часовой кварц и не запариваться. Начинаем как обычно с вкуривания даташита. Выдергиваем оттуда схему применения и собираем ее:

Выцепляем из даташита организацию памяти микросхемы:

Как я уже отметил ранее, меня интересует лишь время, поэтому будем юзать только адреса 00h, 01h, 02h. Данные в регистрах хранятся в формате BCD.

Вкратце о BCD: смешанный формат хранения данных. Число разбивается на две части, в младшей части байта — обычный бинарный формат, в старшей — фактически число в бинарном формате, смещенное влево на 4 бита и умноженное на 10 . Пример — 0b00110101 => 0b0011 = 3*10 = 30, 0b0101 = 5 — число = 35.

Таким образом, нам нужно проделать некоторые манипуляции чтобы записать нормально число в регистр. Я создал две функции: одна конвертирует десятичное число в BCD, другая конвертирует BCD в десятичный формат.

Конвертация из BCD в десятичную форму:

unsigned char BCDconv (unsigned char source) {

unsigned char temp_min=0; //переменная для единиц
unsigned char temp_maj=0; //переменная для десятков
temp_min = source&15; //помещаем младшую часть байта в переменную (15 = 0b00001111)
temp_maj = source >> 4; //Смещаем старшую часть вправо на 4 бита
temp_maj *= 10;
return temp_maj+temp_min; //возвращаем десятичное значение
}


Конвертация в BCD:

unsigned char DCBconv (unsigned char source) {

unsigned char temp_min=0;
unsigned char temp_maj=0;
temp_maj = source/10 ;
temp_min = source - temp_maj*10;
temp_maj <<= 4;
return temp_maj+temp_min;
}


Дальше нам надо определиться с процедурами записи и чтения в часы, лезем в даташит, там красивая картинка:

На картинке показана процедура записи, с этим вопросов не возникает, создаем функции записи часов, минут, секунд.

void SetHour(unsigned char hours) { //записываем значение в часы

i2c_start();
i2c_tx(0b11010000);
i2c_tx(0x02); //адрес часов
i2c_tx(DCBconv(hours)); //запихиваем нужное значение
i2c_stop();
}

void SetMin(unsigned char minutes) { //записываем значение в минуты

i2c_start();
i2c_tx(0b11010000);
i2c_tx(0x01); //адрес минут
i2c_tx(DCBconv(minutes)); //запихиваем нужное значение
i2c_stop();
}

void SetSeconds(unsigned char seconds) { //записываем значение в секунды
i2c_start();
i2c_tx(0b11010000);
i2c_tx(0x00); //адрес секунд
i2c_tx(DCBconv(seconds)); //впихиваем нужное значение
i2c_stop();

}



C чтением есть один небольшой нюанс, на который я вначале не обратил внимания:

Из даташита: The DS1307 must receive a Not Acknowledge to end a read.

А я как образцовый slave отсылал постоянно acknowledge бит . Таким образом:

Потом я это уже и на картинке заметил, так что читаем даташит внимательно, если не хотим потерять много времени впустую.

unsigned char ReadHour() {

unsigned char temp = 0;
i2c_start();
i2c_tx(0b11010000);
i2c_tx(0x02);
i2c_start();
i2c_tx(0b11010001);
temp = i2c_rx(0); //читаем значение часов (0) означает, что мы не шлем acknowledge
i2c_stop();

return BCDconv(temp);

}

unsigned char ReadMin() {

unsigned char temp = 0;
i2c_start();
i2c_tx(0b11010000);
i2c_tx(0x01);
i2c_start();
i2c_tx(0b11010001);
temp = i2c_rx(0); //читаем значение минут (0) означает, что мы не шлем acknowledge
i2c_stop();

return BCDconv(temp);

}

unsigned char ReadSeconds() {

unsigned char temp = 0;
i2c_start();
i2c_tx(0b11010000);
i2c_tx(0x00);
i2c_start();
i2c_tx(0b11010001);
temp = i2c_rx(0); //читаем значение часов (0) означает, что мы не шлем acknowledge

i2c_stop();

return BCDconv(temp);

}



Теперь сварганим процедуры установки и отображения времени по USART.

Отображение времени:

void ShowTime() {

printf("\fTime - %d :", ReadHour());
printf(" %d :", ReadMin());
printf(" %d ", ReadSeconds());
printf("\r\n*********************");
printf("\r\n Menu");
printf("\r\n 1 - Reload time");
printf("\r\n 2 - Setup time");

}



Функция отображает такую вот менюшку:

По клавише 1 — данные в терминале перезагружаются, я специально не стал делать постоянное отображение времени, чтобы не поймать левых косяков. По клавише 2 запускается процедура установки времени:

void SetupTime() {

unsigned char state = 1;
unsigned char temp_min = 0;
unsigned char temp_maj = 0;
unsigned char temp = 0;

while(state){ //Установка часов
printf("\fEnter hours - ");
temp_maj = getch();
printf(" %c", temp_maj);
temp_min = getch();
printf("%c", temp_min);
temp = getch();
if (temp == 13) {
temp_maj -= 48;
temp_min -= 48;
temp = temp_maj*10 + temp_min;
if (temp < 24) {
SetHour(temp);
state = 0;
}
}
}

state = 1;
while(state){ //Установка минут
printf("\fEnter minutes - ");
temp_maj = getch();
printf(" %c", temp_maj);
temp_min = getch();
printf("%c", temp_min);
temp = getch();
if (temp == 13) {
temp_maj -= 48;
temp_min -= 48;
temp = temp_maj*10 + temp_min;
if (temp < 61) {
SetMin(temp);
state = 0;
}
}
}

state = 1;
while(state){ //Установка секунд
printf("\fEnter seconds - ");
temp_maj = getch();
printf(" %c", temp_maj);
temp_min = getch();
printf("%c", temp_min);
temp = getch();
if (temp == 13) {
temp_maj -= 48;
temp_min -= 48;
temp = temp_maj*10 + temp_min;
if (temp < 61) {
SetSeconds(temp);
state = 0;
}
}
}

ShowTime();
}


Ну и кратенькое содержание main.c :

void main(void){

unsigned char input;
CMCON = 0x07;
INTCON=0; // вырубаем прерывания
init_comms(); // инициализация USART
SetHour(15); // записываем произвольное значение времени
SetMin(38);
SetSeconds(23);
ShowTime(); //отображаем менюшку

for(;;){
input = getch(); //опрос клавиши
switch (input) {
case 49 : ShowTime(); //если 1 то обновляем экран
break;
case 50 : SetupTime(); //если 2 то устанавливаем время
break;
}
}
}



Вот собственно и все, этого набора функций достаточно для работы, видео работы реального устройства:

Скачать архив с проектом





Источник: http://diymicro.ru/?p=128
Категория: Обучение PIC с нуля | Добавил: аля))) (26.06.2012)
Просмотров: 2850 | Теги: RTC, I2C, USART., PIC микроконтроллеры, DS1307, pic | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Профиль
Суббота
04.05.2024
17:20

Новости сайта
Добавленно новых материалов:
****************************************
1.06.2012
Просьба...
Уважаемые пользователи!
Выделите пожалуйста 1 минуту вашего времени и кликните пару ссылок от рекламы на Google. Тем самым вы потдержите проект.
Спасибо!
Реклама