Форум программистов, компьютерный форум, киберфорум
Микроконтроллеры
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.89/47: Рейтинг темы: голосов - 47, средняя оценка - 4.89
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
1

Помогите найти ошибку (rs485) (решено)

10.02.2016, 21:56. Показов 8988. Ответов 28
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Обрабатываю запросы, приходящие на 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
10.02.2016, 21:56
Ответы с готовыми решениями:

[решено]Помогите пожалуйста найти ошибку в программе
Привет. Пишу совсем несложную прогу под ATMiko16. И мозг мой взорван, уже часа два не могу найти...

Помогите победить RS485.
Есть здание, в здании некими умными специалистами построена проходная система. двухпроводный...

Программа пишет ошибку!! Помогите найти ошибку
Program Summa; var i, N, M: integer; begin Writeln ('Введите значение N:'); Read (N); ...

Помогите найти ошибку: По двум сторонам и углу найти все остальное
Доброго времени суток. В универе дали задание написать программу &quot;По двум сторонам и углу между...

28
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
Ух,
OUTI UCSRB, (1<<RXEN)|(1<<TXEN)|(1<<RXCIE)|(1<<TXCIE)|(1<<UDRIE) ; запускаем передачу
Отключите прием , он же все равно не нужен
Логику вот этого:
Код
LDS      R16, UARTOUTBUFPTR
LDI      R17, MAXOUTBUF
DEC      R17
CP      R16, R17
BREQ   _ud_buffer_empty
Я вообще не понял. Если вы знаете это число MAXOUTBUF , которое стремительно стремится к нулю DEC R17 , то зачем все остальное.
Так , а это вообще все лишнее :
Код
 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
Логику вот этого:
...
Я вообще не понял. Если вы знаете это число MAXOUTBUF , которое стремительно стремится к нулю DEC R17 , то зачем все остальное.
отправка завершается или по символу 0D в исходящем буфере или по окончанию буфера. вы видите ошибку?

Цитата Сообщение от 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
Буфер может быть уже пуст (готов к приему следующего байте), но передача предыдущего при этом еще не завершена. На прием переключайтесь не по UDRE, а по TX Complete. Интерфейс по меркам МК очень медленный.
Уже сделал. Нет эффекта. Укоротил провода до 10 сантиметров. Нет эффекта.

вместо:
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
а проходя через ST485EB эта посылка превращается вот в такие (каждый раз разные):
Буфер передатчика на 2 байта. Первый у вас выплевывается правильно, на его место подгружается второй и формируется запрос что буфер пуст. Но второй байт еще передается, а вы прерываете передачу в линию принудительным переводом ST485EB на прием.
0
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
11.02.2016, 13:44 11
[QUOTE="STT"][QUOTE="Цитата:[/QUOTE]
а проходя через ST485EB эта посылка превращается вот в такие (каждый раз разные):
Буфер передатчика на 2 байта. Первый у вас выплевывается правильно, на его место подгружается второй и формируется запрос что буфер пуст. Но второй байт еще передается, а вы прерываете передачу в линию принудительным переводом ST485EB на прием.

я вываливаю 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
я вываливаю 7 байт подряд, если б было так как вы говорите, то потерялся бы только последний байт. передачу я прерываю только после всех 7 байт.
Еще раз попробую.
Исходные данные. Сначала у вас стабильно проходил 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
отправка завершается или по символу 0D в исходящем буфере или по окончанию буфера. вы видите ошибку?
А у Вас это так или не так, как Вы описали? Ну так , если вдуматься.
Это прерывание! Мы туда заходим один раз за каждым байтом. Не понимаю о чем вы
Я Вам заменил это всё на одну единственную команду , в том же прерывании
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]
отправка завершается или по символу 0D в исходящем буфере или по окончанию буфера. вы видите ошибку?
А у Вас это так или не так, как Вы описали? Ну так , если вдуматься.

У меня так как я описал и более того это работает в железе у меня перед носом.

[QUOTE="YTYOUT
Я Вам заменил это всё на одну единственную команду , в том же прерывании
Т.е. пофигу что регистр Z за пределами прерывания используется?
Вы показываете исправление блока, который у меня в чистом виде не присутствует. Я не понимаю вас.
0
0 / 0 / 0
Регистрация: 21.01.2011
Сообщений: 159
11.02.2016, 17:29 18
Цитата Сообщение от STT
Чтобы не спорить, попробуйте переводить ST485EB на прием не по прерыванию, а по тайм- ауту, скажем, в 3 секунды. Заодно работоспособность микросхемы проверите.
Сделаю проще. Напишу отдельную прошивку которая будет тупо мяукать через st485 и узнаю что там передается.
0
0 / 0 / 0
Регистрация: 03.11.2012
Сообщений: 9
11.02.2016, 17:33 19
в прерывании TX_OK я проверяю этот флаг и отключаю передатчик
В приведенном вами коде нет такого обработчика. Выложите код полностью, начиная с векторов прерываний.
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 за пределами прерывания используется?
Извините, не оправдал надежд , ибо не капли ни экстрасенс. Но , если без дела "торчат" X и Y , то для них есть работа
0
11.02.2016, 17:50
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.02.2016, 17:50
Помогаю со студенческими работами здесь

Помогите найти ошибку: в двумерном массиве найти второе по величине число
Помогите найти ошибку Нужно в двумерном массиве найти второе по величине число uses crt; const...

Найти коэффициент при 10 степени в разложении бинома Ньютона (помогите найти ошибку).
&quot;После умножения скобок и приведения подобных в полиноме будет слагаемое с x**10. Перед ним стоит...

Найти минимальный элемент в массиве: помогите найти ошибку
Найти минимальный элемент в массиве. Помогите найти ошибку. #include &lt;stdio.h&gt; #include...

Помогите найти ошибку в коде. Найти сумму ряда
Добрый день, помогите найти ошибку. Задача: Найти сумму ряда, вычисление ввести до тех пор пока...

Помогите найти ошибку
Проблема , по моему мнению, заключается в том что выдает неправильную полную сумму ряда. Для...

Помогите найти ошибку
#include &lt;iostream&gt; using namespace std; int main() { double a, b; bool state; ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru