Предлагаю по аналогии с viewtopic.php?f=20&t=64022 скидывать наработки сюда. Блин, нужна чья-то помощь. Есть у кого код для Иара? А то свой написал, проверил 100500 раз, а ни на один байт ACK не могу получить. Делал в соответствии со спецификацией, проверял.
_________________ Steve Jobs. 1955-2011. Мы помним, как ты преобразовал наш мир....
//*** Формирование старт-бита // <-- если 0 - линия занята, иначе - передан старт unsignedchari2c_start(void) { unsignedchar 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; }
//*** Формирование стоп-бита voidi2c_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); } unsignedchari2c_write_byte(u8 Data) { unsignedchar 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 - генерировать, иначе - нет // <-- принятые данные unsignedchari2c_read_byte(u8 Ack) { unsignedchar Res=0;
//####################################################################################################################### //# //# ФУНКЦИИ РАБОТЫ С ЧАСАМИ DS1307 //# //#######################################################################################################################
//ФУНКЦИЯ ЧТЕНИЯ БЛОКА ДАННЫХ ИЗ МИКРОСХЕМЫ ЧАСОВ DS1307 //чтение происходит в глобальный массив ClockData[7] //последовательность данных - [0]секунды, [1]минуты, [2]часы, [3]день, [4]дата, [5]месяц, [6]год voidIICClockReadData(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]год voidIICClockWriteData(void) { IICStart(); IICByteWrite (0xD0); //запись данных в DS1307 IICByteWrite (0x00); //сбросить указатель адреса DS1307 на 0
for (unsignedchar 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 voidIICStart (void) { IICDDR &= ~(IICData | IICClc); Delay2Mks();
IICDDR |= IICData; //подтяжка data к нулю Delay2Mks();
IICDDR |= IICClc; //подтяжка clc к нулю Delay2Mks(); }
//ФУНКЦИЯ ФОРМИРОВАНИЯ СОСТОЯНИЯ STOP ПО ИНТЕРФЕЙСУ IIC voidIICStop (void) { IICDDR |= (IICData | IICClc); Delay2Mks();
IICDDR &= ~IICClc; //подтяжка data к нулю Delay2Mks();
IICDDR &= ~IICData; //подтяжка clc к нулю Delay2Mks(); }
//ФУНКЦИЯ ЗАПИСИ БАЙТА ПО ИНТЕРФЕЙСУ IIC //АРГУМЕНТ - байт данных для вывода по IIC //ЗНАЧЕНИЕ - флаг подтверждения 0 (есть подтверждение) или 1 (нет подтверждения) charIICByteWrite (charbyte) { for (char i = 0; i<8; i++) byte = IICBit (byte);
//ФУНКЦИЯ ЧТЕНИЯ БАЙТА ПО ИНТЕРФЕЙСУ IIC //АРГУМЕНТ - значение бита подтверждения (0 - есть подтверждение, 1 - нет подтверждения) //ЗНАЧЕНИЕ - принятый байт charIICByteRead (char bit) { charbyte = 0xFF; for (char i = 0; i<8; i++) byte = IICBit (byte);
bit <<= 7; IICBit (bit); //передать значение бита подтверждения returnbyte; //возвращаем принятый байт }
//ФУНКЦИЯ ЗАПИСИ\ЧТЕНИЯ БИТА ПО ИНТЕРФЕЙСУ IIC //выводится значение старшего бита аргумента //принятый бит возвращается в младшем бите предварительно сдвинутого влево аргумента charIICBit (charbyte) { 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. Мы помним, как ты преобразовал наш мир....
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 6
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения