0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
1 | |
Помогите найти ошибку (rs485) (решено)10.02.2016, 21:56. Показов 8988. Ответов 28
Метки нет (Все метки)
Обрабатываю запросы, приходящие на attiny2313 через st485. Прием-передача буферизованы.
По дефолту нога отвечающая за направление передачи rs485 опущена в ноль. Идет наполнение приемного буфера побайтно в прерывании URXC. Как только данные похожи на запрос, выставляется флаг готовности данных. Динные преобразовываются, наполняется выходящий буфер и нога поднимается для передачи. Передача происходит в прерывании UDRE. После передачи последнего байта нога опускается прямо в прерывании. Проблема в том, что устройство в точности получает инструкции и отрабатывает их, но отвечает по шине билибердой. Такое ощущение что где-то либо нога раньше времени опускается либо хз что. Начало ответа верное, но в середине и конце возникает мусор. Может у кого-нибудь есть рабочий пример работы по rs485 с буферизованым uartом? Или скажите куда рыть. Анализатора сигналов нету :( Код
; настраиваем USORT OUTI UBRRL, Low(BAUDRATEDIVIDER) OUTI UBRRH, High(BAUDRATEDIVIDER) OUTI UCSRA, (0<<U2X) ; работаем на обычной скорости OUTI UCSRB, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(0<<UDRIE) ; RX enable, TX enable, и прерывания OUTI UCSRC, (1<<UCSZ0)|(1<<UCSZ1) ; Set frame format: 8data, 1stop bit, No parity ; Прием UART RX_OK: PUSHF PUSH R17 PUSH XH PUSH XL LDI XL, Low(UARTINBUF) ; Берем адрес начала буффера LDI XH, High(UARTINBUF) LDS R16, UARTINBUFPTR ; Берем смещение точки записи LDI R17, MAXINBUF ; Размер буфера CP R16, R17 BRLO _rx_ok LDI R16, 1 STS UARTBUFERROR, R16 CLR R16 ; Превысили длину, это ошибка, но все равно возвращаемся в начало _rx_ok: ADD XL, R16 ; Сложением адреса со смещением CLR R16 ; получаем адрес точки записи ADC XH, R16 IN R16, UDR ; Забираем данные ST X, R16 ; Сохраняем их в буфер LDS R16, UARTINBUFPTR INC R16 STS UARTINBUFPTR, R16 ; Сдвигаем указатель LDI R17, MAXINBUF ; Размер буфера CP R16, R17 BRNE _rx_end ; Если дошли до конца буфера то сообщение получено LDI R16, 1 STS DATAREADY, R16 ; Сообщаем о готовности данных CLR R16 STS UARTINBUFPTR, R16 _rx_end: POP XL POP XH POP R17 POPF RETI ; Буфер UART UD_OK: PUSHF PUSH R17 PUSH ZL PUSH ZH LDI ZL, Low(UARTOUTBUF) LDI ZH, High(UARTOUTBUF) LDS R16, UARTOUTBUFPTR ADD ZL, R16 ; Сложением адреса со смещением CLR R16 ; получаем адрес точки чтения ADC ZH, R16 LD R16, Z OUT UDR, R16 CPI R16, 0x0D ; Если перевод строки то это конец вывода BREQ _ud_buffer_empty LDS R16, UARTOUTBUFPTR LDI R17, MAXOUTBUF DEC R17 CP R16, R17 BREQ _ud_buffer_empty LDS R16, UARTOUTBUFPTR INC R16 STS UARTOUTBUFPTR, R16 RJMP _ud_end _ud_buffer_empty: OUTI UCSRB, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(0<<UDRIE) ; глушим передачу CLRB PORTD, PD2, R16 ; выключаем MAX485 CLR R16 STS UARTOUTBUFPTR, R16 _ud_end: POP ZH POP ZL POP R17 POPF RETI ; в бесконечном цикле по флагу DATAREADY наполняем исходящий буфер, а затем: SITB PORTD, PD2, R16 ; включаем MAX485 OUTI UCSRB, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(1<<UDRIE) ; запускаем передачу
0
|
10.02.2016, 21:56 | |
Ответы с готовыми решениями:
28
[решено]Помогите пожалуйста найти ошибку в программе Помогите победить RS485. Программа пишет ошибку!! Помогите найти ошибку Помогите найти ошибку: По двум сторонам и углу найти все остальное |
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
10.02.2016, 22:02 | 2 |
Я допускаю что слишком рано опускаю ногу (данные в UDR засунул, но времени им высраться не дал). Но ведь это была бы ошибка только в последнем байте передачи. А ошибка начинается со второго байта ответа.
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
10.02.2016, 22:05 | 3 |
А может для опускания ноги использовать прерывание UTXC предварительно выставив в UDRE флаг что это последний байт? Или это тоже будет преждевременно?
0
|
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
|
|
11.02.2016, 11:49 | 4 |
Ух,
Логику вот этого: Код
LDS R16, UARTOUTBUFPTR LDI R17, MAXOUTBUF DEC R17 CP R16, R17 BREQ _ud_buffer_empty Так , а это вообще все лишнее : Код
PUSH ZL PUSH ZH LDS R16, UARTOUTBUFPTR ADD ZL, R16 ; Сложением адреса со смещением CLR R16 ; получаем адрес точки чтения ADC ZH, R16 LDS R16, UARTOUTBUFPTR INC R16 STS UARTOUTBUFPTR, R16 POP ZH POP ZL Код
LD R16, Z+
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 12:23 | 5 |
подключил ftdiшку послушать что там говорит тинька интерфейсу, она говорит все верно:
55 11 01 41 4F 4B 0D а проходя через ST485EB эта посылка превращается вот в такие (каждый раз разные): 55 81 40 B0 6A 35 55 91 40 B0 6A CA 55 81 40 A0 6A 35 55 91 40 B0 6A CA 55 C4 81 EA 15
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 12:34 | 6 |
Сообщение от YTYOUT
Сообщение от YTYOUT
Сообщение от YTYOUT
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 12:58 | 7 |
отключил прием везде где только можно, переделал переключение управляющей ножки интерфейса в прерывании TX (т.е. передатчик выключается когда все биты улетели в провод), добавил терминирующее сопротивление 120ом на стороне приемника, добавил подтяжку к питанию 10ком на RX выход контроллера и подтяжку к земле 10ком на управляющий выход (PD2).
один хрен. причем ПОЛУЧАЕТ данные оно точно, у меня проверка по стартовой посылке, по чексумме да и я вижу по исполнительному механизму что оно работает. но почему оно отвечает мусором я не понимаю. кстати после всех переделок теперь еще и первый байт бывает заваленым, раньше он гарантированно проходил. вместо 55 11 01 41 4F 4B 0D получаю 55 C4 A1 AA 35 D5 84 41 BA 35 D5 A4 41 6A DA D5 A4 41 BA 35 55 84 41 6A DA
0
|
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
|
|
11.02.2016, 12:59 | 8 |
Буфер может быть уже пуст (готов к приему следующего байте), но передача предыдущего при этом еще не завершена. На прием переключайтесь не по UDRE, а по TX Complete. Интерфейс по меркам МК очень медленный.
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 13:12 | 9 |
Сообщение от STT
вместо: 55 11 01 41 4F 4B 0D получаю: D5 A4 C1 EA 15 D5 A4 41 6A 15 55 84 A1 AA 35 D5 A4 C1 6A 15 55 84 A1 BA 35 D5 A4 41 6A 35 D5 A4 C1 6A 15 D5 84 41 BA 35 55 84 A1 AA 35 D5 A4 C1 6A 15 55 84 A1 AA 35 D5 A4 C1 6A 15 D5 A4 41 6A 15 95 A4 C1 EA 15 D5 84 41 6A DA D5 84 41 6A 35 55 84 41 BA 35 55 C4 A1 AA 35 55 84 41 AF 69 F8 55 84 A1 BA 35 D5 A4 C1 6A 15 D5 84 41 BA 35 55 84 A1 AA 35 D5 A4 C1 6A 15 D5 A4 C1 EA 15 D5 A4 41 6A 15 D5 84 41 AF 29 F8 D5 A4 C1 6A 15 D5 A4 41 6A 35 D5 A4 41 6A 15 D5 A4 41 6A 15
0
|
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
|
|
11.02.2016, 13:14 | 10 |
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 13:44 | 11 |
[QUOTE="STT"][QUOTE="Цитата:[/QUOTE]
я вываливаю 7 байт подряд, если б было так как вы говорите, то потерялся бы только последний байт. передачу я прерываю только после всех 7 байт. и кстати никаких запросов ST485EB не формирует. я начинаю подозревать что именно этот драйвер какой-то корявый. надо попробовать заменить на MAX485 и посмотреть что будет.
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 14:05 | 12 |
интернет говорит что st485 бывают бракованные, я недавно в кетае заказал десяток max485, как раз должны прийти.
так что пока голову насиловать не буду, попробую детальку заменить. p.s. только что перепаял одну st485 на другую такую же. никаких изменений.
0
|
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
|
|
11.02.2016, 15:01 | 13 |
Сообщение от tymso
Исходные данные. Сначала у вас стабильно проходил 1-й байт, остальные портились. Почему. Помимо вашего программного буфера имеется аппаратный буфер ФИФО на 2 байта в самом УСАПП. В начале передачи (поскольку буфер на 2 байта) вы скармливаете в УСАПП 1-й байт и тут же получаете прерывание по UDRE, поскольку есть куда всунуть второй байт. Ваша программа это и делает. Буфер заполнился. При этом передача уже началась. Следующий запрос на прерывание по UDRE вы получите, когда второй байт из ФИФО поступит на передачу в сдвиговый регистр, т.е. первый байт уже уйдет адресату. Пока вы обрабатываете запрос, идет передача второго байта, но тут вы ее прекращаете волевым решением. По аналогии то же самое происходит с остальными байтами. Таким образом вы портите все байты, кроме первого. Прерывание UDRE возникает тогда, когда в аппаратном буфере ФИФО есть место для очередной порции данных, в то время как TXC возникает после отправки последнего бита из самого передатчика. Т.о., вам необходимо в основном цикле отслеживать флаг занятости аппаратного буфера ФИФО, который будет сбрасываться в обработчике прерывания UDRE и устанавливаться подпрограммой загрузки данных в этот буфер, а переключать интерфейсную микросхему на прием по прерыванию TXC.
0
|
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
|
|
11.02.2016, 17:12 | 14 |
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 17:19 | 15 |
Сообщение от STT
UART работает идеально. В нем нет никаких ошибок. Посылка выходит целиком и полностью. Направление передачи я переключаю в два этапа: в прервании UD_OK поднимаю флаг "ушел последний байт", в прерывании TX_OK я проверяю этот флаг и отключаю передатчик (прерывание TX_OK выскакивает когда все биты улетели в провод). Если выбросить ST485EB всё работает идеально. Но когда я её добавляю, то прием работает идеально, а передача - зажёвывает. Проблема или в чипе ST485EB или в моем понимании его работы.
0
|
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
|
|
11.02.2016, 17:24 | 16 |
Чтобы не спорить, попробуйте переводить ST485EB на прием не по прерыванию, а по тайм- ауту, скажем, в 3 секунды. Заодно работоспособность микросхемы проверите.
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 17:27 | 17 |
[QUOTE="YTYOUT"]
Сообщение от Цитата:[/QUOTE]
У меня так как я описал и более того это работает в железе у меня перед носом. [QUOTE="YTYOUT Вы показываете исправление блока, который у меня в чистом виде не присутствует. Я не понимаю вас.
0
|
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
|
|
11.02.2016, 17:29 | 18 |
Сообщение от STT
0
|
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
|
|
11.02.2016, 17:33 | 19 |
0
|
0 / 0 / 0
Регистрация: 02.10.2012
Сообщений: 1,946
|
|
11.02.2016, 17:50 | 20 |
Код
LDS R16, UARTOUTBUFPTR -берём какое-то число записанное ниже LDI R17, MAXOUTBUF - берём константу DEC R17 - и зачем-то вычитаем из нее единицу CP R16, R17 - сравниваем вычитанную константу с каким-то числом BREQ _ud_buffer_empty LDS R16, UARTOUTBUFPTR За каким то хреном загружаем число которое уже находится в регистре R16 ещё раз INC R16 STS UARTOUTBUFPTR, R16 Код
Т.е. пофигу что регистр Z за пределами прерывания используется?
0
|
11.02.2016, 17:50 | |
11.02.2016, 17:50 | |
Помогаю со студенческими работами здесь
20
Помогите найти ошибку: в двумерном массиве найти второе по величине число Найти коэффициент при 10 степени в разложении бинома Ньютона (помогите найти ошибку). Найти минимальный элемент в массиве: помогите найти ошибку Помогите найти ошибку в коде. Найти сумму ряда Помогите найти ошибку Помогите найти ошибку Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |