Библиотека avr для работы с шиной i2c и с часами реального времени pcf8583

Часы реального времени 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

Источник: http://easyelectronics.ru/chasy-realnogo-vremeni-pcf8583.html

Микросхема часов реального времени PCF8583

Микросхема PCF8583  выполняет функции часов реального времени, таймера, счетчика событий и статического ОЗУ емкостью 240 байт. Для передачи данных используется шина I2C. Микросхема изготавливается в 8-ми выводном корпусе.

 Назначение выводов

OSC1 – вход внешнего генератора 32768Гц.
OSC2 – выход генератора.

A0 – Линия выбора адреса
Vss – общий провод питания
SDA – линия данных шины I2C
SCL – линия тактового сигнала шины I2C
INT – выход прерывания для внешнего устройства. Требует подключения подтягивающего резистора.
Vdd– линия питания

Схема распределения памяти

Фактически микросхема PCF8583 представляет собой статическое ОЗУ, емкостью 256 байт, у которого первые 16 байт являются регистрами специального назначения. Назначение некоторых регистров зависит от режима работы микросхемы. Режим задается в регистре состояния имеющем адрес 00h. Все числа в регистрах часов по умолчанию хранятся в BCD формате. 

АдресОписание00h01h02h03h04h05h06h07h08h09h0Ah0Bh0Ch0Dh0Eh0Fh10h…FFh
Регистр состояния
Доли секунд
1/10с 1/100с
Секунды
10с
Минуты
10мин 1мин
Часы
10ч
Дата
10дн
Месяц
10мес 1мес
Таймер
10дн
Регистр тревог
Тревога. Доли секунд
1/10с 1/100с
Тревога. Секунды
10с
Тревога. Минуты
10мин 1мин
Тревога. Часы
10ч
Тревога.Дата
Тревога. Месяцы
Таймер тревоги
Статическое ОЗУ

 Регистр состояния

Регистр состояния содержит биты задания режимов работы микросхемы и флаги.

76543210
SC HLC CM1 CM0 Mask Alarm FT1 FT0
  • FT0 – флаг Timer. Если бит Alarm установлен в 0, данный бит переключается с частотой 1 Гц.
  • FT1 – флаг Timer. Если бит Alarm установлен в 0, данный бит переключается с частотой ½ мин.
  • Alarm – бит разрешения режима «тревога» ( 0 – запрещен, 1 – разрешен)
  • Mask – при установке 1 позволяет считывать значения даты и месяца (05h,06h) в виде числа, а не в BCD формате.
  • CM1, CM0 – биты установки режима. 00 – часы с входной частотой 32768Гц, 01 – часы с входной частотой 50Гц, 10 – счетчик событий, 11 – режим тестирования.
  • HLC –
  • SC – флаг останова счета (0 – счет идет, 1 – счет остановлен по условию) 

Режим часов (Clock mode)

Режим часов устанавливается путем записи 00b или 01b в биты 4,5 регистра состояния.

В данном режиме микросхема осуществляет счет импульсов от тактового генератора и на основе этих данных вычисляет время и дату. Значения заносятся в регистры 01h-07h в двоично-десятичном формате. Старший полубайт отвечает за десятки, а младший за единицы.

При чтении данных в регистрах 05h,06h рекомендуется устанавливать флаг mask. Это позволяет читать дату и месяц, не проводя дополнительных вычислений. Все регистры доступны на чтение и запись.

Это позволяет установить текущее время, просто записав нужное значение в соответствующий регистр.

 В режиме часов имеются некоторые особенности работы регистров 04h-05h.

 Регистр Часов (04h)

Начальная установка после сброса – 00000000b 

76543210
HM AM/PM DH1 DH0 H3 H2 H1 H0
  • H0-H3 – единицы часов в BCD формате
  • DH0-DH1 – десятки часов
  • AM/PM – флаг до и после полудня.
  • HM – режим работы регистра часов (0 – 24-часовой формат AM/PM не задействован, 1 – 12-часовой формат с установкой флага AM/PM). 

Регистр Дата (05h)

Начальная установка после сброса – 00000001b 

76543210
Y1 Y0 DD1 DD0 D3 D2 D1 D0
  • D0-D3 – единицы дней в BCD формате
  • DD0-DD1 – десятки дней
  • Y0-Y1 – год. В случае установки флага Mask данные биты читаются как 0 

Регистр Месяц (06h)

Начальная установка после сброса – 00000001b 

76543210
W2 W1 W0 DM0 M3 M2 M1 M0
  • M0-M3 – единицы номера месяца в BCD формате
  • DM0 – десятки номера месяца
  • W0-W2 – номер недели в месяце. В случае установки флага Mask данные биты читаются как 0 

В режиме часов можно запустить таймер (07h). Он включается, если в регистре состояния записывается комбинация ХХ0Х Х1ХХb. Таймер имеет диапазон счета от 0 до 99. В случае переполнения таймера устанавливается флаг Timer в регистре состояния.

Сброс этого флага осуществляется программно, путем обнуления соответствующих битов. Выбор функции счета  таймера выполняется в регистре тревог – Alarm Control (08h). В этом же регистре возможно подключить выход таймера к выводу INT микросхемы.

 

Режим Alarm

Микросхема PCF8583 имеет возможность генерировать сигнал события (прерывания) при совпадении значений в счетных регистрах и регистрах alarm. При генерации сигнала могут учитываться не все регистры. Например, при ежедневном сигнале игнорируются значения, находящиеся в регистрах Тревога.Дата, Тревога.Месяцы.

Регистр Alarm Control (08h)

76543210
IntA AT A1 A0 IntT T2 T1 T0

000 – без таймера
001 – десятки и сотни секунд
010 – секунды
011 – минуты
100 – часы
101 – дни
110 – не используется
111 – тестовый сигнал на всех интервалах

  • IntT – прерывание от таймера (0 – нет, 1 – есть)
  • A0-A1 – функция alarm (00 – нет, 01 – ежедневный alarm, 10 – еженедельный alarm, 11 – alarm по дате).
  • AT – alarm по таймеру (0 – выкл, 1 – вкл)
  • IntA  – прерывание по режиму alarm (0 – нет, 1 – есть)

You have no rights to post comments

Источник: https://mcucpu.ru/index.php/pdevices/datchiki/73-pcf8583

Учебный курс AVR. Использования TWI модуля. Основы I2C. Ч1

Подключение устройств к I2C шине

I2C шина представляет собой две двунаправленные линии связи – SDA (Serial Data Line) и SCL (Serial Clock Line). По SDA передаются данные, по SCL тактовый сигнал. Обе линии подтянуты через резисторы к плюсу питания.

Устройства на шине подразделяются на ведущих (master) и ведомых (slave). Ведущие запускают и завершают передачу данных, ведомые – отвечают на запросы. Одни – начальники, другие – подчиненные. Микроконтроллеры могут совмещать в себе обе эти функции.

Выходные каскады устройств, поддерживающих I2C, выполнены как структуры с открытым коллектором/стоком. При подключении к шине, они образуют схему монтажного “И”.

Это значит, что любое устройство, установившее низкий логический уровень на линии шины, “проваливает” высокий уровень остальных устройств.

 

На шине может быть несколько ведущих устройств, но в любой момент времени, обмен данными может производить только один из них. Остальные ведущие в это время молчат в тряпочку и слушают шину.

Существует механизм распределения приоритетов между ведущими, если они начинают передачу данных одновременно. Он заключается в том, что ведущие устанавливают на шине данные и проверяют результат. Если он отличается от ожидаемого, устройство теряет приоритет и останавливает передачу данных.

Передача данных по I2C

Данные передаются поразрядно (спасибо кэп!), старшим разрядом вперед. Каждый разряд сопровождается тактовым сигналом.

Начало и окончание передачи данных сопровождается специальными состояниями шины – СТАРТ и СТОП. Эти состояния формирует ведущее устройство. Также ведущий может сформировать состояние повторного старта до формирования состояния СТОП. 
Данные передаются по I2C шине со служебной информацией. Все вместе это называется пакетом. Существуют адресные пакеты и пакеты данных. Адресные пакеты состоят из 7-и разрядного адреса, управляющего бита R/W и бита квитирования (весь пакет – 9 бит). Адресный пакет нужен, чтобы обратиться к конкретному устройству. R/W – определяет последующее направление передачи данных. Бит квитирования – это ответ ведомого устройства на принятый адрес. Если адрес распознан, ведомый выдает на линию SDA низкий уровень. В противном случае на линии удерживается высокий уровень.Под адрес отведено 7 разрядов, что как бы намекает на возможность адресации 128 устройств, но это не совсем так. Во-первых существует ряд служебных адресов, например, 0000000 – это адрес общего вызова (обращение ко всем ведомым устройствам). Во-вторых есть режим 10-и разрядной адресации, когда адрес передается двумя пакетами. Не буду углубляться в эту тему, только скажу, что адреса из диапазона 1111000…1111111 не рекомендуется использовать в TWI модуле AVR (курим даташит).Пакеты данных состоят из байта данных и бита квитирования, то есть тоже имеют длину 9 бит.После приема каждого байта данных, принимающее устройство (приемник) отвечает передающему устройству (передатчику), устанавливая на линии SDА низкий уровень (это и есть бит квитирования). Если принимающее устройство получило последний байт или больше не может продолжать прием данных, оно должно “оставить” на линии SDA высокий уровень. 

Читайте также:  Как бесплатно звонить домой с сотового телефона

В общем случае, полный цикл обмена по I2C состоит из следующих шагов:- формирование состояния СТАРТ,
– передача адресного пакета,
– передача пакетов данных,
– прием пакетов данных,
– формирование состояния СТОП.На этом все. Продолжение следует..

У вас недостаточно прав для комментирования.

Источник: http://chipenable.ru/index.php/programming-avr/item/194

AVR: Передача данных по шине I²C (I2C, IIC, TWI)

Налаживаем обмен данными между двумя контроллерами по шине I²C

С вашего разрешения я не буду вас томить всякими теоретическими копипастами и сразу перейдем к практической части.

Не, серьезно, почти каждый сайт об электронике содержит статью по этому протоколу, причем одну и ту же :).

Шина I²C состоит из двух линий:

  • SCL — линия последовательной передачи синхроимпульсов («при передаче посылок по шине I2C каждый ведущий генерирует свой синхросигнал на линии SCL» — http://ru.wikipedia.org/wiki/I%C2%B2C)
  • SDA — линия последовательной передачи данных

Эти линии обозначены на схемах выводов контроллера (pinout-схемы) в скобочках. К примеру, на mega16: PC1(SDA), PC0(SCL).

ATMEGA16-pinout

Если таких выводов на схеме не наблюдается, то скорее всего, в кристалл этот самый интерфейс шины I²C (точнее, модуль TWI — более подробно о I2C и TWI читайте в статье про 24CXX_EEPROM, см. в конце статьи) не интегрирован, т.е. аппаратной поддержки этого интерфейса нету и такой контроллер не способен обмениваться данными по этой шине.

Для статьи я выбрал два наиболее распространненных контроллера, имеющие этот интерфейс — ATMEGA16(пусть он будет у нас ведущим устройством) и ATMEGA8(а он будет ведомым).

Бибилиотека avr-libc, входящая в состав WinAVR, не содержит каких-либо готовых сорцев для работы с I²C (кстати там есть демонстрационный исходник для работы с «24Cxx I²C EEPROM» — /avr-libc/examples/twitest/twitest.c).

На вооружение я брал 2 различных исходника:

  • один предлагают специалисты компании Atmel в апноутах (AVR315 Использование модуля TWI в качестве ведущего интерфейса I2C и AVR311 Использование модуля TWI в качестве подчиненного интерфейса I2C)
  • другой принадлежит мистеру Pascal Stang, автору известного набора джентльмена Procyon AVRlib.

Более удобным оказался исходник из библиотеки Procyon AVRlib — в одном файле реализована поддержка и Master, и Slave устройств (в отличие от двух различных файлов в апноутах Atmel), а также подкупила простая и удобная процедура приема данных у slave-устройства. Извините, я уже забежал вперед.

  • i2c.c и i2c.h — главное, что нам надо, однако в этих файлах есть ссылки на другие заголовочные файлы из библиотеки:
  • i2cconf.h — так-то в нем ваще ничо нет :), кроме двух define-ов
  • global.h — в нем определены F_CPU и CYCLES_PER_US + еще 2 заголовочных файла:
  • avrlibdefs.h — часто всеми используемые упрощения clearbit, setbit и тому подобное
  • avrlibtypes.h — здесь переопределены типы, например «typedef unsigned char  u08;» и т.д.

Разумеется, лишнее (а кому и не лишнее) можно убрать — сделать все под себя, под свои принципы и привычки. Пока давайте ничего менять не будем.

Всего нам понадобятся две прошивки — для ведомого устройства ATMEGA16 и для подчиненного ATMEGA8.

Начнем с создания проекта для Master-а (работаю я в AVR Studio). Создаем проект, подключаем i2c.c, i2c.h и все второстепенные файлы (i2cconf.h, …).

В global.h поменяйте F_CPU на свою тактовую, и в файле i2c.c в процедуре void i2cInit(void) закомментируйте лишнее:

sbi(PORTC, 0); // i2c SCL on ATmega163,323,16,32,etc sbi(PORTC, 1); // i2c SDA on ATmega163,323,16,32,etc //sbi(PORTD, 0); // i2c SCL on ATmega128,64 //sbi(PORTD, 1); // i2c SDA on ATmega128,64

Больше ничо менять не нужно, приступим к кодингу главного файла проекта.

/*MASTER*/ ……………………………………………… #define LOCAL_ADDR 0xA0   //адрес мастера ATMEGA16 #define TARGET_ADDR 0x07  //адрес slave-а ATMEGA8 unsigned char buf[100]; int main(void) { _delay_ms(1000); //на момент включения мастера, slave (ATMEGA8) уже должен быть готов к приему данных (далее мы будем тестировать обмен данными в симуляторе Proteus). Поэтому запускаем мастера с секундной задержкой. sendStr0(“*************TWI MASTER RUNNING*************”); uart0_init(); // иниц. UART-а для вывода отладочных сообщений // initialize i2c function library i2cInit(); // set local device address and allow response to general call i2cSetLocalDeviceAddr(LOCAL_ADDR, TRUE); //отсылаем строку по шине I2C unsigned char mBuf[20]; sprintf(mBuf,”%s”,”hello!”); mBuf[strlen(mBuf)]=0x00;//по привычке сделаем последний символ строки нулевым i2cMasterSend(TARGET_ADDR,strlen(mBuf)+1/*(0x00)*/,&mBuf[0]); sprintf(buf,”master sended: %s (length %d)”,mBuf,strlen(mBuf)+1/*(0x00)*/); transmitString(buf);TX_NEWLINE; while(1) { _delay_ms(100); } }

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

Отключение оптимизации всего проекта конечно приводило к желаемому результату — но это не вариант, т.к.

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

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

Теперь надо создать еще один проект для подчиненного ATMEGA8, подключить те же самые файлы и так же настроить.

/*SLAVE*/ ……………………………….. #define LOCAL_ADDR 0x07 //адрес slave-а ATMEGA8 #define TARGET_ADDR 0xA0 //адрес мастера ATMEGA16 unsigned char buf[100]; // При завершении приема данных по шине I2C вызывается эта процедура void i2cSlaveReceiveService(u08 receiveDataLength, u08* receiveData) { sprintf(buf,”slave received: %s (length %d)”,receiveData,receiveDataLength); transmitString(buf);TX_NEWLINE; } int main(void) { sendStr0(“*************TWI SLAVE RUNNING*************”); uart0_init();// иниц. UART-а для вывода отладочных сообщений // initialize i2c function library i2cInit(); // set local device address and allow response to general call i2cSetLocalDeviceAddr(LOCAL_ADDR, TRUE); //Про нее я уже заикнулся – простая и удобная процедура приема данных. По сути прерывание при приеме данных. i2cSetSlaveReceiveHandler( i2cSlaveReceiveService ); while(1) { _delay_ms(100); } }

Ну вот, обе прошивки готовы. Теперь протестируем все в симуляторе Proteus.

Из компонентов нам понадобятся ATMEGA16, ATMEGA8, resistor, из виртуальных устройств — два терминала и SPI-отладчик (SPI DEBUGGER).

Соединяем линии SCL и SDA контроллеров. На эти линии надо еще повесить резисторы 4.7 кОм на + питания. SPI-отладчик подсоединяем к SCL и SDA соответственно. Подключаем терминалы. Настраиваем частоту контроллеров, битрейт в терминалах. Все, пожалуй.

https://www.youtube.com/watch?v=IUmQNXoePSY

Демонстрирую результат:

Архив с проектом  http://www.box.net/shared/nuac0pytxh

UPD1: Если хотите подробно разобраться с I2C и TWI и написать свою библиотеку для этого интерфейса, читайте статью https://nagits.wordpress.com/2010/12/18/avr_i2c_eeprom/.

Источник: https://nagits.wordpress.com/2010/10/09/avr_twi/

Программирование Arduino – библиотека Wire – для работы с I2C

Микроконтроллеры Atmega имеют хардварную поддержку интерфейса (TWI). Линии интерфейса SDA и SCL у МК Atmega8/168/328, сидят на 27 (PC4) и 28 (PC5), соответственно.

На платах , линия данных — SDA (data line) выведена на аналоговый пин 4, а линия тактирования — SCL (clock line) выведена на аналоговый пин 5. На Arduino Mega, SDA — это цифровой пин 20, а SCL — цифровой пин 21.

Для работы с протоколом , у есть штатная библиотека Wire, которая позволяет взаимодействовать с I2C/TWI-устройствами, как в режиме мастера, так и в режиме слейва.

В , библиотека наследуется от Stream, что делает её использование схожим с другими библиотеками чтения/записи (read/write libraries). В связи с этим, методы send() и receive() были заменены на read() и write().

class TwoWire : public Stream {Рассмотрим методы библиотеки

void begin(); void begin(uint8_t address);

void begin(int address);

Описание:

Инициализация библиотеки Wire и подключение к шине I2C в качестве мастера или слейва. Как правило, вызывается только один раз.

Параметры:

address: 7-битный адрес устройства (если работаем в режиме слейва). Если не указано, то контроллер подключается к шине в роли мастера (master).

Возвращаемое значение:

нет

uint8_t requestFrom(uint8_t address, uint8_t quantity);

Описание:

Используется мастером для запроса байта от ведомого устройства (слейва). Байты могут быть получены с помощью методов available() и read().

Параметры:

address: 7-битный адрес устройства для запроса байтов данных quantity: количество запрошенных байт

Возвращаемое значение:

число считанных байт

void beginTransmission(uint8_t address);

Описание:

Начало передачи I2C для ведомого устройства (слейва) с заданным адресом. Затем, нужно вызвать метод write() для добавления последовательности байт в очередь предназначенных для передачи, и выполнить саму передачу данных методом endTransmission().

Параметры:

address: 7-битный адрес устройства для передачи

Возвращаемое значение:

нет

uint8_t endTransmission(void);

Описание:

Завершает передачу данных для ведомого устройства(слейва), которое было начато beginTransmission() и, фактически, осуществляет перечу байт, которые были поставлены в очередь методом write().

Параметры:

нет

Возвращаемое значение:

байт, который указывает статус передачи: 0: успех 1: данных слишком много и они не помещается в буфер передачи 2 получили NACK на передачу адреса 3 получили NACK на передачу данных 4: другая ошибка

size_t write(uint8_t data);
size_t write(const uint8_t *data, size_t quantity);

Вызов:

Wire.write(value); Wire.write(string); Wire.write(data, length);

Описание:

Записывает данные от ведомого устройства (слейва) в ответ на запрос мастера, или записывает очередь байт для передачи от мастера к ведомому устройству (в промежутках между вызовами beginTransmission() и endTransmission()).

Параметры:

value: значение для отправления как единичный байт string: строка для отправления как последовательность байт data: массив байт для отправления length: число байт для передачи

Возвращаемое значение:

возвращает число записанных байт

Пример:

#include byte val = 0; void setup() { Wire.begin(); // подключение к шине i2c } void loop() { Wire.beginTransmission(44); // передача для устройства #44 (0x2c) // адрес устройства указывается в документации (datasheet) Wire.write(val); // отправка байта val Wire.endTransmission(); // передача данных val++; // инкремент значения if(val == 64) // если достигли 64 (max) { val = 0; // начинаем с минимального значения } delay(500); }

int available(void);

Описание:

Возвращает количество байт, доступных для получения. Этот метод должно быть вызван на мастере, после вызова requestFrom() или слейвом внутри обработчика onReceive(). available() наследуется от класса Stream.

Параметры:

нет

Возвращаемое значение:

Число байт, доступных для чтения.

int read(void);

Описание:

Считывает байт, который был передан от ведомого устройства(слейва) к мастеру, после вызова requestFrom() или был передан от мастера к слейву. read() наследуется от класса Stream.

Параметры:

нет

Возвращаемое значение:

Следующий полученный байт.

Пример:

#include void setup() { Wire.begin(); // подключение к шине i2c Serial.begin(9600); // запуск последовательного порта } void loop() { Wire.requestFrom(2, 6); // запрос 6 байт от слейва #2 while(Wire.available()) // пока есть, что читать { char c = Wire.read(); // получаем байт (как символ) Serial.print(c); // печатает в порт } delay(500); }

void onReceive( void (*function)(int) );

Описание:

Регистрирует функцию, которая вызывается, когда ведомое устройство(cлейв) получает данные от мастера.

Параметры:

function: функция, которая вызывается, когда cлейв получает данные; обработчик должен принимать один параметр — int (число байт, считанных от мастера) и ничего не возвращать.

например:

void MyHandler (int numBytes);

Возвращаемое значение:

нет.

void onRequest( void (*function)(void) );

Описание:

Регистрирует функцию, которая вызывается, когда мастер запрашивает данные из этого ведомого устройства.

Параметры:

function: функция, которая будет вызываться; не имеет параметров и ничего не возвращает.

например:

void MyHandler();

Возвращаемое значение:

нет

Ссылки:

По теме:

Источник: http://robocraft.ru/blog/arduino/786.html

Библиотека AVR для работы с шиной I2C и с часами реального времени PCF8583

Мне нужно было сделать часы на основе микросхемы, имеющей I2C интерфейс. Микросхема RTC, т.н. “часы реального времени” PCF8583.

Внутри микросхемы расположены: часы, будильник, таймер, календарь (кривой), и 240 байт оперативной памяти, куда можно записывать любую информацию, которую только вздумается. Оперативная память это очень полезная штука, в отличии от флеш-памяти, оперативная память не имеет ограничений по количеству циклов перезаписи, и в неё можно сохранять какие-то данные, настройки, сколь угодно часто.

Но была одна проблемка – писАть код жутко не хотелось, и я решил найти готовый код в интернете. Как позже выяснилось, найти «на свою голову». Скачал пример работы с I2C, подправил, прошил микроконтроллер. Не заработало.

Стал ковырять код, искать причину неработоспособности… и ужаснулся!! Запись в некоторых случаях велась во весь порт сразу, а не в конкретные биты. Таким образом, если на порт повесить ещё что-то, например, дисплей, то скорее всего, оно работать не будет.

Также неправильно было реализовано чтение данных по шине (без генераций условия окончания приёма, или просто без NACK). Но это пол-беды. Основная проблема в другом. Зачастую автор кода выставлял в порт логическую «1», а как мы знаем, шина I2C управляется «притягиванием» выводов SDA и SCL к общему проводу.

А логическая «1» на шине, в свою очередь, формируется за счёт подтяжки к плюсу питания резисторами на 4,7 килоом. Таким образом, если на выходе микроконтроллера выставить логическую «1», а ведомое устройство «притянет» этот выход к общему проводу, то получится «ба-бах» короткое замыкание.

Мне это очень не понравилось, и я решил изобрести свой велосипед  написать свою библиотеку, а вернее даже 2 библиотеки: одна для работы с шиной I2C, а другая непосредственно для работы с часами реального времени PCF8583. Да, кстати, код написан в AVR Studio 6.

Для того, чтобы подключить библиотеку I2C к проекту, нужно прописать её через include, как на картинке, а также скопировать библиотеку в папку с проектом.

После чего, необходимо открыть файл “i2c.h”, и указать ножки микроконтроллера, которые будут выступать в роли шины I2C. По умолчанию шина настроена на ножки PC0 (SCL) и PC1 (SDA). А настройка делается вот тут:

Всё, библиотеку I2C мы подключили, ножки настроили, библиотека готова к работе. Пример использования:

i2c_init (); // Инициализация шины I2C i2c_start_cond(); // старт шины i2c_send_byte (0xA0); // адрес устройства, которое висит на шине i2c_send_byte (0x10); // байт данных, который записываем в устройство i2c_send_byte (0x10); // ещё один байт данных, который записываем в устройство i2c_stop_cond(); // стоп шины

После стоп-условия, мы можем проверить, всё ли у нас в порядке с шиной I2C. Для этого нужно прочитать переменную «i2c_frame_error». Если всё нормально, то в ней будет 0.

Если один из выводов шины не «подтянулся» к питанию, и логическая «1» не установилась на шине, то библиотека генерирует ошибку, и записвает в переменную «i2c_frame_error» циферку 1.

Читать переменную «i2c_frame_error» нужно после стоп-условия. На рисунке ниже продемонстрирую как работает контроль ошибки:

Теперь займёмся подключением библиотеки часов реального времени PCF8583. Для этого нужно проделать те же самые действия. Скопируем в папку с проектом файл “PCF8583.h”, и пропишем его в include, как на фото:

Готово. Библиотека часов реального времени PCF8583 подключена. Она не требует каких-либо настроек, поэтому можно сразу приступать к чтению времени и даты с микросхемы. Обращаю внимание, что библиотека PCF8583 работает при помощи библиотеки I2C, поэтому если хотим работать с PCF8583, то нужно подключить обе библиотеки!

Пример использования библиотеки (запись и чтение времени и даты):

// Инициализация шины I2C i2c_init (); // Подготавливаем время и дату для записи в микросхему PCF8583 PCF_hour=23; // 23 часа PCF_min=59; // 59 минут PCF_day=31; // 31 число PCF_month=12; // 12 месяц – декабрь PCF_year=0; // год (0 – не високосный) PCF_weekday=6; // 6 день недели (воскресенье) // Записываем время и дату в микросхему PCF8583 PCF_write_hh_mm_ss(); // Считываем время и дату из микросхемы PCF8583 PCF_read_hh_mm_ss(); Пример работы с оперативной памятью (запись и чтение): // Подготавливаем 5 байт для записи в микросхему PCF8583 PCF_data_ram_1=255; // байт 1 PCF_data_ram_2=255; // байт 2 PCF_data_ram_3=255; // байт 3 PCF_data_ram_4=255; // байт 4 PCF_data_ram_5=255; // байт 5 // Записываем 5 байт в микросхему PCF8583 PCF_write_ram(); // Считываем 5 байт из микросхемы PCF8583 PCF_read_ram();

Чтение из микросхемы ещё проще – достаточно вызвать функцию PCF_read_hh_mm_ss() после чего, время и дата появятся в переменных, откуда их только забирай. Для чтения оперативной памяти соответственно используем функцию PCF_read_ram()  после чего данные забираем в переменных PCF_data_ram_N

Вот список переменных, где и что хранится:

// время и дата PCF_hour=0; // время, часы (от 0 до 23, защита от переполнения при записи и чтении) PCF_min=0; // время, минуты (от 0 до 59, защита от переполнения при записи и чтении) PCF_sec=0; // время, секунды (только для чтения, при записи сбрасываются в 00) PCF_day=0; // день (от 1 до 31, защита от переполнения при записи и чтении) PCF_weekday=0 // день недели (0-понедельник; 6-воскресенье, защита от переполнения при записи и чтении) PCF_month=0; // месяц (от 1 до 12, защита от переполнения при записи и чтении) PCF_year=0; // год (0-високосный; 1,2,3-невисокосные, защита от переполнения при записи и чтении) // оперативная память PCF_data_ram_1; // Данные (ОЗУ PCF8583), байт 1 PCF_data_ram_2; // Данные (ОЗУ PCF8583), байт 2 PCF_data_ram_3; // Данные (ОЗУ PCF8583), байт 3 PCF_data_ram_4; // Данные (ОЗУ PCF8583), байт 4 PCF_data_ram_5; // Данные (ОЗУ PCF8583), байт 5

Теперь расскажу про защиту от переполнения. Допустим, мы забыли подключить микросхему. Прочитаем данные с микросхемы, и… прочитается байт 11111111, или число 255. Всё дело в том, что в основе шины I2C лежат 2 подтягивающих резистора, вот они то и выдают нам логические «единички» если микросхема не подключена.

Для защиты от подобных случаев, в библиотеке PCF8583 я сделал защиту от переполнений, которая следит за тем, чтобы часики не показывали вам 62 часа 81 минуту… Наличие переполнения можно проследить, прочитав переменную «PCF_overflow». Если в ней 0, значит ошибок переполнения не было. Если в ней 1 или более, значит ошибки переполнения имеются.

Читать переменную «PCF_overflow» нужно после функции чтения даты и времени PCF_read_hh_mm_ss()

Для наглядности, проект AVR Studio 6 под ATmega32 прилагается. Перекомпилировать можно под любой AVR. В проекте я также подключил дисплей для визуального контроля. При подаче питания, микроконтроллер устанавливает 23 часа 59 минут, 31 декабря, Воскресенье. И через минуту становится 00 часов 00 минут, 1 января, Понедельник.

https://www.youtube.com/watch?v=hs-IpfZ9nQU

Теперь расскажу, почему я говорил про «кривой» календарь этой микросхемы. Всё дело в том, что микросхема не умеет хранить текущий календарный год, а хранит лишь флаг високосного года. Короче говоря:
0 – високосный год
1 – не високосный год
2 – не високосный год
3 – не високосный год

И так по циклу 0-1-2-3-0-1-2-3-0…

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

Также прилагаю в конце статьи небольшой видеоотчёт. В программировании я можно сказать новичок, хоть и программирую уже 3 года (понемногу), за код строго не судите, если есть какие-либо дополнения и замечания, пишите, будем исправлять. Всем удачных самоделок!

Скачать список элементов (PDF)

Прикрепленные файлы:

  • схема, прошивка, проект Proteus, исходники, библиотеки.rar (172 Кб)

Источник: http://cxem.gq/mc/mc249.php

Библиотека AVR для работы с шиной I2C и с часами реального времени PCF8583

Библиотека AVR для работы с шиной I2C и с часами реального времени PCF8583

Мне необходимо было сделать часы на базе микросхемы, имеющей I2C интерфейс. Микросхема RTC, т. н. «часы реального времени» PCF8583.

Снутри микросхемы размещены: часы, будильник, таймер, календарь (кривой), и 240 б оперативки, куда можно записывать всякую информацию, которую только вздумается. Оперативка это очень нужная штука, в отличии от флеш-памяти, оперативка не имеет ограничений по количеству циклов перезаписи, и в неё можно сохранять какие-то данные, опции, сколь угодно нередко.

Но была одна проблемка — писАть код страшно не хотелось, и я решил отыскать готовый код в вебе. Как позднее выяснилось, отыскать «на свою голову». Скачал пример работы с I2C, подправил, прошил микроконтроллер. Не заработало.

Стал колупать код, находить причину неработоспособности… и испугался!! Запись в неких случаях велась во весь порт сходу, а не в определенные биты. Таким макаром, если на порт повесить ещё что-то, к примеру, экран, то вероятнее всего, оно работать не будет.

Также некорректно было реализовано чтение данных по шине (без генераций условия окончания приёма, либо просто без NACK). Но это пол-беды. Основная неувязка в другом. Часто создатель кода выставлял в порт логическую «1», как мы знаем, шина I2C управляется «притягиванием» выводов SDA и SCL к общему проводу.

А логическая «1» на шине, в свою очередь, формируется за счёт подтяжки к плюсу питания резисторами на 4,7 килоом. Таким макаром, если на выходе микроконтроллера выставить логическую «1», а ведомое устройство «притянет» этот выход к общему проводу, то получится «ба-бах» куцее замыкание.

Мне это очень не понравилось, и я решил изобрести собственный велик написать свою библиотеку, а точнее даже 2 библиотеки: одна для работы с шиной I2C, а другая конкретно для работы с часами реального времени PCF8583. Да, кстати, код написан в AVR Studio 6.

Для того, чтоб подключить библиотеку I2C к проекту, необходимо прописать её через include, как на картинке, также скопировать библиотеку в папку с проектом.

После этого, нужно открыть файл «i2c. h», и указать ножки микроконтроллера, которые будут выступать в роли шины I2C. По дефлоту шина настроена на ножки PC0 (SCL) и PC1 (SDA). А настройка делается вот здесь:

Всё, библиотеку I2C мы подключили, ножки настроили, библиотека готова к работе. Пример использования:

i2c_init (); // Инициализация шины I2C i2c_start_cond(); // старт шины i2c_send_byte (0xA0); // адресок устройства, которое висит на шине i2c_send_byte (0x10); // б данных, который записываем в устройство i2c_send_byte (0x10); // ещё один б данных, который записываем в устройство i2c_stop_cond(); // стоп шины

После стоп-условия, мы можем проверить, всё ли у нас в порядке с шиной I2C. Для этого необходимо прочесть переменную «i2c_frame_error». Если всё нормально, то в ней будет 0.

Если один из выводов шины не «подтянулся» к питанию, и логическая «1» не установилась на шине, то библиотека генерирует ошибку, и записвает в переменную «i2c_frame_error» циферку 1.

Читать переменную «i2c_frame_error» необходимо после стоп-условия. На рисунке ниже продемонстрирую как работает контроль ошибки:

Сейчас займёмся подключением библиотеки часов реального времени PCF8583. Для этого необходимо сделать те же самые деяния. Скопируем в папку с проектом файл «PCF8583.h», и пропишем его в include, как на фото:

Готово. Библиотека часов реального времени PCF8583 подключена. Она не просит каких-то опций, потому можно сходу приступать к чтению времени и даты с микросхемы. Обращаю внимание, что библиотека PCF8583 работает с помощью библиотеки I2C, потому если желаем работать с PCF8583, то необходимо подключить обе библиотеки!

Пример использования библиотеки (запись и чтение времени и даты):

// Инициализация шины I2C i2c_init (); // Подготавливаем время и дату для записи в микросхему PCF8583 PCF_hour=23; // 23 часа PCF_min=59; // 59 минут PCF_day=31; // 31 число PCF_month=12; // 12 месяц — декабрь PCF_year=0; // год (0 — не високосный) PCF_weekday=6; // 6 денек недели (воскресенье) // Записываем время и дату в микросхему PCF8583 PCF_write_hh_mm_ss(); // Считываем время и дату из микросхемы PCF8583 PCF_read_hh_mm_ss(); Пример работы с оперативной памятью (запись и чтение): // Подготавливаем 5 б для записи в микросхему PCF8583 PCF_data_ram_1=255; // б 1 PCF_data_ram_2=255; // б 2 PCF_data_ram_3=255; // б 3 PCF_data_ram_4=255; // б 4 PCF_data_ram_5=255; // б 5 // Записываем 5 б в микросхему PCF8583 PCF_write_ram(); // Считываем 5 б из микросхемы PCF8583 PCF_read_ram();

Чтение из микросхемы ещё проще – довольно вызвать функцию PCF_read_hh_mm_ss() после этого, время и дата появятся в переменных, откуда их только забирай. Для чтения оперативки соответственно используем функцию PCF_read_ram() после чего данные забираем в переменных PCF_data_ram_N

Вот перечень переменных, где и что хранится:

// время и дата PCF_hour=0; // время, часы (от 0 до 23, защита от переполнения при записи и чтении) PCF_min=0; // время, минутки (от 0 до 59, защита от переполнения при записи и чтении) PCF_sec=0; // время, секунды (только для чтения, при записи сбрасываются в 00) PCF_day=0; // денек (от 1 до 31, защита от переполнения при записи и чтении) PCF_weekday=0 // денек недели (0-понедельник; 6-воскресенье, защита от переполнения при записи и чтении) PCF_month=0; // месяц (от 1 до 12, защита от переполнения при записи и чтении) PCF_year=0; // год (0-високосный; 1,2,3-невисокосные, защита от переполнения при записи и чтении) // оперативка PCF_data_ram_1; // Данные (ОЗУ PCF8583), б 1 PCF_data_ram_2; // Данные (ОЗУ PCF8583), б 2 PCF_data_ram_3; // Данные (ОЗУ PCF8583), б 3 PCF_data_ram_4; // Данные (ОЗУ PCF8583), б 4 PCF_data_ram_5; // Данные (ОЗУ PCF8583), б 5

Сейчас расскажу про защиту от переполнения. Допустим, мы запамятовали подключить микросхему. Прочитаем данные с микросхемы, и… прочитается б 11111111, либо число 255. Всё дело в том, что в базе шины I2C лежат 2 подтягивающих резистора, вот они то и выдают нам логические «единички» если микросхема не подключена.

Для защиты от схожих случаев, в библиотеке PCF8583 я сделал защиту от переполнений, которая смотрит за тем, чтоб часики не демонстрировали вам 62 часа 81 минутку… Наличие переполнения можно проследить, прочитав переменную «PCF_overflow». Если в ней 0, означает ошибок переполнения не было. Если в ней 1 либо более, означает ошибки переполнения имеются.

Читать переменную «PCF_overflow» необходимо после функции чтения даты и времени PCF_read_hh_mm_ss()

Для наглядности, проект AVR Studio 6 под ATmega32 прилагается. Перекомпилировать можно под хоть какой AVR. В проекте я также подключил экран для зрительного контроля. При подаче питания, микроконтроллер устанавливает 23 часа 59 минут, 31 декабря, Воскресенье. И через минутку становится 00 часов 00 минут, 1 января, Пн.

Сейчас расскажу, почему я гласил про «кривой» календарь этой микросхемы. Всё дело в том, что микросхема не умеет хранить текущий календарный год, а хранит только флаг високосного года. Короче говоря: 0 – високосный год 1 – не високосный год 2 – не високосный год

3 – не високосный год

И так по циклу 0-1-2-3-0-1-2-3-0…

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

Также прилагаю в конце статьи маленькой видеоотчёт. В программировании я можно сказать новичок, хоть и программирую уже 3 года (понемногу), за код строго не судите, если есть какие-либо дополнения и замечания, пишите, будем исправлять. Всем успешных самоделок!

Перечень радиоэлементов

Обозначение Тип Номинал Количество ПримечаниеМагазинМой блокнот МК AVR 8-бит ATmega32 1 Поиск в win-sourceВ блокнот Часы реального времени (RTC) PCF8583 1 Поиск в win-sourceВ блокнот LCD-дисплейWH16021 Поиск в win-sourceВ блокнот Резистор 4.7 кОм 2 Поиск в win-sourceВ блокнот Кварц32768 Гц1 Поиск в win-sourceВ блокнотДобавить все

Скачать перечень частей (PDF)

схема, прошивка, проект Proteus, исходники, библиотеки. rar (172 Кб)
Часы I2C RTC Atmel Studio Proteus AVR Микроконтроллер

Источник: http://bloggoda.ru/2017/08/03/biblioteka-avr-dlya-raboty-s-shinoj-i2c-i-s-chasami-realnogo-vremeni-pcf8583/

ATmega8 + аппаратный TWI модуль: “делаем распечатку памяти RTC DS1307”

разделы: I2C , RTC , AVR , дата: 27 сентября 2015г

После UART, реализация TWI модуля на AVR кажется довольно корявой и без понимания I2C протокола будет не просто его освоить. Однако, если разобраться с “софтовой” эмуляцией протокола, то работа с TWI модулем уже не составит труда.

Не последне место в этом списке должно быть у официального аппнота: AVR315: Using the TWI module as I2C master

Если открыть руководство для ATmega8, на странице 156 раздел “Two-Wire Serial Interface”, то там даже будет примерный набросок программы для работы с TWI:

На модуле с DS1307 есть EEPROM AT24 на 36 кБайт. Здесь: “The TWI example project” есть демонстрационая программа, которая распечатывает содержимое EEPROM в консоль UART. Выглядит это как-то так:

Там только в начале исходника нужно поправить #define F_CPU в соответствии с реальной частотой чипа.

Протокол работы c RTC DS1307, прост. Там есть внутрений регистр – счетчик адреса, и оперативка на 64 байт. Отношение к часам имеют только байты с 0х00 по 0х07, остальные на можно использовать по своему усмотрению. Учитывая, что там автономное питание, их можно использовать вместо или в паре с EEPROM.

Итак, чтобы записать данные в DS1307 , нужно сперва послать адрес начальной ячейки, и затем данные по порядку. Счетчик при этом сам индексируется.При достижении счетчиком верхней границы, он сбрасывается в ноль. Т.е. он бегает по кругу.

Чтобы прочитать данные с определенной ячейки памяти RTC нужно сначала открыть I2C сессию на запись, послать адрес, закрыть сессию, и уже потом открывать сесию на чтение, и читать по порядку.

Официальное руководство по DS130764 x 8, Serial, I2C Real-Time Clock

Используя программу из этого поста в качестве шаблона, я добавил к ней поддержку TWI модуля, и сделал так, что бы она распечатывала через UART содержимое всех 64 байт пямяти RTC DS1307

#define F_CPU 16000000UL
#define LEN 32 #include
#include
#include
#include
#include #define START 0x08
#define REP_START 0x10
#define MT_DATA_ACK 0x28 #define MT_ADR_ACK 0x18
#define MT_ADR_NACK 0x20 #define MT_DATA_ACK 0x28
#define MT_DATA_NACK 0x30
#define MT_ARB_LOST 0x38 #define WRITE 0x00
#define READ 0x01 #define READ_END 0x01
#define READ_NOEND 0x00 #define RTC 0xD0 char buffer[LEN];
register unsigned char IT asm(“r16”);
volatile unsigned char done;
volatile unsigned char IDX; static inline void clearStr(char* str)
{ for(IT=0;IT= LEN) { IDX=0; done=1; }
} static void blink13(uint8_t count)
{ PORTB |= (1

Источник: http://www.count-zero.ru/2015/ds1307_twi/

Software I2C Library

The mikroC PRO for AVR provides routines for implementing Software I²C communication. These routines are hardware independent and can be used with any MCU. The Software I²C library enables you to use MCU as Master in I²C communication. Multi-master mode is not supported.

  Important :

  • This library implements time-based activities, so interrupts need to be disabled when using Software I²C.
  • All I²C Library functions are blocking-call functions (they are waiting for I²C clock line to become logical one).
  • The pins used for the Software I²C communication should be connected to the pull-up resistors. Turning off the LEDs connected to these pins may also be required.
  • Every Software I²C library routine has its own counterpart in Hardware I²C library, except I2C_Repeated_Start. Soft_I2C_Start is used instead of I2C_Repeated_Start.
  • Working clock frequency of the Software I²C is 20kHz.

External dependencies of Software I²C Library

The following variables must be defined in all projects using Software I²C Library:Description :Example :
extern sbit Soft_I2C_Scl_Output; Soft I²C Clock output line.

sbit Soft_I2C_Scl_Output at PORTC0_bit;
extern sbit Soft_I2C_Sda_Output; Soft I²C Data output line. sbit Soft_I2C_Sda_Output at PORTC1_bit;
extern sbit Soft_I2C_Scl_Input; Soft I²C Clock input line.

sbit Soft_I2C_Scl_Input at PINC0_bit;
extern sbit Soft_I2C_Sda_Input; Soft I²C Data input line. sbit Soft_I2C_Sda_Input at PINC1_bit;
extern sbit Soft_I2C_Scl_Direction; Direction of the Soft I²C Clock pin.

sbit Soft_I2C_Scl_Direction at DDC0_bit;
extern sbit Soft_I2C_Sda_Direction; Direction of the Soft I²C Data pin. sbit Soft_I2C_Sda_Direction at DDC1_bit;

Library Routines

Soft_I2C_Init

PrototypeReturnsDescriptionRequiresExample

void Soft_I2C_Init();

Nothing.

Configures the software I²C module.

Global variables :

  • Soft_I2C_Scl_Output: Soft I²C clock output line
  • Soft_I2C_Sda_Output: Soft I²C data output line
  • Soft_I2C_Scl_Input: Soft I²C clock input line
  • Soft_I2C_Sda_Input: Soft I²C data input line
  • Soft_I2C_Scl_Direction: Direction of the Soft I²C clock pin
  • Soft_I2C_Sda_Direction: Direction of the Soft I²C data pin

must be defined before using this function.

// Software I2C connections sbit Soft_I2C_Scl_Output at PORTC0_bit; sbit Soft_I2C_Sda_Output at PORTC1_bit; sbit Soft_I2C_Scl_Input at PINC0_bit; sbit Soft_I2C_Sda_Input at PINC1_bit; sbit Soft_I2C_Scl_Direction at DDC0_bit; sbit Soft_I2C_Sda_Direction at DDC1_bit; // End Software I2C connections … Soft_I2C_Init();

Soft_I2C_Start

PrototypeReturnsDescriptionRequiresExample

void Soft_I2C_Start(void);

Nothing.

Determines if the I²C bus is free and issues START signal.

Software I²C must be configured before using this function. See Soft_I2C_Init routine.

// Issue START signal Soft_I2C_Start();

Soft_I2C_Read

PrototypeReturnsDescriptionRequiresExample

unsigned short Soft_I2C_Read(unsigned int ack);

One byte from the Slave.

Reads one byte from the slave.

Parameters :

  • ack: acknowledge signal parameter. If the ack==0 not acknowledge signal will be sent after reading, otherwise the acknowledge signal will be sent.

Soft I²C must be configured before using this function. See Soft_I2C_Init routine.

Also, START signal needs to be issued in order to use this function. See Soft_I2C_Start routine.

unsigned short take; … // Read data and send the not_acknowledge signal take = Soft_I2C_Read(0);

Soft_I2C_Write

PrototypeReturnsDescriptionRequiresExample

unsigned short Soft_I2C_Write(unsigned short data_);

  • 0 if there were no errors.
  • 1 if write collision was detected on the I²C bus.

Sends data byte via the I²C bus.

Parameters :

Soft I²C must be configured before using this function. See Soft_I2C_Init routine.

Also, START signal needs to be issued in order to use this function. See Soft_I2C_Start routine.

unsigned short data_, error; error = Soft_I2C_Write(data_); error = Soft_I2C_Write(0xA3);

Soft_I2C_Stop

PrototypeReturnsDescriptionRequiresExample

void Soft_I2C_Stop(void);

Nothing.

Issues STOP signal.

Soft I²C must be configured before using this function. See Soft_I2C_Init routine.

// Issue STOP signal Soft_I2C_Stop();

Soft_I2C_Break

PrototypeReturnsDescriptionRequiresExample

void Soft_I2C_Break(void);

Nothing.

All Software I²C Library functions can block the program flow (see note at the top of this page). Calling this routine from interrupt will unblock the program execution. This mechanism is similar to WDT.

  Note : Interrupts should be disabled before using Software I²C routines again (see note at the top of this page).

Nothing.
// Software I2C connections sbit Soft_I2C_Scl_Output at PORTC0_bit; sbit Soft_I2C_Sda_Output at PORTC1_bit; sbit Soft_I2C_Scl_Input at PINC0_bit; sbit Soft_I2C_Sda_Input at PINC1_bit; sbit Soft_I2C_Scl_Direction at DDC0_bit; sbit Soft_I2C_Sda_Direction at DDC1_bit; // End Software I2C connections char counter = 0; void Timer0Overflow_ISR() org 0x12 { if (counter >= 20) { Soft_I2C_Break(); counter = 0; // reset counter } else counter++; // increment counter } void main() { TOIE0_bit = 1; // Timer0 overflow interrupt enable TCCR0_bit = 5; // Start timer with 1024 prescaler SREG_I_bit = 0; // Interrupt disable// try Soft_I2C_Init with blocking prevention mechanism SREG_I_bit = 1; // Interrupt enable Soft_I2C_Init(); SREG_I_bit = 0; // Interrupt disable … }

Library Example

The example demonstrates Software I²C Library routines usage. The AVR MCU is connected (SCL, SDA pins) to PCF8583 RTC (real-time clock). Program reads date and time are read from the RTC and prints it on Lcd.

Copy Code To Clipboard

char seconds, minutes, hours, day, month, year; // Global date/time variables // Software I2C connections sbit Soft_I2C_Scl_Output at PORTC0_bit; sbit Soft_I2C_Sda_Output at PORTC1_bit; sbit Soft_I2C_Scl_Input at PINC0_bit; sbit Soft_I2C_Sda_Input at PINC1_bit; sbit Soft_I2C_Scl_Direction at DDC0_bit; sbit Soft_I2C_Sda_Direction at DDC1_bit; // End Software I2C connections // LCD module connections sbit LCD_RS at PORTD2_bit; sbit LCD_EN at PORTD3_bit; sbit LCD_D4 at PORTD4_bit; sbit LCD_D5 at PORTD5_bit; sbit LCD_D6 at PORTD6_bit; sbit LCD_D7 at PORTD7_bit; sbit LCD_RS_Direction at DDD2_bit; sbit LCD_EN_Direction at DDD3_bit; sbit LCD_D4_Direction at DDD4_bit; sbit LCD_D5_Direction at DDD5_bit; sbit LCD_D6_Direction at DDD6_bit; sbit LCD_D7_Direction at DDD7_bit; // End LCD module connections //——————— Reads time and date information from RTC (PCF8583) void Read_Time() { Soft_I2C_Start(); // Issue start signal Soft_I2C_Write(0xA0); // Address PCF8583, see PCF8583 datasheet Soft_I2C_Write(2); // Start from address 2 Soft_I2C_Start(); // Issue repeated start signal Soft_I2C_Write(0xA1); // Address PCF8583 for reading R/W=1 seconds = Soft_I2C_Read(1); // Read seconds byte minutes = Soft_I2C_Read(1); // Read minutes byte hours = Soft_I2C_Read(1); // Read hours byte day = Soft_I2C_Read(1); // Read year/day byte month = Soft_I2C_Read(0); // Read weekday/month byte Soft_I2C_Stop(); // Issue stop signal } //——————– Formats date and time void Transform_Time() { seconds = ((seconds & 0xF0) >> 4)*10 + (seconds & 0x0F); // Transform seconds minutes = ((minutes & 0xF0) >> 4)*10 + (minutes & 0x0F); // Transform months hours = ((hours & 0xF0) >> 4)*10 + (hours & 0x0F); // Transform hours year = (day & 0xC0) >> 6; // Transform year day = ((day & 0x30) >> 4)*10 + (day & 0x0F); // Transform day month = ((month & 0x10) >> 4)*10 + (month & 0x0F); // Transform month } //——————– Output values to LCD void Display_Time() { Lcd_Chr(1, 6, (day / 10) + 48); // Print tens digit of day variable Lcd_Chr(1, 7, (day % 10) + 48); // Print oness digit of day variable Lcd_Chr(1, 9, (month / 10) + 48); Lcd_Chr(1,10, (month % 10) + 48); Lcd_Chr(1,15, year + 56); // Print year vaiable + 8 (start from year 2008) Lcd_Chr(2, 6, (hours / 10) + 48); Lcd_Chr(2, 7, (hours % 10) + 48); Lcd_Chr(2, 9, (minutes / 10) + 48); Lcd_Chr(2,10, (minutes % 10) + 48); Lcd_Chr(2,12, (seconds / 10) + 48); Lcd_Chr(2,13, (seconds % 10) + 48); } //—————— Performs project-wide init void Init_Main() { Soft_I2C_Init(); // Initialize Soft I2C communication Lcd_Init(); // Initialize LCD Lcd_Cmd(_LCD_CLEAR); // Clear LCD display Lcd_Cmd(_LCD_CURSOR_OFF); // Turn cursor off Lcd_Out(1,1,”Date:”); // Prepare and output static text on LCD Lcd_Chr(1,8,':'); Lcd_Chr(1,11,':'); Lcd_Out(2,1,”Time:”); Lcd_Chr(2,8,':'); Lcd_Chr(2,11,':'); Lcd_Out(1,12,”200″); } //—————– Main procedure void main() { Init_Main(); // Perform initialization while (1) { // Endless loop Read_Time(); // Read time from RTC(PCF8583) Transform_Time(); // Format date and time Display_Time(); // Prepare and display on LCD Delay_ms(1000); // Wait 1 second } }Copyright (c) 2002-2012 mikroElektronika. All rights reserved.
What do you think about this topic ? Send us feedback!Want more examples and libraries? 
Find them on

Источник: http://download.mikroe.com/documents/compilers/mikroc/avr/help/software_i2c_library.htm

Ссылка на основную публикацию
Adblock
detector
",css:{backgroundColor:"#000",opacity:.6}},container:{block:void 0,tpl:"
"},wrap:void 0,body:void 0,errors:{tpl:"
",autoclose_delay:2e3,ajax_unsuccessful_load:"Error"},openEffect:{type:"fade",speed:400},closeEffect:{type:"fade",speed:400},beforeOpen:n.noop,afterOpen:n.noop,beforeClose:n.noop,afterClose:n.noop,afterLoading:n.noop,afterLoadingOnShow:n.noop,errorLoading:n.noop},o=0,p=n([]),h={isEventOut:function(a,b){var c=!0;return n(a).each(function(){n(b.target).get(0)==n(this).get(0)&&(c=!1),0==n(b.target).closest("HTML",n(this).get(0)).length&&(c=!1)}),c}},q={getParentEl:function(a){var b=n(a);return b.data("arcticmodal")?b:(b=n(a).closest(".arcticmodal-container").data("arcticmodalParentEl"),!!b&&b)},transition:function(a,b,c,d){switch(d=null==d?n.noop:d,c.type){case"fade":"show"==b?a.fadeIn(c.speed,d):a.fadeOut(c.speed,d);break;case"none":"show"==b?a.show():a.hide(),d();}},prepare_body:function(a,b){n(".arcticmodal-close",a.body).unbind("click.arcticmodal").bind("click.arcticmodal",function(){return b.arcticmodal("close"),!1})},init_el:function(d,a){var b=d.data("arcticmodal");if(!b){if(b=a,o++,b.modalID=o,b.overlay.block=n(b.overlay.tpl),b.overlay.block.css(b.overlay.css),b.container.block=n(b.container.tpl),b.body=n(".arcticmodal-container_i2",b.container.block),a.clone?b.body.html(d.clone(!0)):(d.before("
"),b.body.html(d)),q.prepare_body(b,d),b.closeOnOverlayClick&&b.overlay.block.add(b.container.block).click(function(a){h.isEventOut(n(">*",b.body),a)&&d.arcticmodal("close")}),b.container.block.data("arcticmodalParentEl",d),d.data("arcticmodal",b),p=n.merge(p,d),n.proxy(e.show,d)(),"html"==b.type)return d;if(null!=b.ajax.beforeSend){var c=b.ajax.beforeSend;delete b.ajax.beforeSend}if(null!=b.ajax.success){var f=b.ajax.success;delete b.ajax.success}if(null!=b.ajax.error){var g=b.ajax.error;delete b.ajax.error}var j=n.extend(!0,{url:b.url,beforeSend:function(){null==c?b.body.html("
"):c(b,d)},success:function(c){d.trigger("afterLoading"),b.afterLoading(b,d,c),null==f?b.body.html(c):f(b,d,c),q.prepare_body(b,d),d.trigger("afterLoadingOnShow"),b.afterLoadingOnShow(b,d,c)},error:function(){d.trigger("errorLoading"),b.errorLoading(b,d),null==g?(b.body.html(b.errors.tpl),n(".arcticmodal-error",b.body).html(b.errors.ajax_unsuccessful_load),n(".arcticmodal-close",b.body).click(function(){return d.arcticmodal("close"),!1}),b.errors.autoclose_delay&&setTimeout(function(){d.arcticmodal("close")},b.errors.autoclose_delay)):g(b,d)}},b.ajax);b.ajax_request=n.ajax(j),d.data("arcticmodal",b)}},init:function(b){if(b=n.extend(!0,{},a,b),!n.isFunction(this))return this.each(function(){q.init_el(n(this),n.extend(!0,{},b))});if(null==b)return void n.error("jquery.arcticmodal: Uncorrect parameters");if(""==b.type)return void n.error("jquery.arcticmodal: Don't set parameter \"type\"");switch(b.type){case"html":if(""==b.content)return void n.error("jquery.arcticmodal: Don't set parameter \"content\"");var e=b.content;return b.content="",q.init_el(n(e),b);case"ajax":return""==b.url?void n.error("jquery.arcticmodal: Don't set parameter \"url\""):q.init_el(n("
"),b);}}},e={show:function(){var a=q.getParentEl(this);if(!1===a)return void n.error("jquery.arcticmodal: Uncorrect call");var b=a.data("arcticmodal");if(b.overlay.block.hide(),b.container.block.hide(),n("BODY").append(b.overlay.block),n("BODY").append(b.container.block),b.beforeOpen(b,a),a.trigger("beforeOpen"),"hidden"!=b.wrap.css("overflow")){b.wrap.data("arcticmodalOverflow",b.wrap.css("overflow"));var c=b.wrap.outerWidth(!0);b.wrap.css("overflow","hidden");var d=b.wrap.outerWidth(!0);d!=c&&b.wrap.css("marginRight",d-c+"px")}return p.not(a).each(function(){var a=n(this).data("arcticmodal");a.overlay.block.hide()}),q.transition(b.overlay.block,"show",1*")),b.overlay.block.remove(),b.container.block.remove(),a.data("arcticmodal",null),n(".arcticmodal-container").length||(b.wrap.data("arcticmodalOverflow")&&b.wrap.css("overflow",b.wrap.data("arcticmodalOverflow")),b.wrap.css("marginRight",0))}),"ajax"==b.type&&b.ajax_request.abort(),p=p.not(a))})},setDefault:function(b){n.extend(!0,a,b)}};n(function(){a.wrap=n(document.all&&!document.querySelector?"html":"body")}),n(document).bind("keyup.arcticmodal",function(d){var a=p.last();if(a.length){var b=a.data("arcticmodal");b.closeOnEsc&&27===d.keyCode&&a.arcticmodal("close")}}),n.arcticmodal=n.fn.arcticmodal=function(a){return e[a]?e[a].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof a&&a?void n.error("jquery.arcticmodal: Method "+a+" does not exist"):q.init.apply(this,arguments)}}(jQuery)}var debugMode="undefined"!=typeof debugFlatPM&&debugFlatPM,duplicateMode="undefined"!=typeof duplicateFlatPM&&duplicateFlatPM,countMode="undefined"!=typeof countFlatPM&&countFlatPM;document["wri"+"te"]=function(a){let b=document.createElement("div");jQuery(document.currentScript).after(b),flatPM_setHTML(b,a),jQuery(b).contents().unwrap()};function flatPM_sticky(c,d,e=0){function f(){if(null==a){let b=getComputedStyle(g,""),c="";for(let a=0;a=b.top-h?b.top-h{const d=c.split("=");return d[0]===a?decodeURIComponent(d[1]):b},""),c=""==b?void 0:b;return c}function flatPM_testCookie(){let a="test_56445";try{return localStorage.setItem(a,a),localStorage.removeItem(a),!0}catch(a){return!1}}function flatPM_grep(a,b,c){return jQuery.grep(a,(a,d)=>c?d==b:0==(d+1)%b)}function flatPM_random(a,b){return Math.floor(Math.random()*(b-a+1))+a}