; Продцедуры для работы с часами реального времени DS1307
; Автор - Lpa
; http://radioelektr.ru/

.def temp=r16
.def temp1=r17
.def temp2=r18
.def temp3=r19

;================================================
.dseg
Hours:        .byte 1; 1 байт под часы
Minutes:      .byte 1; 1 байт под минуты

Days:         .byte 1; 1 байт под дни
Month:        .byte 1; 1 байт под месяц

Weekday:      .byte 1; 1 байт для дня недели
Year:         .byte 2; Год в 1 байт не помещается, поэтому 2



;=========================================================================
.cseg
RTC_Start:
; Запускает ход часов,
; Регистры не портит.

push temp; Сохраняем temp

rcall IIC_Start; Отправляем стартовую посылку

ldi temp,0b11010000
rcall IIC_Send; Отправляем адрес часов с битом записи

ldi temp,0x00; Отправляем адрес ячейки памяти - 0x00
rcall IIC_Send

rcall IIC_Start; Повторный старт

ldi temp,0b11010001
rcall IIC_Send; Адрес микрухи, но уже с битом чтения

clt
rcall IIC_Recieve; Принимаем байт. Первый и последний

rcall IIC_Stop; Стоп

;------------------------

cbr temp,0b10000000; Обнуляем седьмой бит. Остальные не трогаем

push temp; Сохраняем результат в стек

;------------------------

rcall IIC_Start; Отправляем стартовую посылку

ldi temp,0b11010000
rcall IIC_Send;  Отправляем адрес часов с битом записи

ldi temp,0x00;   Отправляем адрес ячейки памяти - 0x00
rcall IIC_Send

pop temp; Достаём значение, которое нужно записать

rcall IIC_Send; Записываем

rcall IIC_Stop; Всё, хватит!!! ;-)

pop temp; Восстанавливаем temp

ret; Выход из подпрограммы


;=========================================================================
RTC_Stop:
;Остановка часов.
;Регистры также остаются целыми

push temp; Сохраняем temp


rcall IIC_Start; Отправляем стартовую посылку

ldi temp,0b11010000
rcall IIC_Send; Отправляем адрес часов с битом записи

ldi temp,0x00; Отправляем адрес ячейки памяти - 0x00
rcall IIC_Send

rcall IIC_Start; Повторный старт

ldi temp,0b11010001
rcall IIC_Send; Адрес микрухи, но уже с битом чтения

clt
rcall IIC_Recieve; Принимаем байт. Первый и последний

rcall IIC_Stop; Стоп

;------------------------------

sbr temp,0b10000000; Устанавливаем седьмой бит. Остальные не трогаем

push temp; Сохраняем результат в стек

;------------------------------

rcall IIC_Start; Отправляем стартовую посылку

ldi temp,0b11010000
rcall IIC_Send; Отправляем адрес часов с битом записи

ldi temp,0x00; Отправляем адрес ячейки памяти - 0x00
rcall IIC_Send

pop temp; Достаём значение, которое нужно записать

rcall IIC_Send; Записываем

rcall IIC_Stop; Стоп

pop temp; Восстанавливаем temp

ret; Выход из подпрограммы


;=========================================================================
RTC_Get_time:
; Подпрограмма, которая читает время из часов.
;
;                Результат:
;
;         1)Переменная hours - часы в десятичке
;         2)Переменная minutes - минуты в десятичке
;

push temp; Сохраняем temp

rcall IIC_Start; Старт

ldi temp,0b11010000
rcall IIC_Send; Отправляем адрес часов с битом записи

ldi temp,0x01; Адрес ячейки памяти, там находятся минуты
rcall IIC_Send

rcall IIC_Start; Повстарт

ldi temp,0b11010001
rcall IIC_Send; Адрес микрухи, но уже с битом чтения

set
rcall IIC_Recieve; Принимаем первый байт
rcall bcd2dec;     Преобразовываем в десятичное
sts minutes,temp;  Запихиваем в переменную

clt
rcall IIC_Recieve; Аналогично с последним байтом
cbr temp,0b11000000
rcall bcd2dec
sts hours,temp

rcall IIC_Stop; Стоп

pop temp; Восстанавливаем temp

ret; Я думаю не надо каждый раз обЪяснять, что это... Return

;=========================================================================

RTC_Get_date:
; Подпрограмма, которая читает дату из часов.
;
;                Результат:
;
;         1)Переменная days - число в десятичке
;         2)Переменная month - месяц в десятичке


push temp; Сохраняем temp

rcall IIC_Start; Старт

ldi temp,0b11010000
rcall IIC_Send; Отправляем адрес часов с битом записи

ldi temp,0x03; Адрес ячейки памяти, там находится число
rcall IIC_Send

rcall IIC_Start; Повстарт

ldi temp,0b11010001
rcall IIC_Send; Адрес микрухи, но уже с битом чтения

set
rcall IIC_Recieve; Принимаем первый байт
rcall bcd2dec;     Преобразовываем в десятичное
sts weekday,temp;     Запихиваем в переменную

set
rcall IIC_Recieve; Аналогично
rcall bcd2dec
sts days,temp

set
rcall IIC_Recieve
rcall bcd2dec
sts month,temp


clt
rcall IIC_Recieve; Аналогично с последним байтом
rcall bcd2dec
sts year+1,temp

rcall IIC_Stop; Стоп

pop temp; Восстанавливаем temp

ret

;=========================================================================

RTC_Set_Time:
; Подпрограмма для установки времени
;
;                Вход:
;
;         1)Переменная hours - часы в десятичке
;         2)Переменная minutes - минуты в десятичке


rcall RTC_Stop; Останавливаем часы

rcall IIC_Start; Старт

ldi temp,0b11010000
rcall IIC_Send; Адрес микросхемы с битом записи

ldi temp,0x01; Адрес ячейки памяти
rcall IIC_Send

lds temp,minutes;Спихиваем минуты в temp
rcall Dec2bcd;   Преобразовываем в десятичное
rcall IIC_Send;  Записываем

lds temp,hours; Аналогично
rcall Dec2bcd
rcall IIC_Send

rcall IIC_Stop; Стоп

rcall RTC_Start; Запускаем часы

ret

;=========================================================================

RTC_Set_Date:
; Подпрограмма для установки даты
;
;                Вход:
;
;         1)Переменная days - число в десятичке
;         2)Переменная month - месяц в десятичке


rcall IIC_Start; Старт

ldi temp,0b11010000
rcall IIC_Send; Адрес микросхемы с битом записи

ldi temp,0x03; Адрес ячейки памяти
rcall IIC_Send

lds temp,weekday; Спихиваем день в temp
rcall Dec2bcd; Преобразовываем в десятичное
rcall IIC_Send;Записываем

lds temp,days; Аналогично
rcall Dec2bcd
rcall IIC_Send

lds temp,month; Аналогично
rcall Dec2bcd
rcall IIC_Send

lds temp,year+1; Аналогично
rcall Dec2bcd
rcall IIC_Send

rcall IIC_Stop; Стоп



ret

;=========================================================================
Dec2bcd: 
; Подпрограмма для перевода десятичного числа в двоично-десятичное
; Исходное значение загружается в Temp и оттдуда же забирается 
; двоично-десятичное число

push temp1
push temp2
push temp3

	cpi temp,10
	BRLO _1exit
	push temp
	clr temp2      
	ldi temp1,10   
	cikl2: sub temp,temp1 
	inc temp2
	cpi temp,10    
	BRGE cikl2

	clr temp3
	Clr temp 
	cikl3: 
	add temp3,temp1 
	inc temp
	cp temp,temp2
	brne cikl3 
	pop temp
	sub temp,temp3 
	swap temp2
	add temp,temp2
	_1exit:


pop temp3
pop temp2
pop temp1

ret


;========================================================================
bcd2dec: 

push temp1
push temp2



	push temp
	swap temp
	clr temp2
	cbr temp,0b11110000
	mov temp2,temp
	Clr temp1 
	Mult: add temp,temp2
	inc temp1
	cpi temp1,9
	brne Mult
	mov temp1,temp
	pop temp 
	cbr temp,0b11110000
	add temp,temp1

pop temp2
pop temp1


ret





