Часы реального времени PCF8583

Делал я тут один коммерческий девайсик и требовалось там вести лог событий. А конкретно фиксировать управляющие команды пользователя, а также время и дату, чтобы если оператор где накосячит его можно было взять за задницу. Вот такой вот электронный цербер.
Задача несложная, но для ее реализации нужен был способ замерять время, причем делать это независимо, с сохранением результатов даже если питалово вырубили. Данные можно хранить во флеше, а что делать с временем?

Я решил поставить микросхему часов реального времени PCF8583 от NXP. Стоит она рублей 80, дороговато, конечно. Можно было дешевле выкрутиться, на одном лишь асинхронном таймере AVR, но при цене девайса в жутки тыщи на таких спичках не экономят, а тут готовое промышленное решение :) Сам таймер PCF8583 представляет собой восьминогую тараканину, которой из обвяза нужен только кварц на 32768Гц, батарейка резервного питания на 3.3 вольта и собственно все.
Общается она с микроконтроллером по протоколу I2C который я недавно разобрал.

Заметки между делом, при желании можно пропустить
Доточить библиотеку I2C (сполной поддержкой конечного автомата TWI на прерываниях) под RTOS все пока времени не хватает, поэтому я по быстрому, тупо в лоб, сделал работу с TWI на флагах ожидания. Метод, ИМХО, дебильный так как жрет дофига процессорного времени, но зато рабочий, простой и мозг никому не взорвет :) Как минимум этот метод используется в avrlibc библиотеках под WinAVR и, вроде бы, в CVAVR.

Схема включения проста — связать с контроллером по шине I2C, не забыв подтянуть шину к +5 через резисторы в 10к. Если этого не сделать, то слабая 100к подтяжка портов не будет справляться и фронты сигналов будут завалены, что нехорошим образом сказывается на надежности передачи. Да и стандарт IIC этого требует.

Также потребуются два диода. Диод VD1 не дает заряжать резервную батарейку напряжением питания (она все же не аккумулятор, а батарейка). Второй диод не дает батарейке питать всю схему когда из нее вынимают родной источник питания. Часы же в это время кормятся от таблетки. Причем напряжения питания девайса должно быть немного выше напряжения питания батарейки, где то на 0.7 вольт, чтобы не допускать кормление часов от батареи в нормальном, не аварийном, режиме. Лучше взять диоды Шоттки, тогда падение напряжения на них будет меньше и превышение питающего надо будет тоже меньше. Впрочем, на батарейке часы проживут несколько лет, так что это не очень критично. Конденсатор является подстроечным. С его помощью можно править ход часов немножко. Я его ставить не стал.

Теперь немного по разводке. Поскольку напряжение питания мало, потребление тоже крошечное, то и генератор на кварце работает на мизерной амплитуде, что его еле еле осциллографом прощупываешь. Отсюда повышенная чувствительность к наводкам. Так что при разводке часовой кварц надо прифигачить как можно ближе к ногам микросхемы часов, корпус кварца окружить земляным полигоном, а лучше вообще взять и припаять к земле. Благо часовой кварц снаружи луженый и паяется отлично. По крайней мере мой. Если не сделать — будет работать очень нестабильно. Я на этом уже прокололся, на моей монтажке которую ты видишь на фото то работало то не работало. Так что вот так вот делать не следует! Часовой кварц надо припаивать корпусом к земле!

Код тут несложен. Во главе угла стоит библиотека iic_dumb.asm
Вот ее содержимое:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
;--------------------------------------------------------
; I2C Code
;--------------------------------------------------------
; Работа с IIC передатчиком. Предупреждаю -- это быдлокод!
; Несмотря на то, что так делают почти все :) 
; Но это медленно и тормозно, особенно в свете использования
; RTOS. Почему? Да потому что использует глухое
; ожидание флага готовности IIC. Вместо того, чтобы отдать 
; управление диспетчеру задач. Также нет обработоки ошибок
; и какой либо оценки прошла команда или нет. Просто пример!
 
