Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Связь двух МК по UART

Сообщений 1 страница 30 из 51

1

Привет, коллеги. Стоит задача научить общаться два МК по данной шине, хотя бы в одну сторону, ну это пока)) Вот код отправляющего МК:

Код:
$regfile = "m16def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 9600
......
разный код
......
'раз в секунду выполняется прерывание
Print "231"
'конец прерывания
......
разный код
.....
loop

А вот код принимающей стороны:

Код:
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 9600
Dim A As Integer
Dim B As Byte
Do
Input B
Locate 1 , 1 : Lcd B
Loop

Проблемы с кодом следующие:
1. Первый прием нормальный, цифра на дисплее отображается верно, но после отображается только ноль;
2. Если отключить UART, то принимающий МК как будто зависает и до восстановления связи он ничего не делает, это норм?
МК соединены напрямую, витой парой, длиной порядка 30см, питание общее от лабораторного БП.

0

2

1. читайте в хелпе про команду "timeout"
2. если в процессе приёма/передачи, параллельно происходит какой-то процесс, то данные портятся из-за задержек, следовательно надо учитывать этот факт и на момент обмена данными ничего параллельно происходить не должно или очень быстро должно происходить
3. в идеале это всё надо реализовывать в асинхронном виде, буферами (тоже есть в хелпе)

0

3

RDW написал(а):

1. читайте в хелпе про команду "timeout

