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

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

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

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


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » uart и Tetminal v1.9b


uart и Tetminal v1.9b

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

1

Приветствую всех! начал разбираться с uart на Bascom и для этих целей использую маленькую программу

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

Config Pind.6 = Output

On Urxc Getchar

Dim Wtime As Word
Dim S As String * 4

Const Fastblink = 100
Const Slowblink = 500

Wtime = Slowblink

Enable Interrupts
Enable Urxc

Do

  Set Portd.6
  Waitms Wtime
  Reset Portd.6
  Waitms Wtime

Loop

Getchar:
 Input S
    If S = "val" Then
    Print Wtime
       End If
    If S = "fast" Then
    Wtime = Fastblink
    Print Wtime
       End If
     If S = "slow" Then
     Wtime = Slowblink
     Print Wtime
       End If

Return

End

Компилирую, всё ок. Собираю схему в протеусе тоже всё ок.
Собираю в железе. Запускаю Terminal 1.9, выставляю все параметры порта и при отправке любой команды программа в мк зависает. Запускаю HyperTerminal. При наборе команды программа приостанавливается, а при получении всей команды (после нажатия enter), команда исполняется. Тоже самое и в терминале Bascom'а и протеуса. Попробовал в delphi с компанентом BComPort - опять зависает и не исполняется, хотя все остальные проекты с использованием Terminal 1.9 и BComPort по uart прекрасно работают.
Помогите разобраться в чём дело.

0

2

1. зачем так усложнять? используйте ножки/пины аппаратного UART контроллера по умолчанию и тогда сделав просто настройки (сконфигурировав), обычным print "test" можно выводить информацию
2. если нет возможности использовать аппаратный UART, то используем софтовый, выглядить будет так:

Open "comb.0:19200,8,n,1" For Output As #1
Print #1 , "Test!"
Close #1

Естественно вначале сконфигурируйте порты на выход(вход).

При прошивке не забудьте отключить фюз деление на 8.

0

3

Разве в моём случае не аппаратный UART?
Вопрос у меня в большей степени про приём команд мк от пк. Единственное в чём удалось разобраться - в конце команды добавляю $0D (fast$0D) и это шлю терминалом. Тогда всё отрабатывается.
Аппаратный uart всегда шлёт эхо?
Касаемо первой части ответа:

Код:
Config Pind.1 = Output
Config Pind.0 = Input

Это имелось в виду?

0

4

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

Разве в моём случае не аппаратный UART?
Вопрос у меня в большей степени про приём команд мк от пк. Единственное в чём удалось разобраться - в конце команды добавляю $0D (fast$0D) и это шлю терминалом. Тогда всё отрабатывается.
Аппаратный uart всегда шлёт эхо?

Вы хелп почитайте, он доступно написан, с примерами.
Сделайте поиск по "UART", "ECHO"...
Сколько работал с отправкой и приёмом в МК, никаких эхо не наблюдал, всё от настройки зависит ПО на компе.
Так же данные должны отправляться сразу без всяких шаманств, возможно это у вас терминал так настроен. Я виндусовским вообще не пользовался, есть очень удобный такой (где в инете взять не помню).
Если использовать INPUT, PRINT, то отправляться будут все коды кроме 0 - это для текста всё. Если нужно отправить код, то нужно пользоваться INPUTBIN...

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

Это имелось в виду?

Немного не правильно, так:

Код:
Config PORTD.1 = Output
Config Pind.0 = Input

0

5

Кстати, по 0D у вас срабатывает потому, что используете INPUT.
Если хотите без него, то используйте другой алгоритм (обрабатывайте сами по байтно все данные).
Для этого есть классный оператор "Ischarwaiting".

Если есть возможность использовать RTS и CTS, то рекомендую, не будите пропускать ничего и не парится с обработкой (в меру доступного, пока буфер FIFO компа не переполнится).

У меня кусок кода выглядит так:

Код:
...
Reset Cts ' разрешить передачу данных
B = Ischarwaiting()
If B = 1 Then
    Set Cts ' запретить передачу данных
    In_data = Inkey()
    End If
...

Отредактировано RDW (2012-03-16 21:33:35)

0

6

Уже запарился тыкать мк туда сюда :)
Делаю так:

Код:
Getchar:

 If Ischarwaiting() = 1 Then
    S = Waitkey()
    End If

    If S = "val" Then
    Print Wtime
       End If
    If S = "fast" Then
    Wtime = Fastblink
    Print Wtime
       End If
     If S = "slow" Then
     Wtime = Slowblink
     Print Wtime
       End If
Return

Как я понимаю waitkey и inkey принимают по одному символу, пришедшему по uart. Есть мысль складывать их до получения какого-то спецсимвола.
RDW помоги с данным кодом, а то мозг уже не соображает. Нужно по uart отправить команду, а мк в зависимости от команды выполнил бы определённые действия. Длинна команд различная как в данном примере. Возможности использовать RTS и CTS нет.

Кстати терминал тот же самый

0

7

evgen79
1. Делайте работу как у меня в примере, не нужно сокрощать всё в одну строку - это всё-таки не полный бэйсик и он не правильно генерит код, если пытаешься усложнить всё в одну строчку. Примеры в хелпе даны не просто так. Я просто уже сталкивался в ряде случаев, когда вот так казалось бы сократив выполнение задачи до одной строки, на выходе получаю "ОК" при сборке, а в реалии Г. Правило простое: одно вычисление - строчка!

2. CTS & RTS вещь не обязательная, просто с нима упрощается код и есть надежность...в общем, если нет возможности с ними работать - и не надо.  ^^