; Даем старт на линию I2C
IIC_START:	OUTI	TWCR,1<<TWINT|1<<TWSTA|1<<TWEN|0<<TWIE
 
IIC_S:		IN	OSRG,TWCR
		ANDI	OSRG,1<<TWINT			
		BREQ	IIC_S		; Ждем пока передатчик IIC выполнит старт
		RET
 
;-----------------------------------------------------------------------------
;Посылаем байт по IIC 
IIC_BYTE:  	OUT	TWDR,OSRG
		OUTI	TWCR,1<<TWINT|1<<TWEN|0<<TWIE
 
 
IIC_B:		IN	OSRG,TWCR
		ANDI	OSRG,1<<TWINT	; Ждем пока передатчик пошлет байт			
		BREQ	IIC_B
		RET
 
;-----------------------------------------------------------------------------
; Принять байт. 
IIC_RCV:	OUTI	TWCR,1<<TWINT|1<<TWEN|1<<TWEA|0<<TWIE
IIC_R:		IN	OSRG,TWCR
		ANDI	OSRG,1<<TWINT			
		BREQ	IIC_R		; Ждем пока байт будет принят
		RET
 
;-----------------------------------------------------------------------------
; Принять последний байт. Помните я писал о разнице между просто байтом и последним
; байтом? В последнем байте не генерируется ACK!!!
IIC_RCV2:	OUTI	TWCR,1<<TWINT|1<<TWEN|0<<TWEA|0<<TWIE
IIC_R2:		IN	OSRG,TWCR
		ANDI	OSRG,1<<TWINT	; Ждем пока байт будет принят		
		BREQ	IIC_R2
		RET
 
;-----------------------------------------------------------------------------
; Сгенерировать STOP
IIC_STOP:	OUTI	TWCR,1<<TWINT|1<<TWSTO|1<<TWEN|0<<TWIE
 
IIC_ST:		IN	OSRG,TWCR
		ANDI	OSRG,1<<TWSTO			
		BREQ	IIC_ST		; Ждем пока не будет готов стоп.
		RET

Сами процедуры просты:

  • IIS_START — устраивает на шине Start состояние
  • IIC_BYTE — посылает байт, просто байт. Не важно что это — адрес, данные…
  • IIC_RCV — команда противополжная предыдущей — принимает байт в конце дает ACK
  • IIC_RCV2 — тоже принимает байт, но в конце дает NACK, используется для приема последнего байта. Чтобы дать понять Slave устройству что мы в его услугах больше не нуждаемся.

Параметры, такие как адрес/данные или возвращаемое значение передаются через OSRG. OSRG это любой регистр страшей группы. Сам термин взят из моей RTOS, там это регистр R17 такой общесистемный Temp.

Общение с RTC происходит как с обычной EEPROM типа АТ24Схх, только вместо сохраненных байтов данных мы принимаем значения времени. Впрочем, там, после регистров с временем еще есть 240 байт памяти которые мы можем юзать как нам угодно. Мелочь, а приятно.

Вот, например, чтение:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
RTC_READ:	RCALL	IIC_START		; Отослали старт
 
		LDI	OSRG,0b10100000		; Отослали адрес часов на запись
		RCALL	IIC_BYTE
 
		LDI	OSRG,RTCAddr		; Отослали адрес ячейки откуда будем читать
		RCALL	IIC_BYTE
 
		RCALL	IIC_START		; Повторный старт
 
		LDI	OSRG,0b10100001	; Адрес часов снова, но уже на чтение
		RCALL	IIC_BYTE
 
		RCALL	IIC_RCV			; Считали первый байт - секунды
		IN	OSRG,TWDR		; Забрали из регистра TWIDR 
		STS	Sec_o,OSRG		; Сохранили в память
 
		RCALL	IIC_RCV			; Второй байт - Минуты, с ним также
		IN	OSRG,TWDR
		STS	Min_o,OSRG
 
		RCALL	IIC_RCV			; Третий байт - Часы
		IN	OSRG,TWDR
		STS	Hour_o,OSRG
 
		RCALL	IIC_RCV			; Четвертый - число
		LDS	OSRG,TWDR
		STS	Date_o,OSRG
 
		RCALL	IIC_RCV2		; Ну и напоследок месяц. Внимание! 
		IN	OSRG,TWDR		; тут процедура послденго байта! RCV2!!!
		STS	Mth_o,OSRG
 
