Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: DS1307 может оживить время?
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
AVRdeveloper
Всем доброе время суток! У меня проблема с DS1307. Использую Мегу16
После инициализации МК произвожу чтение с этой МС раз в секунду таким способом:
Первый байт принимаеться каждый раз с новым значением, а второй - постоянно $FF
Как принять последовательность из нескольких байт?


call TWI_init ; инитим I2C МК
call TWI_stop
call TWI_start
ldi r16,0b11010001
call TWI_send_adr
ldi r16,0 ; r16 используеться для передачи след. ф.-ии значений
call TWI_send_data
call get_byte1 ; При приеме первого байта считываеться случаqное число регистра данных TWI
call get_byte2 ; При приеме второго байта постоянно принимается $FF
call TWI_stop
..
..
..
TWI_init:
ldi r16,(0<<TWPS0)|(1<<TWPS1)
out TWSR,r16
ldi r16,9 ; битрейт при частоте 8МГц меньше 100кГц
out TWBR,r16
ldi r16,(1<<TWEA)|(1<<TWEN)|(0<<TWIE);
out TWCR,r16
ret
;
;
TWI_start:

ldi r16, (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)
out TWCR, r16; формирование режима START

waitST:
in r16,TWCR ; Проверка бита TWINT
sbrs r16,TWINT
rjmp waitST ; Не получен TWINT - цикл

RETURN:
ret

TWI_send_adr:

// проверим, что предидущее состояние было старт
// в регистре r16 содержится адрес адрессуемого устройства
push r16

in r16,TWSR ; Проверка кода ответа
andi r16,0xF8
cpi r16,$08
breq dalee11
cpi r16,$10
breq dalee11 ; Правильный код -выход из подпрограммы
brne TWI_error ; Нет - повтор.

dalee11:
pop r16
out TWDR, r16
ldi r16, (1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(0<<TWIE)
out TWCR, r16



wait2:
in r16,TWCR
sbrs r16,TWINT
rjmp wait2
// передача не происходит? или установка флага не происходит из-за другой причины?
in r16,TWSR
andi r16, 0xF8
cpi r16, $18
breq tsa_00
cpi r16, $40
brne TWI_ERROR
tsa_00:
ret
;
get_byte1:
in r16,TWCR
sbrs r16,TWINT
rjmp get_byte1
in r16,twdr
ldi XH,high(secs_twi1)
ldi XL,low(secs_twi1)
st x,r16 // Секунды в БЦД формате записали
ldi r16,(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(0<<TWIE)
out TWCR,r16
ret
;
;
get_byte2:
in r16,TWCR
sbrs r16,TWINT
rjmp get_byte2
in r16,twdr
ldi XH,high(secs_twi2)
ldi XL,low(secs_twi2)
st x,r16 // Секунды в БЦД формате записали
ldi r16,(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(0<<TWIE)
out TWCR,r16
ret
;
TWI_send_data:
out TWDR, r16
ldi r16, (0<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE)
out TWCR, r16;
wait3:
sei
nop
cli
in r16,TWCR
sbrs r16,TWINT
rjmp wait3
in r16,TWSR
andi r16, 0xF8
cpi r16, $28;MT_DATA_ACK
breq tsa_01
cpi r16,$58
breq tsa_01
cpi r16,$50
brne TWI_error
TSA_01:
ret
aaarrr
ACK, нaверное, не выставляется после 1-о чтения.
Шалапут:-)
Цитата(aaarrr @ Jul 24 2008, 16:09) *
ACK, нaверное, не выставляется после 1-о чтения.

При приёме первого байта
get_byte1:
in r16,TWCR
sbrs r16,TWINT
rjmp get_byte1
in r16,twdr
ldi XH,high(secs_twi1)
ldi XL,low(secs_twi1)
st x,r16 // Секунды в БЦД формате записали
ldi r16,(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(0<<TWIE); Флаг (1<<TWEA) - для формирования АСК!
out TWCR,r16
ret

Ещё:
TWEA - TWI Enable Acknowledge Bit
Я устанавливаю этот бит после и перед приемом (т.е. после отправки адресса), и после приема первого байта..
наверное, АСК выставляеться...
Александр Куличок
TWI_send_data:
out TWDR, r16
ldi r16, (0<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE)
out TWCR, r16;

Ничего, что здесь разрешаете прерывания от twi?

И при выходе по ошибке из TWI_send_adr у Вас портится стек (в нем остается R16).
defunct
Цитата(Шалапут:-) @ Jul 24 2008, 16:55) *
TWEA - TWI Enable Acknowledge Bit
Я устанавливаю этот бит после и перед приемом

TWEA нужно устанавливать перед приемом НЕ последнего байта данных. Во всех остальных случаях его устанавливать не нужно и даже вредно.
AVRdeveloper
Цитата(Александр Куличок @ Jul 24 2008, 17:24) *
TWI_send_data:
out TWDR, r16
ldi r16, (0<<TWEA)|(1<<TWINT)|(1<<TWEN)|(1<<TWIE)
out TWCR, r16;

Ничего, что здесь разрешаете прерывания от twi?

И при выходе по ошибке из TWI_send_adr у Вас портится стек (в нем остается R16).

Ой... точно.. а я то думаю, почему МК паразагружаеться при ошибке.. Исправил.
И запретил прерывания при отправке данных. Сейчас узнаем, что происходит smile3046.gif
AVRdeveloper
Цитата(AVRdeveloper @ Jul 25 2008, 08:23) *
Ой... точно.. а я то думаю, почему МК паразагружаеться при ошибке.. Исправил.
И запретил прерывания при отправке данных. Сейчас узнаем, что происходит smile3046.gif

Всё равно, второй байт постоянно FF...

После чтения первого байта из TWDR устанавливаю разрешение АСК:

get_byte1:
in r16,TWCR
sbrs r16,TWINT
rjmp get_byte1
in r16,twdr
ldi XH,high(secs_twi1)
ldi XL,low(secs_twi1)
st x,r16
ldi r16,(1<<TWEA)|(1<<TWINT)|(1<<TWEN)|(0<<TWIE); бит TWEA = 1
out TWCR,r16
ret

Значит, второй байт должен быть отправлен микросхемой на шину..
Я думаю проблема может быть в протоколе обмена:
По даташиту:
При чтении из DS1307 нужно сделать Старт -> Отправка адреса(R/W = 1), проверяем АСК-> читаем байт, делаем АСК-> читаем байт, делаем неАСК->Стоп

В этом случае программа при отладке ведёт себя нормально, даже считываються разные значения 2-х байтов..А при запуске в реал-тайм прога зацикливаеться в этом месте при формировании старт:
waitST:
in r16,TWCR
sbrs r16,TWINT
rjmp waitST


Как делаю я:
Старт -> Отправка адреса(R/W = 1), проверяем АСК-> Отправляю "0" -> читаем байт, делаем АСК-> читаем байт, делаем неАСК->Стоп
В таком режиме читаеться первый байт
Qwertty
Цитата(AVRdeveloper @ Jul 25 2008, 18:56) *
Как делаю я:
Старт -> Отправка адреса(R/W = 1), проверяем АСК-> Отправляю "0" -> читаем байт, делаем АСК-> читаем байт, делаем неАСК->Стоп
В таком режиме читаеться первый байт

По логике работы шины надо чуть изменить:
Старт -> Отправка адреса(R/W = 1), проверяем АСК->делаем АСК-> Отправляю "0" -> читаем байт->делаем неАСК-> читаем байт->Стоп
defunct
Цитата(AVRdeveloper @ Jul 25 2008, 17:56) *
Старт -> Отправка адреса(R/W = 1), проверяем АСК-> Отправляю "0" -> читаем байт, делаем АСК-> читаем байт, делаем неАСК->Стоп

Что значит - "Отправляю "0"?
В SLA-R ничего отправлять нельзя, это не SPI где можно и читать и писать одновременно.

Цитата
По логике работы шины надо чуть изменить:

и еще чуть изменить:
Цитата
Старт -> Отправка адреса(R/W = 1), проверяем АСК->делаем АСК-> Отправляю "0" -> читаем байт->делаем неАСК-> читаем байт->Стоп



Цитата
После чтения первого байта из TWDR устанавливаю разрешение АСК:

Не после чтения, а перед нужно устанавливать.
Я же ж написал выше
Цитата
TWEA нужно устанавливать перед приемом НЕ последнего байта данных. Во всех остальных случаях его устанавливать не нужно и даже вредно.
AVRdeveloper
Цитата(defunct @ Jul 26 2008, 01:12) *
Старт -> Отправка адреса(R/W = 1), проверяем АСК->делаем АСК-> читаем байт->делаем неАСК-> читаем байт->Стоп

Сделал так. с JTAG в пошаговой эмуляции работает.. читаються разные байты данных.. а если программу запустить в реал тайме, она зацыкливаеться в месте проверки флага TWINT, после формирование сост. "Старт"..
Ещё: Поменял частоту TWI. Для 8 МГц она = 97,56 кГц
TWI_init:
ldi r16,(0<<TWPS0)|(0<<TWPS1)
out TWSR,r16
ldi r16,21 // 97кГц
out TWBR,r16
ldi r16,(1<<TWEA)|(1<<TWEN)|(0<<TWIE)
out TWCR,r16
ret
defunct
Цитата(AVRdeveloper @ Jul 28 2008, 10:14) *
TWI_init:
...
ldi r16,(1<<TWEA)|(1<<TWEN)|(0<<TWIE)

не надо TWEA где попало ставить.
Посмотрите еще раз где он должен быть!
AVRdeveloper
Цитата(defunct @ Jul 28 2008, 12:58) *
не надо TWEA где попало ставить.
Посмотрите еще раз где он должен быть!

Убрал 1<<TWEA с инициализации..
теперь последовательность выполняемых подпрограмм такая (выполняем раз в секунду):

call TWI_start
ldi r16,0b11010001
call TWI_send_adr
call get_byte1
call get_byte2
call TWI_stop

При отладке в пошаговом режиме программа выполняеться, а реал-тайм зависает при втором опросе DS1307 в ожидании установки флага TWINT в подпрограмме TWI_start..

Подпрограммы в приложении.Нажмите для просмотра прикрепленного файла
OlegH
вот мои библиотеки для работы с DS1307 для IAR C, Mega16 (может помогут)...

Инициализация:

DS1307_WriteByte(7, 0x80); // No output on pin 7
if (DS1307_Read(0)==0 AND (DS1307_Data & 0x80)) DS1307_WriteByte(0, 0);


Периодически читаем время c помощью:

DS1307_ReadRTC();
Шалапут:-)
Всем спасибо, ваши советы помогли, но все равно перешел на Си, где все заработало сразу)
ILYAUL
Цитата(Шалапут:-) @ May 17 2012, 13:12) *
Всем спасибо, ваши советы помогли, но все равно перешел на Си, где все заработало сразу)

