Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DS1338 + XMEGA
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
Pavel_Bor
В даташите на эти часики указаны 2 режима работы: Fast mode(400КГц), Standart mode(100КГц).
В меге инициализирован RC на 32Мгц.
Как между собой связать скорости. или какое время нужно давать при задержке.

При коде следующего вида никаких изменений не происходит..

CODE
void rtc_init()
{
RTC_DATA_DIR_SET;
RTC_DATA_SET;
RTC_SCL_UP;
delay_us(1);
}

void rtc_start()
{
RTC_DATA_CLR;
delay_us(1);
RTC_SCL_DOWN;
delay_us(1);
}

void rtc_stop()
{

RTC_SCL_UP;
delay_ms(1);
RTC_DATA_DIR_SET;
RTC_DATA_SET;
delay_ms(1);
}

void rtc_write (unsigned char buffer)
{
unsigned char MASK;
RTC_DATA_DIR_SET;
for(i=8;i>=0;--i)
{
if(buffer&&MASK )
RTC_DATA_SET;
else
RTC_DATA_CLR;
RTC_SCL_UP;
delay_ms(1);
RTC_SCL_DOWN;
delay_ms(1);
MASK>>1;
}

RTC_SCL_UP;
delay_ms(1);
RTC_SCL_DOWN;
delay_ms(1);
}

unsigned char read_rtc()
{
unsigned char buffer=0;

RTC_DATA_DIR_CLR;
for(i=8;i>=0;--i)
{
buffer|=((buffer<<1)||(PORTE.IN&PIN3_bm));
RTC_SCL_UP;
delay_ms(1);
RTC_SCL_DOWN;
delay_ms(1);
}
return buffer;
}

void RTC_ACKNOWLEGDGE_0()
{
RTC_DATA_DIR_SET;
RTC_DATA_SET;
delay_ms(1);
RTC_SCL_UP;
delay_ms(1);
RTC_SCL_DOWN;
delay_ms(1);
}

void RTC_ACKNOWLEGDGE_1()
{
RTC_DATA_DIR_SET;
RTC_DATA_CLR;
delay_ms(1);
RTC_SCL_UP;
delay_ms(1);
RTC_SCL_DOWN;
delay_ms(1);
}
alexeyv
Код
void rtc_write (unsigned char buffer)
{
    unsigned char MASK;
    RTC_DATA_DIR_SET;
    for(i=8;i>=0;--i)
                  {
                     ...
                   MASK>>1;
                     ....
                  }
.............
.............
}


1. Где первоначальное задание значения MASK ?? (по умолчанию=0)
2. MASK>>1; - переменная сдвигается (ноль сдвинуть влево!!) , но никуда не записывается, надо "MASK>>=1;"

Код
unsigned char read_rtc()
{
    unsigned char buffer=0;
    RTC_DATA_DIR_CLR;
    for(i=8;i>=0;--i)
   {
        buffer|=((buffer<<1)||(PORTE.IN&PIN3_bm));
        RTC_SCL_UP;
        delay_ms(1);      
        RTC_SCL_DOWN;
        delay_ms(1);    
    }    
    return buffer;
}


Значение с шины надо считывать ПОСЛЕ подачи тактового сигнала!


И вообще, где код вызывающий эти функции, сами они никогда не исполнятся?
Pavel_Bor
Цитата
Значение с шины надо считывать ПОСЛЕ подачи тактового сигнала!

Это пропустил.

Цитата
unsigned char MASK;
ошибка при копировании. unsigned char MASK=0х80

Цитата
И вообще, где код вызывающий эти функции, сами они никогда не исполнятся?



Собственно код
Код
    rtc_start();                           //старт
    rtc_write (DS1338W);           // адрес устройства, + запись. DS1338W=0xD0
    rtc_write (SecondsReg);       // Регистр секунд
    rtc_write (0x7f);
    rtc_write (0x3f);
    rtc_write (0xff);  
    rtc_write (0xff);
    rtc_write (0xff);
    rtc_write (0xff);
    rtc_write (0xff);
    rtc_stop();