IIC_RErr:	RCALL	IIC_STOP		; Дали STOP и освободили линию.
 
		RET				; Вышли из задачи

Поясню пару моментов:
0b10100000 это адрес устройства на шине IIC с битом направления. Все часы марки PCF8583 откликаются на адрес 101000yх, впрочем, этот адрес стандартен и для большинства других RTC. бит y определяется адресным выводом А0, у меня он посажен на землю. Так что y=0 То что последний бит = 0 означает что мы записываем в часы байт. Этот байт идет следом и равен он RTCAddr=2. Почему два?

Да все просто. В нулевой ячейке памяти PCF лежит регистр конфига часов, нам он не интересен. В первой ячейке лежат сотые доли секунды. Нам они тоже не интересны, а вот начиня с 2 ячейки идут секунды, минуты, часы, число, месяц, год…

Последовательность чтения для IIC обычно такая:

  • Старт
  • Адрес дейвайса[write]
  • Адрес ячейки откуда будем читать
  • Повторный Старт,
  • Адрес девайса [read],
  • Байт из адресованой ячейки,
  • Байт из адресованой ячейки+1,
  • Байт из адресованой ячейки+2
  • ….
  • PROFIT Cтоп


Запись идет проще:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
RTC_WRITE:	RCALL	IIC_START		; Старт 
 
		LDI	OSRG,0b10100000	; Загрузили Адрес часов на запись
 
		RCALL	IIC_BYTE		; Отослали адрес часов на запись
 
		LDI	OSRG,RTCAddr		; Загрузили адрес ячейки памяти часов
		RCALL	IIC_BYTE		; Отослали адрес ячейки
 
		LDS	OSRG,Sec_i	;Sec	; Загрузили секунды
		RCALL	IIC_Byte		; Отослали секунды
 
		LDS	OSRG,Min_i	;Min	; Загрузили минуты
		RCALL	IIC_Byte		; Отослали минуты
 
		LDS	OSRG,Hour_i	;Hr	; Загрузили часы
		RCALL	IIC_Byte		; Отослали часы
 
		LDS	OSRG,Date_i	;Date	; Загрузили число
		RCALL	IIC_Byte		; Отослали число
 
		LDS	OSRG,Mth_i	;Mth	; Загрузили Месяц
		RCALL	IIC_Byte		; Отослали месяц
 
IIC_WErr:	RCALL	IIC_STOP		; Стоп
 
		RET				; Выход из задачи

  • Старт
  • Адрес девайса [write]
  • Адрес ячейки куда будем писать
  • Данные раз
  • Данные два
  • Данные три
  • …..
  • Стоп
Впрочем, я повторяюсь. Все это уже было описано в статье про IIC на примере этих же часов :)

В общем, захочешь юзать мою черновую либу, то собираешь себе нужную процедуру чтения-записи как из кусочков. Но учти, что обработки ошибок там нет (добавь если хочешь), так что на шине может и никого и не быть, а микроконтроллер упорно отошлет адрес, данные, а может и считать что нибудь попытается. И ведь считает мусор какой нибудь! :) Проверку сделать не сложно, надо всего лишь после каждой процедуры опросить регистр TWISR на предмет флагов — есть ли там ожидаемое нами состояние, например наличие бита ACK. Если что то не то — косяк.

Для работы с девайсом я сделал тестовую программу. Точнее выкинул из коммерческой разработки весь стафф, оставив лишь работу с часами, да прикрутил туда интерфейс терминальный.

Итак, общение идет через обычный RS232 интерфейс aka COM порт.
Команды следующие:

  • «G» — Get Time выдает текущее время из недр часов.
  • «L» — Load Time приготовится к загрузке новых данных времени и даты. После этой команды микроконтроллер все байты начинает воспринимать как значения. Данные шлются в двоично десятичном виде. В порядке от младшего к старшему, начиная с минут. 5 байт и 6й байт завершающий. Т.е. минуты, секунды, часы, число, месяц, любой байт (он закроет ввод данных) Данные пока записываются в память МК. Чтобы можно было неспеша ввести данные.
  • «S» — Set Timeперенести данные из памяти МК в память RTC. Вот тут то и происходит запись.
Пример:
Сейчас на часах 00:10 25/06, надо настроить часы. Настраивать будем на 00:13, как раз трех минут хватит, чтобы неспеша ввести данные
ЗапросОтвет МКПримечание
G00:24:33 04/06Запрашиваем время что сейчас. Явно лажа
LНет ответаПереходим в режим программирования
0х130х13Минуты
0х000х00Часы
0х250х25Число
0х060х06Месяц
0х000х00Любой байт
Ждем когда настанет 0:13
S0х13,0х00,0х25,0х06,0х00Записываем!!!
G00:23:06 25/06Проверяем… ОК!

Файлы к статье:

Другие плюшки:
Эти часы также могут работать в режиме счетчика.
То есть считать входящие события и генерировать логический 0 на выходе INT при переполнении. Для этого надо всего лишь на вход OSC1 подать считаемые импульсы. А еще там есть будильник. То есть можно запрограммировать его и в назначенное время на выходе INT будет ноль. Программирование ведется записью данных в ячейки, адресация подробно указана в даташите. Можно менять формат вывода с 24 часового на 12 часовой. В общем, навротов там порядочно.

Перевод чисел из BCD в ASCII:
Тут все просто. Что такое BCD? Это Двоично десятичное число. То есть мы десятичное числое записываем в двоичном виде как есть. Выглядит это так: 0х01,0х02..0х09,0х10.. То есть, видишь, после 0х09 идет не 0х0А, а 0х10. Таким образом, в одном байте может влезть не больше чем 0х99. Но зато такие числа удобно перегонять в ASCII. Например, код ‘0’ в ASCII это 0х30, код ‘1’ = 0x31, ‘2’ = 0x32 и так далее, закономерность видишь? ;) Так что чтобы получить цифру в ASCII надо к 0х30 прибавить ее BCD разряд. BCD обычно идет упакованым, то есть в одно байте два числа, старший и младший разряд. Так что чтобы вывести двузначное число надо его по маскам 0x0F и 0xF0 разделить на младшую и старшие тетрады, каждую из них сложить с кодом 0х30 и последовательно отрыгнуть в USART или куда нам там надо. Что я, собственно, и сделал в процедуре BCD2ASCII.

Внезапно!
Тут, пока возился со статьей, обнаружил косяк. Разные микросхемы работают по разному. Например тот экземпляр PCF, что ушел к заказчику — работает отлично.
Тот что стоит в моей макетке странно глючит — на том же самом коде выдает все нормально, но вместо месяца всегда число 04, мало того, при сбросе оно должно быть 00, а оно все равно 04. Ничего понять не могу. И нельзя туда ничего ни записать ни считать ничего отличного от 04 (реально всегда выдает 0х84, но от этого не легче) :/ Думал может в коде где косяк возник, на фоне выкидывания барахла… Загрузил всю эту бодягу в ISIS Proteus, благо там эта микросхема часов есть. Там всегда читается ноль вроде бы верно, но он не устанавливается в нужное число, как я ни пытался. А в девайсе заказчика все Ок. Либо у меня где то лыжи не едут, либо тут дело не чисто. В общем, фигня какая то. Причем ладно бы первый или последний байт посылки был косячным, а то прям с середины. И три разных результата. Я в панике :)