не нашел такую((((

sasha_1973 написал(а):

Связь дву МК

спасиб за ссылку, видел её, но что-то не обратил внимание))

0

4

sasha_1973 написал(а):

Связь дву МК  -  здесь

Вот изучаю я код для связи по UART и не пойму, а почему этого нет в хелпе? Там всё просто принт, инпут и все, никаких буферов и прерываний :angry:  :angry:

0

5

Алексей bird написал(а):

не нашел такую((((

http://avrhelp.mcselec.com/index.html?_timeout.htm

0

6

RDW
спасибо!

sasha_1973
я так понимаю в Ваших примерах, не используется $TIMEOUT и соответственно МК встаёт в ожидании данных?

Отредактировано Алексей bird (2014-02-16 00:03:34)

0

7

sasha_1973 написал(а):

Не встаёт, так как работает аппаратный USART на прерываниях.

Я скопировал весь Ваш код для принимающего устройства, за исключением того что касается дисплея. Но при отключении сигнала rs232 от другого МК, счет A=A+1 встаёт до тех пор, пока не восстановиться связь.
Пример 1 взял за основу

Отредактировано Алексей bird (2014-02-16 00:17:39)

0

8

Причем считает четко по приходу сигнала от передающего МК, а он передает раз в секунду, по своему таймеру.

0

9

sasha_1973 написал(а):

Какой код Вы взяли?

Алексей bird написал(а):

Пример 1 взял за основу

вот что получилось

Код:
$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32
$baud = 9600


Config Lcd = 16 * 2
Config Lcdpin = Pin , Rs = Portc.4 , E = Portc.5 , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3
Config Portc = Output
Config Portb = Output
Config Portd.0 = Input
Config Portd.1 = Output
Cls

Dim A As Byte
Dim B As Byte

Dim Есть_данные_lcd As Bit
Dim Конец_передачи As Byte
Dim Что_принимаем_uart As Byte
Dim Счетчик_проходов_uart As Word
Dim Буфер_приема_uart As String * 20
Dim Очистка_буфера_uart As String * 1
Dim Передача_закончена_uart As Bit , Прием_закончен_uart As Bit

  Declare Sub Прерывание_прием_uart_закончен()
  Declare Sub Прерыв_передача_uart_закончена()
  Declare Sub Display_lcd_uart()

   Очистка_буфера_uart = ""
  Счетчик_проходов_uart = 0
  Что_принимаем_uart = 1
  Set Прием_закончен_uart
  Конец_передачи = 62

  On Utxc Прерыв_передача_uart_закончена                    '> Разрешаем прерывание после окончания передачи по UART
  On Urxc Прерывание_прием_uart_закончен                    '> Разрешаем прерывание после окончания приёма данных по UART
  On Udre Прерывание_буфер_пуст_uart                        '> Разрешаем прерывание после опустошения буфера UARTT
  Enable Urxc                                               '> Разрешаем прерывание после окончания приёма данных по UART
  Enable Utxc                                               '> Разрешаем прерывание после окончания передачи по UART
 Enable Interrupts                                          '> Разрешаем прерывания

   Do                                                       ': Nop
'-----------
   A = A + 1
    Locate 2 , 1 : Lcd A

    If Прием_закончен_uart = 1 Then


       Input Буфер_приема_uart

       Буфер_приема_uart = Mid(буфер_приема_uart , 2 , 5)

       Reset Прием_закончен_uart

       Set Есть_данные_lcd

    End If

'================================
    If Есть_данные_lcd = 1 Then
        Call Display_lcd_uart
        'Print ">"
    End If
'================================

  Loop
'-------
 End

   Прерывание_прием_uart_закончен:
'----------------------
   Disable Urxc
   Set Прием_закончен_uart
'----------------------
  Return
'-------------------------------------------------------------------------------
'*******************************************************************************

'*******************************************************************************
'-------------------------------------------------------------------------------
  Прерыв_передача_uart_закончена:
'--------------------------------
    Enable Urxc
'    Set Передача_закончена_uart
'----------------------
  Return
'-------------------------------------------------------------------------------
'*******************************************************************************

'*******************************************************************************
'-------------------------------------------------------------------------------
  Прерывание_буфер_пуст_uart:
'--------------------------------
'    Set Буфер_пуст_uart
'----------------------
  Return

    Display_lcd_uart:
'---------------
    Cls


    Locate 1 , 1 : Lcd Буфер_приема_uart

    Reset Есть_данные_lcd

'    Print ">"
'-----------
  Return

0

10

sasha_1973 написал(а):

Дайте ссылку, где взяли основу для исходника???

http://yadi.sk/d/G7FELtPQGMP3F файл "Atmega32 прием по USART.bas"
Ок, попробую другой код

0

11

Проблема осталась :confused:
Если отключить соединение UART и сбросить МК, то счет, ну по которому я сужу работу МК, не начинается. На дисплее светиться только "1", но как только восстанавливаю контакт, счет начинает идти. Также, в ваших примерах используется атмега328, а неё, видимо, есть другие комманды для управления UART, которые отсутствуют в атмеге8. Устройство планирую использовать на даче, для удаленного управления и прерывание связи между блоками на должно блокировать работу. Директива $TIMEOUT не помогает, т.к. если вставить её перед вводом информации, то да, МК выжидает какое-то время и продолжает работать дальше, НО при восстановлении сигнала, больше сигнал не принимает, т.е. INPUT не работает.
Кстати, сейчас я отлаживаю связь по 232 интерфейсу, но в дальнейшем я планирую связать эти МК через 485 шину, т.е. добавить SN75176BD в качестве преобразователя, и получается заново придётся отлаживать?

0

12

sasha_1973 написал(а):

Выложите код и симуляцию.

Код я выкладывал ранее, а симуляции нет, т.к. у меня только собранное устройство. Но чуть позже попробую накидать в протеусе....

0

13

Алексей bird, почему бы Вам не использовать ISCHARWAITING Вставьте в свой код, и если появиться еденица уходим проверять буфер УАРТ. Если в коде нет больших задержек, то, по моему, проще не куда.

0

14

Ну так Алексей как я понимаю хочет что бы прием шел в фоне, а камень в это время что то делал свое. В этом случае конечно все примеры будут либо ждать в цикле, либо ждать в слипе в главном цикле. Надо убирать из главного цикла " Idle             ' Спим, по приходу данных в USART, просыпаемся и галопируем на обработку принятого" и все будет крутиться без сна. Иначе как только пропадают символы на приеме, программа уйдет в слип до прерывания.

Отредактировано IgorL (2014-02-16 19:37:07)

0

15

Остальное вроде все так (если честно глаза кириллица ломает, может что то действительно не так в обработчике, вчитываться надо.)

+1

16

IgorL написал(а):

Надо убирать из главного цикла " Idle

Это я убрал, МК действительно заработал как надо, почему в предыдущих вариантах не работал хз.
Как я понимаю, инфа передается по UART байтами, т.е. за один раз 8 бит? И число больше 255 передается в несколько "приемов"?
Также, подскажите, я вывожу на дисплей число, которое приходит по UART, через переменную

Код:
Locate 1 , 1 : Lcd Буфер_приема_usart_str

, но на экране дисплея первый символ похож на.... а вот и не понять на что похож, какие три вертикальный черты, занимают одно место. Откуда они взялись?

0

17

Передается один байт. Оператор Print передает не байты из переменной а биты ASCII представления числа. То есть 255 будет передано как три байта с кодами 50,53,53
Если лезут левые символы то либо помеха, либо рассинхрон по скорости. Если конечно исползуется Print, а не PrintBin

0

18

С передающего МК я посылаю цифры от 1 до 32786(Integer) командой "Print A". На принимающей стороне отображаются цифры верно, но первым символом идут какие-то три вертикальные черты. Я оставил на работе на ночь, посмотрим что будет утром...

0

19

Замени Chr(...  на Hex(...
Увидишь не символы, а их коды в шестнадцатеричке, как их принял юарт. Если черточка останется, глюк библиотеки LCD  либо переменную накопительную не так очищаешь. А если пропадет и будет код не 30...39 а больше или меньше значит что то ловишь или передаешь не так, компом подключись параллельно, тоже покажет что реально в линии летает.

0

20

IgorL написал(а):

А если пропадет и будет код не 30...39 а больше или меньше значит что то ловишь или передаешь не так, компом подключись параллельно, тоже покажет что реально в линии летает.

Пропало, теперь виден код первого символа 0A ,это видимо какой-то спецсимвол. Наводкой, врядли это будет, т.к. символ постоянный, никуда не девается. Возможно, что-то уходит с передающего МК, хотя в коде там лишь Print A

0

21

Ну так правильно, Print шлет не только код 10, но и 0A в шестнадцатеричке. Возврат каретки и перевод строки.

Отредактировано IgorL (2014-02-18 09:14:40)

0

22

IgorL написал(а):

Ну так правильно, Print шлет не только код 10, но и 0A в шестнадцатеричке. Возврат каретки и перевод строки.

И теперь придётся в ручную это убирать?
Как я уже писАл, в дальнейшем я планирую перейти на 485 шину, и как я понимаю, придется заного всё отлаживать?

0

23

Можешь просто класть свою переменную в UDR. Передача одного байта произойдет автоматически и аппаратно.
Или вот кусочек кода из моей поделки )

Txd_int:                                                    'Обработчик
                                               
sbis ucsr0a, 5                                              '
rjmp Txd_int                                                ' Ждем флаг готовности принять данные
Udr = Mbuf(i)                                               'кладем значение в  UDR
                                               

Return

Отредактировано Skull (2014-02-18 11:03:24)

0

24

Алексей bird написал(а):

IgorL написал(а):

    Ну так правильно, Print шлет не только код 10, но и 0A в шестнадцатеричке. Возврат каретки и перевод строки.

И теперь придётся в ручную это убирать?
Как я уже писАл, в дальнейшем я планирую перейти на 485 шину, и как я понимаю, придется заного всё отлаживать?

Как нужно получить данные? Если как чистую строку, то удаять все, что меньше цифр. Если передавть переменной, то передавть Printbin а принимать Input
Вообще Print для передачи не очень хорош. Надо передавать побайтно, с маркером начала и конца и контрольной суммой.
Переход на 485 ничего не поменяет.

0

25

Когда делал терминал,
Ссылка
столкнулся именно с этой проблемой.
PRINT передает, в отличии от ПК больше спец символов, а INPUT "настроен" на прием от ПК.
В результате при связи МК-ПК всё работает, а при связи МК-МК они не понимают друг друга.
Пришлось программно отлавливать эти спец символы.

Посмотри исходники из этой статьи, там два исходника для двух МК именно для связи между собой. Может, что-то будет полезно.

У меня правда есть по новее прошивка, надо будет отправить на обновление.

0

26

Димон написал(а):

Когда делал терминал,
Ссылка
столкнулся именно с этой проблемой.
PRINT передает, в отличии от ПК больше спец символов, а INPUT "настроен" на прием от ПК.
В результате при связи МК-ПК всё работает, а при связи МК-МК они не понимают друг друга.
Пришлось программно отлавливать эти спец символы.

Посмотри исходники из этой статьи, там два исходника для двух МК именно для связи между собой. Может, что-то будет полезно.

У меня правда есть по новее прошивка, надо будет отправить на обновление.

Я не совсем понял каким методом ты решил эту проблему, поэтому прошу уточнить. Неужели команда "NOECHO" помогла?

0

27

Взял код для приёма по УАРТ, чтобы при прерывании связи между двумя МК, они могли работать самостоятельно отсюда. Туда же перенесён немного поправленный код, в него добавлена строка и для передачи по УАРТ. На МК выводы УАРТа замкнуты.

Код:
https://bascomavr.bbok.ru/viewtopic.php?id=1130#p12771

Помогла вот эта статья
В итоге индикация и счёт идёт нормально, ничего не заезжает и нет лишних символов.

Отредактировано Алексей bird (2014-02-27 10:02:07)

0

28

Алексей bird написал(а):

Выкладываю сей код

Перенёс Ваш вариант кода сюда.

Если Вы против, напишите, удалю?

0

29

sasha_1973 написал(а):

Не удалил, а перенёс  сюда, что-бы его могли видеть только зарегистрированные пользователи форума.

хмм.., возможно.

sasha_1973 написал(а):

ак, что большая просьба, здесь, фрагмент удалите!

хорошо, поправлю )))

sasha_1973 написал(а):

Если Вы уже сделали приём по прерыванию, так сделайте так-же и передачу

пока такая задача не стоит, но возможно, с усложнением кода, я так и сделаю.

sasha_1973 написал(а):

Получите полный контроль над трансляцией и будете четко видеть, что и куда передаётся или принимается. И самое главное, не будет никаких потерь, или некорректно переданных или принятых данных (проверено в железе и Протеусе, во всём диапазоне скоростей трансляции приведённых в документации на МК).

Вопрос был в том, что командой PRINT посылался LF, а при приёме этот LF не убирался и выводился на экран, хотя в дальнейшем я планирую по УАРТу гонять "сырые" данные, не выводя их на дисплей, но при лишних символах могут быть проблемы, поэтому я и отлаживал связь и на то, как "чисто" перегоняются данные. Протеус я не использую, потому что: 1. я с ним так и не смог найти общий язык, а разбираться мне лень, а ещё: 2. у меня есть реальное устройство, которое мне надо отладить именно в железе и отправить "в печать", ошибки там если и будут, то поправлю их программно))

sasha_1973 написал(а):

Если Вы против, напишите, удалю?

нет, не против :flag:

sasha_1973 написал(а):

Небыло никакого обсуждения, была игра в одни ворота.

Видимо вы думали, что я не обращаю внимание на ваши ссылки. Обращал я, только пользовался я не протеусом, а заливал код непосредственно в МК. И тут вылизали расхождения в работе кода в протеусе у вас и на реальном МК у меня.

Но в итоге совместными усилиями мы решили этот вопрос  :cool:

0

30

sasha_1973 написал(а):

За всё время работы с Протеусом, ни разу небыло такого, что-бы работало там и не работало в железе, или наоборот. Если что-то не работало, то только из-за моих ошибок.

Я пишу то, что было у меня. Я знаю в чем проблема, но у меня на реальном МК работало так, как я написал. Связь рву - МК встаёт, может протеус не так реагирует на данное действие, я хз. Но работало именно так.
А в итоге проблема решена с помощью вашего кода, просто передачу данных также надо правильно организовывать :idea:

Отредактировано Алексей bird (2014-02-26 11:53:45)

0