//При чтении
rtc_start();
    rtc_write (DS1338R);            // адрес устройства, + чтение DS1338R=0xD1
    RTC_ACKNOWLEGDGE_1();
    rtc_write (SecondsReg);
    RTC_ACKNOWLEGDGE_1();  
    rtcTime.seconds=read_rtc();
    RTC_ACKNOWLEGDGE_1();
    rtcTime.minutes=read_rtc();  
    RTC_ACKNOWLEGDGE_1();  
    rtcTime.hours=read_rtc();
    RTC_ACKNOWLEGDGE_1();
    rtcTime.day=read_rtc();;
    RTC_ACKNOWLEGDGE_1();  
    rtcTime.date=read_rtc();
    RTC_ACKNOWLEGDGE_1();
    rtcTime.month=read_rtc();
    RTC_ACKNOWLEGDGE_1();
    rtcTime.year=read_rtc();
    RTC_ACKNOWLEGDGE_0();
    rtc_stop();
alexeyv
1. А это исправил?
Цитата
2. MASK>>1; - переменная сдвигается (ноль сдвинуть влево!!) , но никуда не записывается, надо "MASK>>=1;"


2. Посмотри осциллографом сигналы на шине, в частности наличие сигнала АСК от часов

3. Формат записи в регистры не правильный
Код
    rtc_write (SecondsReg);       // Регистр секунд
    rtc_write (0x7f);
    rtc_write (0x3f);
    rtc_write (0xff);  
    rtc_write (0xff);
    rtc_write (0xff);
    rtc_write (0xff);


Из даташита:
Нажмите для просмотра прикрепленного файла

то есть время/дата записывается в формате BCD

4. Общие замечания: имена макросов - прописными буквами, локальных переменных - строчными, глобальных переменных и функций - не полностью прописными

5. Где объявлены переменные i в rtc_write и read_rtc? По сути они должны быть локальные, а не глобальные
Pavel_Bor
Цитата
1. А это исправил?

написал по другому

if(buffer&&0x80)
....
buffer=buffer<<1;


Цитата
2. Посмотри осциллографом сигналы на шине, в частности наличие сигнала АСК от часов

Нету высокого уровня сигнала тактирования

Цитата
Формат записи в регистры не правильный

Знаю, но щас смысл передать хоть что-то

Цитата
4. Общие замечания: имена макросов - прописными буквами, локальных переменных - строчными, глобальных переменных и функций - не полностью прописными

кто как привык..

Цитата
5. Где объявлены переменные i в rtc_write и read_rtc? По сути они должны быть локальные, а не глобальные

Перевел в локальную. Была глобальная
alexeyv
1. А не забыл в rtc_init что-то типа RTC_SCL_DIR_SET; ??

2. Не правильно!!

Цитата
написал по другому

if(buffer&&0x80)


Это у тебя логическое выражение, а тебе надо битовое, вместо "&&" надо использовать "&"

3.
Цитата
кто как привык..


Судя по коду, ты еще не привык. Так что привыкай использовать принятые соглашения. Почитай книжку Ален И. Голуб. "ВЕРЕВКА ДОСТАТОЧНОЙ ДЛИНЫ, ЧТОБЫ…" Москва 2001г. Будет интересно.
Pavel_Bor
RTC_SCL_DIR_SET; в инициализации портов

Цитата
Это у тебя логическое выражение, а тебе надо битовое, вместо "&&" надо использовать "&"

"&"="*"
"&&"="и"

За книжку отдельное спасибо.
alexeyv
Цитата
"&"="*"
"&&"="и"


Неужели!!!!

Почитай еще книгу "Д. Ричи. Б. Керниган. Язык Си." Желательно 2-е издание.

"&" == порязрядное "И"
"&&" == логическое "И"

можешь проверить:
Код
0x02 & 0x04   == 0x00;
0x06 & 0x04   == 0x04;
0x02 && 0x04 == 0x01;
0x02 * 0x04   == 0x08;



Цитата
RTC_SCL_DIR_SET; в инициализации портов


В первом листинге не было!!!
Pavel_Bor
Цитата
В первом листинге не было!!!


я в листинг не включал.
alexeyv
Цитата
я в листинг не включал.


Так может ошибки в тех местах, которых нет в листинге? Весь код относящийся к одному определенному объекту нужно держать в одном месте, а не размазывать по всей программе
Pavel_Bor
Цитата(alexeyv @ Jul 7 2011, 12:01) *
Так может ошибки в тех местах, которых нет в листинге? Весь код относящийся к одному определенному объекту нужно держать в одном месте, а не размазывать по всей программе


Есть первый шаг. Получил ответ от часиков в виде данных: 248 из все регистров. (я так понимаю что это 0xff или пустое место памяти)
alexeyv
Поздравляю!
Только 248=0xF8, а 0xFF=255.
Pavel_Bor
Цитата(alexeyv @ Jul 7 2011, 12:17) *
Только 248=0xF8, а 0xFF=255.

))
Это пустое место?

по поводу Acknowledge.
При записи между байтами необходимо ждать 0 в DATA
А при чтении отправлять?
alexeyv
В функции rtc_write после цикла выставления байта на шину, необходимо выставить данные=1, для того, что бы после дополнительного клока проанализировать принятый от часов бит АСК

Цитата
А при чтении отправлять?


Да. Бит АСК всегда формирует приемник. При записи - это часы, при чтении - проц. При чтении последнего байта - формирование NACK
Pavel_Bor
Код

bool RTC_ACKW()
{
    RTC_DATA_DIR_CLR;          
    RTC_SCL_DOWN;
    delay_us(100);
    RTC_SCL_UP;
    while(PORTE.IN&PIN3_bm!=0);
    delay_us(100);      
    RTC_SCL_DOWN;
    delay_us(100);
    return 1;
              
}

void RTC_ACKR()
{
    RTC_DATA_DIR_SET;
    RTC_DATA_SET;
    delay_us(100);          
    RTC_SCL_UP;
    delay_us(100);          
    RTC_SCL_DOWN;
    delay_us(100);          
}


так пойдет?
alexeyv
функцию контроля АСК проще сделать не отдельно, а в rtc_write - выдавать как результат работы функции
функцию посылки АСК проще сделать не отдельно, а в read_rtc - принимать как параметр 1= выдача АСК, 0 - выдача НАК

Маленький вопрос. Подтягивающие резисторы на линиях SCL и SDA есть?

Посмотри здесь

Оссобенно изучи пост №18.
Pavel_Bor
Цитата
Маленький вопрос. Подтягивающие резисторы на линиях SCL и SDA есть?

Подтяжек нет.



Цитата
Маленький вопрос. Подтягивающие резисторы на линиях SCL и SDA есть?

Подтяжек нет.

Цитата
В функции rtc_write после цикла выставления байта на шину, необходимо выставить данные=1, для того, что бы после дополнительного клока проанализировать принятый от часов бит АСК

Направление порта должно быть входом иначе не видно будет АСК. Но какой тогда смысл выставлять данные в 1?
alexeyv
Цитата
Направление порта должно быть входом иначе не видно будет АСК. Но какой тогда смысл выставлять данные в 1?


В смысле необходимо переключить порт (DDR_X) как вход, но перед этим записать в PORT_X единицу - этим включаются подтягивающие резисторы на порту

посмотри пост №18

в архиве - исходники
Pavel_Bor
Цитата(alexeyv @ Jul 7 2011, 14:09) *
В смысле необходимо переключить порт (DDR_X) как вход, но перед этим записать в PORT_X единицу - этим включаются подтягивающие резисторы на порту

посмотри пост №18

в архиве - исходники


а внешние подтягивающие резисторы в схеме нужны?
alexeyv
Цитата(Pavel_Bor @ Jul 7 2011, 16:21) *
а внешние подтягивающие резисторы в схеме нужны?