Да как быстро летит время . 4 - года и всё таки помогли советы lol.gif
chu
Цитата(AVRdeveloper @ Jul 24 2008, 19:43) *
Всем доброе время суток! У меня проблема с DS1307. Использую Мегу16
После инициализации МК произвожу чтение с этой МС раз в секунду таким способом:
Первый байт принимаеться каждый раз с новым значением, а второй - постоянно $FF
Как принять последовательность из нескольких байт?


call TWI_init ; инитим I2C МК
call TWI_stop
call TWI_start
ldi r16,0b11010001
call TWI_send_adr
ldi r16,0 ; r16 используеться для передачи след. ф.-ии значений
call TWI_send_data
call get_byte1 ; При приеме первого байта считываеться случаqное число регистра данных TWI
call get_byte2 ; При приеме второго байта постоянно принимается $FF
call TWI_stop
..
..

если не ошибаюсь, 0b11010001 ==0xD1, вот что написанов даташите на ds1307:
Цитата
The device’s slave address is D0h and cannot be modi-fied by the user. When the R/W bit is 0 (such as in D0h), the master is indicating it writes data to the slave. If R/W = 1 (D1h in this case), the master is
indicating it wants to read from the slave. If an incor-rect slave address is written, the device assumes the
master is communicating with another I2C device and ignore the communication until the next START condi-tion is sent.

а для считывания необходимо повторный рестарт делать
go forth
ILYAUL
Алгоритм считывания данных приведён на Figure 6. Data Read (Write Pointer, Then Read)—Slave Receive and Transmit в DS
chu
у меня с ds1307 таких проблем, как у топикстартера, не было.
в приведенном фрагменте кода (amforth) протокол обмена по шине i2c представлен весьма прозрачно

Код
  $d0  constant  twi.ds1307   \ device address on i2c bus

\ запись байта <c> по адресу <addr> в ds1307
  : twi.rtc! ( c addr -- )

      \ send device address
        twi.ds1307
        twi.start
        twi.tx      $18 twi.status?

      \ send ds1307 address pointer
        twi.tx      $28 twi.status?

      \ send data byte
        twi.tx      $28 twi.status?
        twi.stop
       ;

\ чтение байта по адресу <addr> из ds1307
  : twi.rtc@ ( addr -- c )

        twi.ds1307
        twi.start
        twi.tx      $18 twi.status?
        twi.tx      $28 twi.status?

      \ repeated start to read the data byte
        twi.start   $10 twi.status?
        twi.ds1307  set-rw
        twi.tx      $40 twi.status?
        twi.rxn     $58 twi.status?
        twi.stop
       ;


and so forth...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.