3. Разница между waitkey и inkey в том, что waitkey подвешивает выполнение кода до получения одного знака, а inkey - нет (т.е. там всегда 0, когда нет символа). Ischarwaiting - нужно как раз для того, что бы определить заполняемость байта в порте по битам, т.е. можно определить 0 в inkey - это данные или нет (очень удобно).

Т.е. код приблизительно выглядит так должен:

Код:
Getchar:

   B = Ischarwaiting()
   If B = 1 Then
      S = inkey()

      If S = 0 Then
         Print Wtime
      End If
      If S = 1 Then
         Wtime = Fastblink
         Print Wtime
      End If
      If S = 2 Then
         Wtime = Slowblink
         Print Wtime
      End If
   End If
Return

Это как пример. При приходе значений из порта от 0-2 будет выполняться действие.

inkey - на выходе выдает байт, а не символ/текст
Если нужно обрабатывать целое слово/команду, то нужно делать соответствующее преобразование byte > chr + некое подобие буфера в котором будут накапливаться данные.

Дело в том, что если делать на прерывания через тот же INPUT, реализайия будет весьма простая, но будут существовать следующие проблемы:

- прием будет в области только текста;
- все данные будут приниматься только ключевого байта #0D из-за этого не трудно догадаться, что на это время прерывание будет вешать весь процесс и оно не будет успевать выполняться полностью пока данные не примутся.
- проблема безопасности, при такой реализации, если будет приходить глюк, то выхода из прерывания будет практически не возможен, т.к. вероятность встретить #0D мала.

Недостатки inkey:

- нужно самому делать буфер/массив в котором будут накапливаться данные, алгоритм массива должен быть на подобии FIFO (кольцевым);
- скорость/задержка работы, т.к. из-за буфера в котором сдвигаются байты.

Зато куча плюсов, никогда не подвешивается выполнение программы, всё выполняется за 1 проход, накопительная система (пошагово - это кстати основа прерывания, оно далеко не всегда обязано сразу загружать все данные)...

Я бы наверное вообще не стал пихать прием данных в прерывание.

Отредактировано RDW (2012-03-17 11:28:30)

0

8

RDW, спасибо за ответы.
В случае с inkey: если в кольцевой буфер тоже вкрадывается ошибка, то как быть тогда?
Код с приходом одного значения понятен, но хотелось бы разобраться с длинной командой, как в моём примере.

Насчёт преобразования:

Код:
Do
Akey = Waitkey()
If Akey = 13 Then Goto Thanks
Inputstring = Inputstring + Chr(akey)
Loop

Взято из help'a. Вот так?
Всё это делаю вот к чему: есть attiny2313 с 12 выходами. в зависимости от команды по uart на одном из выходов есть "1" или "0". Команда для этого "А1"-включить 1 канал, "В1"-второй и т.д.

0

9

вот, нашёл у себя пример работы с телефоном.

Код:
Ring = Inkey()
 If Ring = 82 Then                                          'проверяем есть ли сигнал с телефона
     Input Cmcin Noecho                                     'и считываем его
     If Cmcin = "ING" Then

Ловим букву R ну а далее ING. Команда Input ждёт перевод коретки. Если перевода коретки нет, можно использовать Inputbin, тогда пока не ззаполнит переменную. К примеру если переменная Integer, пока не придёт три байта. что-бы не висла программа, можно использовать таймаут.

0

10

Длинную команду определяем методом накопления простых/одно байтовых значений.
Алгоритмов массу: я например просто посмотрел какая у меня самая большая команда с данными по длине, далее беру массив/кешь/буфер равной это длине и начинаю заполнять/накапливать по одному байту справа налево, т.е. данные по байтно сдвигаются справа налево. Самый левый крайний байт соответственно забывается с каждым шагом. Параллельно массив преобразуется в строку (у меня не весь, для убыстрения работы), на выходе получаем готовую строку для сравнения её с искомой/ожидаемой... в общем есть где фантазии развернуться.

0

11

Что то я уже совсем запутался :(
Можно привести готовый простенький пример, например приём команды "reset".

0

12

Пример:

Код:
Const Buff = 5                      ' Длина текстового буфера обработки всех команд. 5 - потому что reset пять знаков
Const Buff1 = 4                    ' Длина текстового буфера - 1 (минус один)
Dim In_data As Byte             ' приходящий байт из порта
Dim Str_in As String * Buff  ' основной буфер приходящих команд
Dim Stmp As String * Buff     ' временная строка для обработки
...
Do
         In_data = Ischarwaiting()
         If In_data = 1 Then
            In_data = Inkey()

            If In_data < 32 Or In_data > 122 Then In_data = 32       ' - убраем всё лишнее
            Str_in = Right(str_in , Buff1)                ' Buff - 1 - основной заполнитель буфера
            Str_in = Str_in + Chr(in_data)                ' -- // -- // -- //  -- // -- // --

            If Str_in = "reset" Then Print "Reset"
Loop
...

Если команда короче буфера, то можно вытягивать так:

Код:
            Stmp = Right(str_in , 3)
            If Stmp = "run" Then Print "Run"

Вообще здесь входящую команду можно обрабатывать как по правому краю буфера, так и по левому. Так же не нужно забывать, что определенные команды могут внутренне по сочетанию знаков совпадать + есть приоритетность команд, соответственно тогда нужно в буфере удалять часть данных (заменять пустотой) после/перед их выполнения чтобы не было ложных срабатываний.

0

13

Этот алгоритм хорош, когда нужно работать с строками, для гибрида с кодом, нужно параллельно добавить обработку массива по такому же алгоритму, причем, если данные идут частично в коде, а остальное в тексте, то буфер кодовый (массив) может быть меньших размеров.

Отредактировано RDW (2012-03-20 12:28:26)

0

14

Вот это другое дело. Спасибо RDW! Буду пробовать.

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » uart и Tetminal v1.9b