Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: SAM7X + DS1340
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
athlon64
Реализую чтение и запись даты и времени, на SAM7X512 в IAR 5.4.
Сначала чтение сделал за один проход как чтение из микросхемы с внутренним адресом. Т.е. устанавливал внутренний адрес 0x08 и читал 9 байт.
Считывалась последовательность байт: 0xA9 0x80 0x13 0x19 0x00 0xFF 0xFF 0x00 0x00. Причём секунды и минуты (0x13 и 0x19) тикают и изменяются верно, часы и дату пока проверить не успел. Но с датой какая то ерунда - читается 45.00.0000.
Пробовал сделать чтение регистров как сказано в даташите на ds1340, т.е. сначала запись 1 байта адреса регистра, а затем повторный старт на чтение. Считывается та же последовательность байт. Осциллограммы обоих вариантов в приложении. Смутило на осциллограммах что нет межбайтовых интервалов, при обмене с другими модулями (на меге8, меге32) интервалы присутствуют.
В чём может быть подвох?

В основной программе:
Код
StateTWI=ReadRTC;
EndDataInTWI=9;
PtrDataInTWI=0;    // Будет прочитан ответ 9 байт
AT91C_BASE_TWI->TWI_MMR = (1 << 8) | AT91C_TWI_MREAD | ((CntAddrTWI >> 1) << 16); // 1-байтовый внутренний адрес
AT91C_BASE_TWI->TWI_IADR = 0x08;                                        // Начальный адрес регистров RTC
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START;                               // START
AT91C_BASE_TWI->TWI_IER = AT91C_TWI_RXRDY | AT91C_TWI_TXCOMP;           // Ловить будем получение байта и окончание обмена по NACK на адрес

В обработчике прерывания от TWI:
Код
unsigned int status = AT91C_BASE_TWI->TWI_SR;    // читаем статус TWI

if (status & AT91C_TWI_RXRDY)       // Сначала был получен байт от модуля (до окончания обмена)  // Устройство отправило в CPU байт
{
DataInTWI[PtrDataInTWI]=AT91C_BASE_TWI->TWI_RHR;    // Прочитали очередной байт
if (++PtrDataInTWI >= (EndDataInTWI-1))           // Если принят предпоследний байт
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;        // STOP. После этого будет принят последний байт по событию TWI_TXCOMP
}
    
if (status & AT91C_TWI_TXCOMP)      // Пришёл последний байт от  устройства
{
DataInTWI[PtrDataInTWI] = AT91C_BASE_TWI->TWI_RHR;
AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;          // STOP
AT91C_BASE_TWI->TWI_IDR = 0xFFFFFF;               // Выключаем все прерывания от TWI
StateTWI=255;                                     // Ставим признак свободного TWI

//////------- Отладочный вывод в COM-порт принятого пакета --------
      unsigned char i;
      for (i=0;i<(EndDataInTWI+1);i++)
        AddToRS(DataInTWI[i]);
      AddToRS(0x7E);
//////--------------------------------------------------------------------------
PoiskTWI |= fPoiskTWIData;                        // Ставим флаг - Есть пакет на обработку
}
aaarrr
Если коротко, то есть два пути:
1. Всеми правдами и неправдами заставить работать TWI (еррату, аппноты почитать, поэкспериментировать и т.п.)
2. Использовать программный I2C

Советую выбрать второй.
athlon64
Цитата(aaarrr @ Jun 28 2010, 12:56) *
Если коротко, то есть два пути:
1. Всеми правдами и неправдами заставить работать TWI (еррату, аппноты почитать, поэкспериментировать и т.п.)
2. Использовать программный I2C

Советую выбрать второй.

Боюсь программный I2C - не вариант.
Устройство должно каждые 2.5мс опрашивать очередной модуль и в фоне вести кучу рассчётов и формировать ответы в ком-порты максимально быстро sad.gif


Пробую читать разное количество регистров, все значения те же, что и при считывании пачкой, ну кроме секунд и минут которые уже натикали.
Ощущение что глюк не с I2C связан.
Вопрос:
Если случайно записать в регистр (скажем по адресу 0x04H (день месяца) байт 0xFF), при чтении этого регистра будет читаться 0xFF до истечения суток по часам?
aaarrr
Цитата(athlon64 @ Jun 28 2010, 11:37) *
Боюсь программный I2C - не вариант.
Устройство должно каждые 2.5мс опрашивать очередной модуль и в фоне вести кучу рассчётов и формировать ответы в ком-порты максимально быстро sad.gif

Ну, смотрите. Наше дело предупредить wink.gif

Цитата(athlon64 @ Jun 28 2010, 11:37) *
Вопрос:
Если случайно записать в регистр (скажем по адресу 0x04H (день месяца) байт 0xFF), при чтении этого регистра будет читаться 0xFF до истечения суток по часам?

Насколько я помню, он моментально урезается в этом случае, т.е. лишних бит нет физически.
athlon64
Цитата(aaarrr @ Jun 28 2010, 14:24) *
Ну, смотрите. Наше дело предупредить wink.gif

smile.gif Обидно просто что со всеми другими модулями сделать обмен получилось, а с RTC запара

Цитата(aaarrr @ Jun 28 2010, 14:24) *
Насколько я помню, он моментально урезается в этом случае, т.е. лишних бит нет физически.

Видимо нет. Взял такую же плату с SAM7X512 и DS1340, но без батарейки. После каждого сброса питания и до попытки синхронизировать время дата и время в RTC корректные 00:00:00 01.01.00. После записи в RTC - 45:85:85 45.25.2145, хотя судя по осциллограммам (если отключить весь остальной обмен и оставить только запись в RTC) запись проходит верно. Запутался в общем sad.gif
ILYAUL
Было , такое правдо не с ARM. Теперь , перед тем как , что -то писать в DS устанавливаю его на нулевой регистр, а эатем пишу. Если регистры прочитать не все , то следущее чтение начнётся с регистра не прочитанного в предыдущем чтении.
И данные Вы записываете в BCD?
athlon64
Цитата(ILYAUL @ Jun 28 2010, 19:40) *
Было , такое правдо не с ARM. Теперь , перед тем как , что -то писать в DS устанавливаю его на нулевой регистр, а эатем пишу. Если регистры прочитать не все , то следущее чтение начнётся с регистра не прочитанного в предыдущем чтении.
И данные Вы записываете в BCD?

Данные записываю, конечно, закодированные в BCD.
Всегда пишу и читаю по предварительно переданному адресу регистра. Пробовал писать отдельные регистры и все 10 регистров пачкой.
Оставлял часы тикать на ночь, читая с RTC 3 раза в секунду время-дату и передавая в ком-порт. На утро часы верно насчитали прошедшие 15 часов, дата осталась корректной. Т.е. с чтением проблем нет.
Снял сегодня осциллограмму записи в RTC пачки 10 регистров начиная с адреса 0x08.

Посылка (на дату-время 10:58:36 29.06.30):
Цитата
0x08(адрес) 0xA9 0x00 0x36 0x58 0x10 0x29 0x29 0x06 0x30 0x00
соответствует осциллограмме, единственное межбайтовых интервалов нет, всё засылается сплошняком. Читается мусор типа 00:14:10 45.00.00.

Код начала записи:
Код
  StateTWI = WriteData;       // Будем писать в модуль
    EndDataOutTWI=11;
    DataOutTWI[0]=0x08;
    DataOutTWI[1]=0xa9;
    DataOutTWI[2]=0;
    DataOutTWI[3]=0x36;
    DataOutTWI[4]=0x58;
    DataOutTWI[5]=0x10;
    DataOutTWI[6]=0x29;
    DataOutTWI[7]=0x29;
    DataOutTWI[8]=0x06;
    DataOutTWI[9]=0x30;
    DataOutTWI[10]=0;

  PtrDataOutTWI=1;                                    // Т.к. 0й байт уже передан, продолжаем с 1
  
  AT91C_BASE_TWI->TWI_MMR = (CntAddrTWI >> 1) << 16;  // Задаём адрес для записи в модуль
  AT91C_BASE_TWI->TWI_IADR = 0;                       // Начальный адрес регистра 0x08
  AT91C_BASE_TWI->TWI_THR = DataOutTWI[0];            // Передаём на запись первый байт буфера
  AT91C_BASE_TWI->TWI_CR = AT91C_TWI_START;           // START
  AT91C_BASE_TWI->TWI_IER = AT91C_TWI_TXRDY | AT91C_TWI_NACK; // Ловить будем успешные отправки байт и неподтверждённые приёмником посылки


Код в обработчике прерывания:
Код
  unsigned int status = AT91C_BASE_TWI->TWI_SR;    // Читаем статус TWI
    if (status & AT91C_TWI_TXRDY)                 // Прошлый байт был принят приёмником (получен ACK)
    {
      if (PtrDataOutTWI >= (EndDataOutTWI))                 // Если последний байт
      {
        AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;                  // STOP
        AT91C_BASE_TWI->TWI_IDR = 0xFFFFFF;                       // Выключаем все прерывания от TWI
        StateTWI=255;                                             // Ставим признак свободного TWI
      }
      else
        AT91C_BASE_TWI->TWI_THR = DataOutTWI[PtrDataOutTWI++];    // Передаём очередной байт данных
    }
    
    if (status & AT91C_TWI_NACK)                  // Прошлый байт не был успешно принят приёмником (получен NACK)
    {
      LedErrorOn();                                             // Мигнём индикатором "Ошибка"
      AT91C_BASE_TWI->TWI_CR = AT91C_TWI_STOP;                  // STOP
      AT91C_BASE_TWI->TWI_IDR = 0xFFFFFF;                       // Выключаем все прерывания от TWI
      StateTWI=255;                                             // Ставим признак свободного TWI
    }


В принципе запись в RTC будет выполняться не чаще чем раз в час, можно и пинодрыганием сделать.
Может у кого нибудь есть пример? Как реализовать задержки?
ILYAUL
А если попробывать писать не c 0x08 , а с 0x00 т.е сначала секунды. Записать 0x36 0x58 0x10 0x29 0x29 0x06 0x30 И не запуская счёт - прочитать .
Цитата
AT91C_BASE_TWI->TWI_MMR = (CntAddrTWI >> 1) << 16; // Задаём адрес для записи в модуль
И извините я это не понял. Так Вы задаёте Slaveadr?

И почему у Вас день недели 29-ый их всего 7 и год какойто странный? И Вы про него не забываете (день недели), когда декодируете часы
Цитата
Читается мусор типа 00:14:10 45.00.00.
я его здесь не вижу


Цитата
00,$18,$09,$02,$29,$06,$10
как-то так
athlon64
Цитата(ILYAUL @ Jun 29 2010, 12:54) *
А если попробывать писать не c 0x08 , а с 0x00 т.е сначала секунды. Записать 0x36 0x58 0x10 0x29 0x29 0x06 0x30 И не запуская счёт - прочитать.

Записал с 0 адреса последовательность: 0x36 0x58 0x10 0x02 0x29 0x06 0x30
Сразу читаю с 0 адреса: 0x02 0xFF 0xFF 0x00 0x00 0x14 0x10

Цитата(ILYAUL @ Jun 29 2010, 12:54) *
И извините я это не понял. Так Вы задаёте Slaveadr?

У меня просто адреса i2c устройств везде в программе 8-битные. Смещением на 1 вправо я убираю лишний бит, после чего пишу его в TWI_MMR

Цитата(ILYAUL @ Jun 29 2010, 12:54) *
И почему у Вас день недели 29-ый их всего 7 и год какойто странный? И Вы про него не забываете (день недели), когда декодируете часы я его здесь не вижу

В программе день недели не используется, я в него писал дату, т.к. он всё равно урежется. Выше я вместо дня недели писал 0x02, это ничего не изменило, к сожалению smile.gif
ILYAUL
Цитата
У меня просто адреса i2c устройств везде в программе 8-битные. Смещением на 1 вправо я убираю лишний бит, после чего пишу его в TWI_MMR

Slave DS1340 1101000+bit R/W Зачем смещение ? Задайте его как константу , а при чтении прибавляйте 1 и пишите в TWI_MMR.

Цитата
Оставлял часы тикать на ночь, читая с RTC 3 раза в секунду время-дату и передавая в ком-порт. На утро часы верно насчитали прошедшие 15 часов, дата осталась корректной

Уточните - часы Вы инициализировали или они считали с нулей. Т.е после сброса Вы не писали ни время ни даты
athlon64
В общем разобрался с записью в RTC. Была ошибка в обработчике прерывания, из-за чего последний байт слался мусором.
Убрал всё лишнее, оставил только запись и чтение 1 байта в одном и том же регистре DS1340, снял осциллограммы и всё стало понятно.
Интервалов между байтами при обмене с RTC так и нет, на старой версии платы на меге256 они были и при обмене с другими модулями (слейвами) на мегах интервалы есть. Ну пока в общем всё работает.
Теперь сажусь разбираться с I2C EEPROM
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.