95 thoughts on “Часы реального времени PCF8583”

  1. 1. «напряжения питания девайса должно быть немного выше напряжения питания батарейки, где то на 0.7 вольт, чтобы не допускать кормление часов от батареи в нормальном, не аварийном, режиме.»
    Оба источника подключены к нагрузке через одинаковые диоды (Шотки надеюсь?) Почему же требуется именно 0.7В превышения? ;)
    2. Кто ж так кварцы, кроме китайцев, ставит? Да и китайцы уже научились класть их на плату и крепить перемычкой внахлест/пайкой.

    1. 1. Для общей надежности. =) Диоды шоттки стоят ессесно.

      2. Это моя отладочная платка, собственно с ней я обнаружил приколы с кварцем. Так то да, запаять бы не помешало.

  2. А почему именно эта микросхема? Есть отличия от DS1307 скажем? Просто везде где видел применения таких часов именно вышеупомянутая микруха стоит. Сам еще не юзал, потому спрашиваю :)

  3. Кстати, в догонку, раньше занимался гитарными примочками, так вот — там распространена такая схема включения б/п и батарейки: http://s60.radikal.ru/i168/0906/f4/88a1f16fc2fa.jpg На схеме обозначены панелька под батарейку и гнездо под б/п (2.1мм power plug jack). При включении штекера в гнездо прижимная платстина отжимается, контакт разрывается, и питание идет только от б/п. Когда штекер б/п не вставлен в гнездо, контакт нормально замкнут и питание осуществляется от батарейки. ИМХО так дешевле будет — экономия двух диодов :-D Думаю вы и сами знаете такую схему, наверное она вам тут чем-то неподошла. Просто в тему написал

    1. Во время переключения контактов цепь питания разрывается, и если не повесить на микросхему питания большой конденсатор, времени будет хана. Электроника с механикой не дружат…

      1. При токе потребления этой микросхемы (Imax=1.5mA) падение на диоде Шотки будет почти ровно 0.2В. При питании от батареи — ток еще ниже, падение напряжения — порядка 0.1В.

  4. ой как замечательно!!! у нее есть десятые и сотые секунды???
    если это так? и я правильно понял рисунок из даташита — то это основное отличие от ds1307 — которая только секунды выдавать может….

  5. Попользовал недавно DS1307, за неименеем опыта наступил на все грабли, которые только можно: начиная от того, что резервное питание вешал на Vcc (из-за отсутствия положительной разницы между Vcc часов и резервным питанием, часы думали что живут на батарейке), заканчивая тем, что остатки ЛТИ120 добавили 3-6 секунд отставания в час.
    Потом заработало как надо, но вот с точностью кварца все же косяки. Следующий раз буду пользовать часы с регистром подстройки

    1. А не проще кварц подстроить или подобрать? Делов то — небольшой конденсатор параллельно или последовательно… Нормальные люди подстроечник сразу ставят, если точность нужна.

    2. Надо брать не китайский ноунэйм с недокументированными параметрами, а нормальный кварц с нагрузочной ёмкостью строго 12.5пФ — например, «KX-38 32.768kHz 12.5pF» от GEYER, стоит 7 рублей.
      И будет очень точный ход у часов.

      1. У них там какой то прикол со временем и напряжениями.

        Если напряжение ниже батарейного или какого то там порога то они затыкаются и для повторного запуска их надо пнуть вручную записав в регистр единичку. Как то так.

        Ну или у тебя часовой кварц не запустился, может от того что флюс не смыл.

      2. DS1337 такая же фигня, 2 дня боролся ))
        в общем, между x1 и x2 должно быть оч большое сопротивление.
        Если маленькое — смерть микрухе. Я одну так убил, показывает 0 ом сопротивление между x1 и х2.
        Убил следующим образом — забыл отключить USB от ноутбука, питание на pinboard2 и перепаивал кварц, пробило в руку от паяльника, микруха данные дает, но не тикает. Мож как 14 байтовую i2c озу использовать? :)
        убил — на второй день.
        Первый день запустилась только от кварца, который шел вместе с Pinboard2.
        Оказалось всё проще. Корпус SOIC, 8 выводом. Отпаял, сцарапал канифоль, перепаял, прогрел всё что шло по схеме питания и кварца.
        Теперь тикает от любого и от китайского и от не китайского.
        Так же был выявлен глюк, когда отказывалась тикать при наличии батарейки — пропайка схемы питания исправила ситуацию.
        Ну и еще в App нотах нашел, что при первом запуске микросхемы ей нужно поставить время.

  6. Так, для информации:

    У микрухи DS1307 следующие преимущества перед PCF:
    — на порядок меньшее потребление от батарейки;
    — встроенная схема переключения на резервное питание.

    Правда, у обеих микросхем сурьезный недостаток: они не вычисляют день недели! Регистр Weekday есть, но инициализировать его надо «вручную», вычисляя в программе по дате. Что мешало разработчикам этот простейший алгоритм засунуть внутрь чипа — неясно…

    1. Засунуть мешало 2 знака на год. Часам абсолютно всё равно, 2009 или 1909 год на дворе, а вот день недели разный. Тем более, что если все равно устанавливать часы, почему бы не поставить заодно и день недели

      Кстати, очень часто сталкивался с мнением что DS1307 лучше и не использовать совсем, т.к. барахло.

      З.Ы,
      А еще лучше пользовать часы от эпсон. Там есть модельки со встроенным кварцем.
      Вот только где найти их в нашей деревне я не знаю

      1. Я предпочитаю делать из того, что у меня уже лежит в коробочке, или можно купить за полдня. Мало ли где чего выпускают. Толку то с того… Еще полгода искать будешь.

      2. «Засунуть мешало 2 знака на год. Часам абсолютно всё равно, 2009 или 1909 год на дворе, а вот день недели разный.»

        — так вот именно! Что мешало сделать «полный» год и автовычисление дня недели?!… Лентяи! 8D

    2. Есть еще одно, в некоторых случаях неприятное отличие. PCF не хранит год. Год представлен как число 0-3(где 0 — високосный). А стало быть, если нужен реальный год, то нужно писать дополнительный код на хранение и вычисление года уже в микропроцессоре…

  7. По поводу глюка микрухи. У меня на тини 26 не хотел работать сторожевой таймер. Никаких ошибок не выдавал, а на другой тини 26 этот код работал нормально. Я так понимаю контроль качества у производителей хромает.

  8. Меня тут друзья попросили намутить что-то типа «эмуляции» присутствия в доме. бывают что они уезжают на неделю-две. Ну короче чтобы свет вечером, то включался, то выключался.А мне как всегда некада и тут эта статейка. И я вот подумал, и надумал такую концепцию: контроллер опрашивает часики с каким-то интервалом, если время больше или равно, то дергает с заданой программой MOSFET. Как вам? или есть способ легче?

    1. Можно перепрограммировать на лету эти часики и тогда они сами просигнализируют о событии, там же будильник есть.

      А вообще я бы сделал продвинутей — детектор освещения+рандом генератор на включение
      часы + рандом генератор на выключение.

    1. Извините DI HALT — это не реклама.
      По поводу :»Меня тут друзья попросили намутить что-то типа “эмуляции” присутствия в доме. бывают что они уезжают на неделю-две. Ну короче чтобы свет вечером, то включался, то выключался.» Посмотрите на сайте http://iopa4.narod.ru

      1. DI HALT спасибо, я тоже в даташите не нашел, решил спросить тебя. Вероятно все-таки нет, нужно делать программно. Я все со своим таймером бегаю как нищий с торбой. Прислал мне trembo с форума на Казусе две PCF8583 и две S26MD01. Я их подсунул в таймер и переписал управление по гражданским сумеркам, но вышло уже на Atmega168 (тоже его). Теперь пытаюсь урезать код. Думал, что смарт-календарь, чтобы убрать код проверки високосного и лето/зима.

  9. На фотке, где девайс в руке лежит, там, на заднем плане лежит плата отладочная на мегу 8, так вот, ты видео снимал, где то я уже не помню, ты там рассказывал, как светодиод подключить к штыревым линейкам, как SMD припаять, и рассказывал о достоинствах штыревых разъемов PLS. Где это видео? надо срочно найти)))Ты еще там говорил, что резисторы — вот такие чернинькие, а конденсаторы вот такие вот кориченевенькие. И говорил, что продаюстя вот в таких вот линейках. Плиз, найди видео, отошли мне тэг или адрес.

  10. а я мя нету этого диска…((( а у тебя он лайн на ютубе его нету? я его где то видел. плиз, дай он лайн ссылку)

    а что, твои статьи публиковали нна журнале?

  11. http://i014.radikal.ru/0907/95/6d3c5d59e986.jpg
    В общих чертах, имхо, микруха ничего. От батарейки работает идеально, но когда подключаю внешний источник, начинают ускоряться, хотя кварц заземлил. Подстроечный кондер не ставил, впадло его крутить каждый раз.

  12. А у меня с такими часиками косяк.
    Считываю данные в цикле.
    Значения секунд и минут несуразные. Вот например, от нуля до девяти досчитывает,
    а после скачком становится 16 или другим, при этом само значение минут и секунд
    может быть 80 или 90.

  13. Di, в чем разница?

    ;Принять байт.
    IIC_RCV: OUTI TWCR,1<<TWINT|1<<TWEN|1<<TWEA|0<<TWIE
    IIC_R: IN OSRG,TWCR
    ANDI OSRG,1<<TWINT
    BREQ IIC_R ; Ждем пока байт будет принят
    RET

    ;——————————————————————————
    ; Принять последний байт. Помните я писал о разнице между просто байтом и последним
    ; байтом? В последнем байте не генерируется ACK!!!
    IIC_RCV2: OUTI TWCR,1<<TWINT|1<<TWEN|0<<TWEA|0<<TWIE
    IIC_R2: IN OSRG,TWCR
    ANDI OSRG,1<<TWINT ; Ждем пока байт будет принят
    BREQ IIC_R2
    RET

        1. 128 переполнений 8-битного таймера с частотой 32768 дадут ровно 1 сек. Или 1 переполнение, с предделителем 128.
          Смотря с какой точностью тебе надо отловить эту 1 секунду, можно еще высчитывать время входа в прерывание, увеличение счетчика переполнений и т.д.

    1. Я софтовый I2C не делал, только аппаратный. А примеров так то вагон и маленькая тележка по инету разбросаны. Собственно, все какие видел примеры они и есть софтовые.

      1. Спасибо, я разобрался. Похоже pcf8583 и WDT не давали нормально работать 24с256.
        Так что, если что есть пример софтового на Си, ведь никто не мешает смотреть асемблерные листинги.

  14. DI HALT — спасибо, клевый у тебя сайт и материал классный.
    Собрал я по этой статье часики — от батарейки нормально идут, от внешнего питания начинают бежать в 1,5 раза примерно. Переделал на DS1307 — не записывается в них дата и месяц (ну и dayofweek тоже) — на двух разных (по стилю надписей) чипах одна и та же беда. Время и год записывается, а число-месяц никак!
    Вот теперь думаю — может, переделать опять на PCF8535? Может из-за канифоли на ножках бежали? Хотя DS1307 больше по душе пришлась, но вот с датами — косяк…

      1. Уря!!! Победил PCF8583!!! Оказывается, совсем без конденсатора нельзя. Поставил кварц на 32768 с нагрузочной емкостью 19 пФ — бегут как бешенные. Воткнул конденсатор между 1 и 8-й ножкой на 27 пФ — сразу ход нормализовался. Так что ф топку DS1307 :)

        1. блин… рано обрадовался… через полдня часики взяли и глюканули странным образом… секунды зациклились от 0 до 4. Вернулся опять на DS1307

          DI HALT, рамтроновские — это как?

          1. фирма RAMTRON они вообще прикольной памятью славятся (типо флеша, но не имеет лимита перезаписей и быстрая как незнаю что) и в довесок к своей памяти еще часто RTC пихают.

    1. Нет, они не рассчитаны на интервал в четыре года. В часах вообще год не хранится, эти два бита — признак високосного года. Значение 0 — високосный год, в феврале 29 дней, значения 1,2,3 — в феврале 28 дней. Собственно год рассчитывается программно.

  15. Немного оптимизируя iic_dumb.asm, я с экономил 24 байта. Это много, если работать с attiny2313 с памятю в 2 кб. Так как с точек IIC_S, IIC_B, IIC_R и IIC_R2 до выхода всё повторяется, я вставил RJMP IIC_S и оставил его только в одном экземпляре.

  16. Кстати, ни в статье, ни в каментах не нашел замечания о том, что при записи в часы текущего времени\даты рекомендуется остановить часы, выставив флаг остановки (бит 7) в регистре CONTROL\STATUS (по адресу $00), иначе можно нарушить их нормальную работу. После записи надо сбросить флаг, чтобы часы пошли.

    Источник datasheet на PCF8583 от Phillips.

  17. Спаял и написал программу на Си. Компилировал в CVAVR. Иногда при пропадании питания часы продолжают идти, а иногда — сбиваются и начинают показывать что попало.88 часов например или вообще выводятся не коректные символы, тоесть из микросхемы в МК приходит некоректные данные типа 0xAD или 0xFF, выходящие за число а максимальным ведь должно быть число 0x59 например для минут если, верно? Кварц на общий припаян.
    В основном цикле программы постоянно опрашиваю CF8583, на прерывании таймера реализована индикация. Опрашиваю так:
    while (1){rtc_get_time(0,&chas,&min,&sek,&msek);};
    или так:
    while (1)
    {
    min = rtc_read(0, 3);
    chas = rtc_read(0, 4);
    };
    глючит одинаково во обеих вариантах

      1. Нет нигде в программе я прерывания не запрещал., в уме прокрутил и не понял зачем их запрещать вначале прерывания? или на время считывания данных из CF8583 надо запрещать прерывания?

  18. сейчас штурмую буфер из стать про уарт и мне сильно кажется что его можно использовать и для TWI. просто там можно использовать регистры управления по другому? или как?
    и как перевести из си на асм? транслятором? (чтобы самому — «не дорос» ещё моском)

      1. ладно. попробую перевести сам.
        кстати можно ли про библиотеку в отдельную статью на главную сайта?
        судя по форуму — не полнять — написано ли или ещё в работе…

        а про буфер (вх. и вых.) — оно того стоит?

  19. а то что регистр состояния постоянно меняется после того как с часов считали несколько байт это нормально? то есть было записано 0х00, считали сс/мм/чч и в регистре рандомное значение.
    пцц микрухи делают
    подробности тут: http://forum.easyelectronics.ru/viewtopic.php?f=4&t=8436&p=147515#p147515

  20. Такой вопрос: можно ли так настроить часы чтобы например при каждом изменении минут делала прерывание (вывод INT устанавливался в 0)? Не нашел как настроить такую возможность.

  21. Строчку
    BREQ IIC_ST ; Ждем пока не будет готов стоп.
    надо заменить на
    BRNE IIC_ST ; Ждем пока не будет готов стоп.

    А то флаг стопа ведь опускается, когда стоп-последовательность выполнилась, поэтому надо пропускать если TWSTO = 0, а не 1
    :)

  22. Есть несколько вопросиков:
    1. Есть ли смысл использовать термокомпенсированные кварцы? Насколько это улучшит точность?
    2. Существуют микросхемы часов со встроенными резонаторами. Есть ли у них какие-то преимущества (кроме экономии места)?
    3. По IIC. Если на шине несколько устройств, как делать подтяжку? Так же 2 резистора по 10к или как-то иначе?

Добавить комментарий