Подтягивающие резисторы обычно рекомендуют ставить.

У меня недавно был клюк. На линиях TWI, видать в целях экономии места на плате, не поставили подтяжку. При этом, при касании осциллографом любой из линий, процессор вылетал в неизвестно куда. Пришлось напаять резисторы и проблема исчезла. Нормально отлаженая программа также хорошо работала и без подтягивающих резисторов.
Но эта проблема была только на линиях аппаратного TWI. При программной реализации все работало и без подтяжек.
Pavel_Bor
Я так понимаю время задержки между тактами значения не имеет. Главное чтобы оно было больше минимального.
Когда программа получает АСК, пока SCL в "1" ACK никуда не денется до тех пор пока SCL не станет "0"?

Есть шаг №2. Читаю с регистров 0. Пошли часы)

Не получается записать в регистры новые значения.
текущий программа для записи:
Код
void i2c_tx_soft(unsigned char byte)
{
  
  unsigned char count;
  RTC_DATA_DIR_SET;
  if(i2c_error_soft)
    return;
  for(count=0;count<8;count++)
    {
      if(byte&0x80)
        RTC_DATA_SET;
      else
        RTC_DATA_CLR;
      RTC_SCL_UP;
      delay_ms(5);
      RTC_SCL_DOWN;
      delay_ms(5);
      byte<<=1;
    }
  RTC_DATA_DIR_CLR;
  RTC_SCL_UP;
  delay_ms(5);
  while(in_sda());
  delay_ms(5);
  RTC_SCL_DOWN;
  delay_ms(5);
  RTC_DATA_DIR_SET;
}


Вызов ее вот отсюда
Код
void rtc_set_time(unsigned char hours, unsigned char minutes, unsigned char seconds)
{
  i2c_start_soft();
  i2c_tx_soft(DS1338_ADDR|WR);
  i2c_tx_soft(0);
  i2c_tx_soft(dec2bcd(seconds));
  i2c_tx_soft(dec2bcd(minutes));
  i2c_tx_soft(dec2bcd(hours));

  i2c_stop_soft();
}


void rtc_set_date(unsigned char date, unsigned char month, unsigned int year)
{
  i2c_start_soft();
  i2c_tx_soft(DS1338_ADDR|WR);
  i2c_tx_soft(3);
  i2c_tx_soft(dec2bcd(rtcTime.day));
  i2c_tx_soft(dec2bcd(date));
  i2c_tx_soft(dec2bcd(month));
  i2c_tx_soft(dec2bcd(year));
  i2c_stop_soft();
}
alexeyv
Цитата
while(in_sda());


Во время подачи клока, по одному фронту производится выставление данных передатчиком(в данном случае мастером), а по другому фронту - считывание приемником ( в данном случае слейвом)!
Ждать до бесконечности появления нуля на шине SDA (ACK) НЕЛЬЗЯ, т.к. при подаче фронта SCL слейв ОБЯЗАН выставить ACK, иначе это говорит об отсутствии устройства (слейва) на шине!

Посмотри осциллографом физическое наличие сигнала АСК на шине.

Еще вопрос - какие-либо прерывания в программе используются ?

Pavel_Bor
С часами уже все ок)
Значение с внешнего RTC (DS1338) передается на внутренний RTC при включении контроллера. Добавлена проверка на отключение батарейки.
Прерываний будет много но со временем. (клавиатура, АЦП, УАРТ...)

Может системой событий воспользоваться..?
alexeyv
Цитата
Прерываний будет много но со временем. (клавиатура, АЦП, УАРТ...)


Тогда желательно в функциях чтения/записи I2C расставить:
1. в начале обмена - сохранение регистра статуса и глобальный запрет прерываний
2. в конце обмена - восстановление регистра статуса

Это необходимо для сохранения временных параметров доступа к шине.
Pavel_Bor
Сделаем. Спасибо
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.