Предлагаю по аналогии с viewtopic.php?f=20&t=64022 скидывать наработки сюда. Блин, нужна чья-то помощь. Есть у кого код для Иара? А то свой написал, проверил 100500 раз, а ни на один байт ACK не могу получить. Делал в соответствии со спецификацией, проверял.
_________________ Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
//*** Формирование старт-бита // <-- если 0 - линия занята, иначе - передан старт unsigned char i2c_start (void) { unsigned char Res = 1;
CBI(I2C_DDR, I2C_SDA); if (GBI(I2C_PIN, I2C_SDA)) // проверка на ошибку линии { // устанавливаем лог 1 на линии SCL за счет подтягивающих резисторов CBI(I2C_DDR, I2C_SCL); CBI(I2C_PORT, I2C_SCL); delay_us(I2C_DELAY);
// устанавливаем лог 0 на линии SDA за счет защелки SBI(I2C_DDR, I2C_SDA); CBI(I2C_PORT, I2C_SDA); delay_us(I2C_DELAY);
// устанавливаем лог 0 на линии SCL за счет защелки SBI(I2C_DDR, I2C_SCL); delay_us(I2C_DELAY); } else Res = 0;
return Res; }
//*** Формирование стоп-бита void i2c_stop (void) { // устанавливаем лог 0 на линии SDA за счет подтягивающих резисторов SBI(I2C_DDR, I2C_SDA); CBI(I2C_PORT, I2C_SDA); delay_us(I2C_DELAY);
// устанавливаем лог 1 на линии SCL за счет защелки SBI(I2C_DDR, I2C_SCL); CBI(I2C_PORT, I2C_SCL); delay_us(I2C_DELAY);
// устанавливаем лог 1 на линии SDA за счет защелки CBI(I2C_DDR, I2C_SDA); delay_us(I2C_DELAY); } unsigned char i2c_write_byte(u8 Data) { unsigned char Res = 0;
CBI(I2C_PORT, I2C_SCL); CBI(I2C_PORT, I2C_SDA);
for (u8 i = 0; i < 8; i++) { SBI(I2C_DDR, I2C_SDA); if (Data & 0x80) CBI(I2C_DDR, I2C_SDA);
delay_us(I2C_DELAY);
// устанавливаем лог 1 на линии SCL за счет подтягивающих резисторов CBI(I2C_DDR, I2C_SCL); delay_us(I2C_DELAY);
// устанавливаем лог 0 на линии SCL за счет подтягивающих резисторов SBI(I2C_DDR, I2C_SCL); delay_us(I2C_DELAY); Data <<= 1; }
CBI(I2C_DDR, I2C_SDA); delay_us(I2C_DELAY);
// устанавливаем лог 1 на линии SCL за счет подтягивающих резисторов CBI(I2C_DDR, I2C_SCL); delay_us(I2C_DELAY);
Res = GBI(I2C_PIN, I2C_SDA);
// устанавливаем лог 0 на линии SCL за счет подтягивающих резисторов SBI(I2C_DDR, I2C_SCL); delay_us(I2C_DELAY);
SBI(I2C_DDR, I2C_SDA); delay_us(I2C_DELAY);
return Res; }
//*** Чтение байта из I2C // --> Ack > 0 - генерировать, иначе - нет // <-- принятые данные unsigned char i2c_read_byte(u8 Ack) { unsigned char Res=0;
//####################################################################################################################### //# //# ФУНКЦИИ РАБОТЫ С ЧАСАМИ DS1307 //# //#######################################################################################################################
//ФУНКЦИЯ ЧТЕНИЯ БЛОКА ДАННЫХ ИЗ МИКРОСХЕМЫ ЧАСОВ DS1307 //чтение происходит в глобальный массив ClockData[7] //последовательность данных - [0]секунды, [1]минуты, [2]часы, [3]день, [4]дата, [5]месяц, [6]год void IICClockReadData (void) { IICStart(); IICByteWrite (0xD0);//запись данных в DS1307 IICByteWrite (0x00);//сбросить указатель адреса DS1307 на 0
IICStart(); IICByteWrite (0xD1);//команда на чтение данных
char temp = IICByteRead (0);//читсем секунды с выдачей подтверждения (0) if (temp != ClockData[0]){ ClockData[0]= temp;
char* pClockData =&ClockData[1];//указатель на данные часов for (char i = 0; i<5; i++) *pClockData++= IICByteRead (0);//пишем, минуты, часы, день, дата, месяц (с выдачей подтверждением) *pClockData = IICByteRead (1);//пишем год (без подтверждения) IICStop(); }
//ФУНКЦИЯ ЗАПИСИ БЛОКА ДАННЫХ В МИКРОСХЕМУ ЧАСОВ DS1307 //запись происходит из глобального массива ClockData[7] //последовательность данных - [0]секунды, [1]минуты, [2]часы, [3]день, [4]дата, [5]месяц, [6]год void IICClockWriteData (void) { IICStart(); IICByteWrite (0xD0);//запись данных в DS1307 IICByteWrite (0x00);//сбросить указатель адреса DS1307 на 0
for (unsigned char i = 0; i<7; i++) IICByteWrite (ClockData [i]);//пишем, секунды, минуты, часы, день, дата, месяц, год
IICStop(); }
А вот софтовая реализация I2C. Заморочек меньше чем с аппаратной, да и цеплять можно на любые выводы контроллераСпойлер
Код:
#define IICDDR DDRC /*порт управления I2C*/ #define IICPORT PORTC /*порт вывода данных на линию I2C*/ #define IICPIN PINC /*порт ввода данных с линий I2C*/ #define IICData (1<<4) /*линия DATA*/ #define IICClc (1<<5) /*линия CLC*/
//ФУНКЦИЯ ФОРМИРОВАНИЯ СОСТОЯНИЯ START ПО ИНТЕРФЕЙСУ IIC void IICStart (void) { IICDDR &=~(IICData | IICClc); Delay2Mks();
IICDDR |= IICData;//подтяжка data к нулю Delay2Mks();
IICDDR |= IICClc;//подтяжка clc к нулю Delay2Mks(); }
//ФУНКЦИЯ ФОРМИРОВАНИЯ СОСТОЯНИЯ STOP ПО ИНТЕРФЕЙСУ IIC void IICStop (void) { IICDDR |=(IICData | IICClc); Delay2Mks();
IICDDR &=~IICClc;//подтяжка data к нулю Delay2Mks();
IICDDR &=~IICData;//подтяжка clc к нулю Delay2Mks(); }
//ФУНКЦИЯ ЗАПИСИ БАЙТА ПО ИНТЕРФЕЙСУ IIC //АРГУМЕНТ - байт данных для вывода по IIC //ЗНАЧЕНИЕ - флаг подтверждения 0 (есть подтверждение) или 1 (нет подтверждения) char IICByteWrite (char byte) { for (char i = 0; i<8; i++) byte = IICBit (byte);
//ФУНКЦИЯ ЧТЕНИЯ БАЙТА ПО ИНТЕРФЕЙСУ IIC //АРГУМЕНТ - значение бита подтверждения (0 - есть подтверждение, 1 - нет подтверждения) //ЗНАЧЕНИЕ - принятый байт char IICByteRead (char bit) { char byte = 0xFF; for (char i = 0; i<8; i++) byte = IICBit (byte);
bit <<= 7; IICBit (bit);//передать значение бита подтверждения return byte;//возвращаем принятый байт }
//ФУНКЦИЯ ЗАПИСИ\ЧТЕНИЯ БИТА ПО ИНТЕРФЕЙСУ IIC //выводится значение старшего бита аргумента //принятый бит возвращается в младшем бите предварительно сдвинутого влево аргумента char IICBit (char byte) { if (byte & 0x80)//выводимый бит IICDDR &=~IICData;//вывод 1 на линию данных else IICDDR |= IICData;//вывод 0 на линию данных Delay2Mks();
IICDDR &=~IICClc;//старт строб импульса while (!(IICPIN & IICClc)){}//ожидание формирования строба Delay2Mks();
Еще требуется инициализация микросхемы. rtc_init(0, 0, 0); // при первом запуске DS1307 его регистры не установлены (ручками установим их - биты: rs=0, sqwe=0, out=0) Кажется rs обязательно надо в 0 установить. Давно разбирался. Теперь пользуюсь готовым куском и не парюсь. Но все в CV.
Pika4u - по-моему у Вас ошибка в среднем блоке функции i2c_stop() и комментарии там везде неправильные. Если это не поможет, дайте код обрашения к DS1307 с указанием ее I2C адреса (может он неправильный в программе?) Получаете-ли ACK после отсылки адреса по I2C? Если ДА, то на каком этапе коммуникации с DS получаете NACK?
Итак, добил я все же эту ds1307,посадил ей 3 вывод(батарея) на землю и вышеизложенный код заработал. Но вот в чем трабла-смотрю на дисплее результаты отправки байтов-случайным образом, бывает, ACK не приходит.В случае получения NACK, нужно байт отправить ещё раз?
_________________ Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
Как все запущено оказалось... А полазить по сайтам производителей часиков и почитать рекомендации по применению ? Да и правила по обычным микрухам пока не отменялись! Вот на всяк случай манька по PCFам - типовые решения все одинаковые:
А вот так выглядит мое решение макетки часиков на DS1307 как отдельного узла (под схему с акумулятором или ионистором - при литиевой батарее цепочка заряда не ставится!):
Спасибо огромное) просто у меня сейчас отладочная плата на меге8(сделал сам, все по минимуму, разводка питания и все выводы выведены на штыри. Так вот, на плате мега8, дс1307, дс18б20, и жк-дисплей. Все питается от программатора(юсб,5В). Я думал, что конденсатора меги, керамики 18б20 и конденсатора в программаторе хватит... Не хватило)
_________________ Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения