|
DS1307 может оживить время?, Помогите прочитать с DS1307 больше одного байта! плиз.. |
|
|
|
Jul 24 2008, 12:43
|
Группа: Новичок
Сообщений: 11
Регистрация: 8-02-08
Пользователь №: 34 857

|
Всем доброе время суток! У меня проблема с 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
Сообщение отредактировал AVRdeveloper - Jul 24 2008, 12:44
|
|
|
|
|
Jul 24 2008, 13:55
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 11-01-07
Пользователь №: 24 303

|
Цитата(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 Я устанавливаю этот бит после и перед приемом (т.е. после отправки адресса), и после приема первого байта.. наверное, АСК выставляеться...
--------------------
Роботы делают роботов - предел автоматизации
|
|
|
|
|
Jul 25 2008, 05:23
|
Группа: Новичок
Сообщений: 11
Регистрация: 8-02-08
Пользователь №: 34 857

|
Цитата(Александр Куличок @ 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). Ой... точно.. а я то думаю, почему МК паразагружаеться при ошибке.. Исправил. И запретил прерывания при отправке данных. Сейчас узнаем, что происходит
|
|
|
|
|
Jul 25 2008, 14:56
|
Группа: Новичок
Сообщений: 11
Регистрация: 8-02-08
Пользователь №: 34 857

|
Цитата(AVRdeveloper @ Jul 25 2008, 08:23)  Ой... точно.. а я то думаю, почему МК паразагружаеться при ошибке.. Исправил. И запретил прерывания при отправке данных. Сейчас узнаем, что происходит  Всё равно, второй байт постоянно 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" -> читаем байт, делаем АСК-> читаем байт, делаем неАСК->Стоп В таком режиме читаеться первый байт
|
|
|
|
|
Jul 25 2008, 17:41
|
Местный
  
Группа: Свой
Сообщений: 408
Регистрация: 21-10-06
Из: Санкт-Петербург
Пользователь №: 21 527

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

кекс
     
Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326

|
Цитата(AVRdeveloper @ Jul 25 2008, 17:56)  Старт -> Отправка адреса(R/W = 1), проверяем АСК-> Отправляю "0" -> читаем байт, делаем АСК-> читаем байт, делаем неАСК->Стоп Что значит - "Отправляю "0"? В SLA-R ничего отправлять нельзя, это не SPI где можно и читать и писать одновременно. Цитата По логике работы шины надо чуть изменить: и еще чуть изменить: Цитата Старт -> Отправка адреса(R/W = 1), проверяем АСК->делаем АСК-> Отправляю "0" -> читаем байт->делаем неАСК-> читаем байт->Стоп Цитата После чтения первого байта из TWDR устанавливаю разрешение АСК: Не после чтения, а перед нужно устанавливать. Я же ж написал выше Цитата TWEA нужно устанавливать перед приемом НЕ последнего байта данных. Во всех остальных случаях его устанавливать не нужно и даже вредно.
|
|
|
|
|
Jul 28 2008, 07:14
|
Группа: Новичок
Сообщений: 11
Регистрация: 8-02-08
Пользователь №: 34 857

|
Цитата(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
Сообщение отредактировал AVRdeveloper - Jul 28 2008, 07:18
|
|
|
|
|
Jul 28 2008, 12:37
|
Группа: Новичок
Сообщений: 11
Регистрация: 8-02-08
Пользователь №: 34 857

|
Цитата(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.. Подпрограммы в приложении.
TWI.txt ( 1.58 килобайт )
Кол-во скачиваний: 271
|
|
|
|
|
Jul 30 2008, 13:57
|

Частый гость
 
Группа: Свой
Сообщений: 186
Регистрация: 14-01-06
Из: Украина, г.Харьков
Пользователь №: 13 168

|
вот мои библиотеки для работы с 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();
Сообщение отредактировал Олег Хохлов - Jul 30 2008, 14:00
|
|
|
|
|
May 17 2012, 09:12
|
Участник

Группа: Участник
Сообщений: 52
Регистрация: 11-01-07
Пользователь №: 24 303

|
Всем спасибо, ваши советы помогли, но все равно перешел на Си, где все заработало сразу)
--------------------
Роботы делают роботов - предел автоматизации
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|