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

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

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

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



PZEM-004T

Сообщений 91 страница 120 из 133

91

Наваял в Excel, проверил.
Получается так:

(4-5) - напряжение 0x0898, преобразовано в десятичное 2200, дисплей 220,0 в
- берем позиции в указанном порядке
(6-9) - ток 0x000003E8, преобразованный в десятичный 1000, дисплей 1.000A
- последовательность позиций: 8-9-6-7
(10-13) - мощность 0x00000898, преобразована в десятичную-2200, дисплей 220,0 Вт
- последовательность позиций: 12-13-10-11
(14-17) - энергия 0x00000000, преобразована в десятичный 0, дисплей 0 Вт · ч
- последовательность позиций: 16-17-14-15
(18-19) - частота l-0x01F4, преобразованная в десятичную-500, дисплей 50,0 Гц
- берем позиции в указанном порядке
(20-21) - коэффициент мощности 0x0064, преобразованный в десятичный 100, дисплей 1,00
- берем позиции в указанном порядке
(22-23) - сигнал тревоги 0x0000, означает, что сила тока ниже порога сигнала тревоги
- думаю, по-барабану, просто флаги ;)
(24-25) - CRC

0

92

Вот такое у продавца на али написано , похоже совпадает с выше сказанным.

https://ae01.alicdn.com/kf/HTB18BFQaHys3KVjSZFnq6xFzpXaA.jpg

Например, мастер отправляет следующую команду (код проверки CRC заменен
0xHH и 0xLL, то же самое ниже)
0x01 + 0x04 + 0x00 + 0x00 + 0x00 + 0x0A + 0xHH + 0xLL
Означает, что мастер должен считывать 10 регистраторов с slave адресом 0x01 и стартом
Адрес регистратора 0x0000
Правильный ответ от раба:
0x01 + 0x04 + 0x14 + 0x08 + 0x98 + 0x03 + 0xE8 + 0x00 + 0x00 + 0x08 + 0x98 + 0x00 +
0x00 + 0x00 + 0x00 + 0x00 + 0x00 + 0x01 + 0xF4 + 0x00 + 0x64 + 0x00 + 0x00 + 0xHH + 0xLL
Приведенные выше данные показывают
⚫Напряжение 0x0898, преобразовано в десятичное 2200, дисплей 220,0 в
⚫Ток 0x000003E8, преобразованный в десятичный 1000, дисплей 1.000A
⚫Мощность 0x00000898, преобразована в десятичное число 2200, дисплей 220,0 Вт
⚫Энергия 0x00000000, преобразована в десятичное число 0, отображение 0 Вт · ч
⚫Частота 0x01F4, преобразованная в десятичную-500, дисплей 50,0 Гц
⚫Коэффициент мощности 0x0064, преобразованный в десятичное значение 100, дисплей 1,00
⚫Состояние будильника 0x0000, означает, что сила тока ниже, чем мощность будильника

Отредактировано olegkaras (2019-07-03 22:08:40)

+1

93

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

Вот такое у продавца на али написано , похоже совпадает с выше сказанным.

А вот сразу не было возможности выложить ? ;)
И не было бы 4-х страниц темы... ;)
Не будут же все форумчане на поставленный вопрос кидаться рыть инет в поисках ответа...

В любом случае - нашли правильный подход ?
Попробуйте, расскажете практический результат.

0

94

Вот пример Александра УАРТ .
Почему в строке Pzem_004t (0xF8 0x04 0x14 0x08 0x98 0x08 0x98 0xE8 0xBA 0x16 0xF6 0xE8 0x01 0xF4 0x45 0xF8 ) пропускаются байты с значением 0x00 ? Cчетчик принятых байтов такие байты считает ?

КОД

'===============================================================================
'*
'*  Автор: Sasha_1973
'*  Дата:  27.02.2014 г.
'*
'*  МК:  ATmega8А
'*  Тактовая частота МК:  1 MГц
'*
'*  Скорость передачи USART: 9600 бод
'*
'*  Компилятор: BASCOM-AVR 2.0.7.1
'*  Используемый шрифт в Bascom: Consolas; размер = 14
'*
'*  Программа симулятор: Proteus 7.10 SR0
'*
'*  Описание:
'*           Приём и передачи по USART с ипользованием прерываний и аппаратного буфера МК
'===============================================================================
'===============================================================================

  $map
  $regfile = "m128def.dat"
  $crystal = 8000000
  $framesize = 128
  $hwstack = 128
  $swstack = 128

'------------------------  Настройка USART  ------------------------------------

  $baud = 4800                                              '4800     '19200     '38400     '57600     '76800     '115200    '230400
  'Ucsra.1 = 1                                               ' Двойная скорость работы USART, скорость трансляции = $baud * 2
  On Urxc Принятые_данные_usart                             ' Переход на подпрограмму обработки прерывания после окончания приёма данных по USART
  On Udre Прерывание_буфер_usart_пуст                       ' Переход на подпрограмму обработки прерывания после опустошения буфера передачи данных по UART

'------------------- Конфигурация LCD на базе HD44780 --------------------------

  Config Lcd = 16 * 2                                       ' Используемый LCD
  Config Lcdpin = Pin , Rs = Portc.4 , E = Portc.5 , Db4 = Portc.0 , Db5 = Portc.1 , Db6 = Portc.2 , Db7 = Portc.3

  Initlcd                                                   ' Инициализируем LCD
  Waitms 50                                                 ' Ждем пока все запустится
  Cursor Off Noblink                                        ' Выключаем неморгающий курсор
  Cls                                                       ' Чистим экран, на всякий случай

'-----------------------  Настройка TIMER1  ------------------------------------

  Config Timer1 = Timer , Prescale = 1                      ' Настройка TIMER1
  On Timer1 Обработка_прерывания_timer1                     ' Подпрограмма для обработки прерывания TIMER1
  Stop Timer1                                               ' Останавливаем таймер
  Timer1 = 0                                                ' Сбрасываем таймер
  Dim Флаг_было_прерывание_timer1 As Byte

'--------------------  Используемые переменные  --------------------------------

  Dim Переменная_word As Word

  Dim Флаг_буфер_uart_пуст As Byte
  Dim Флаг_есть_принятое_сообщ_usart As Byte

  Dim Буфер_lcd_str As String * 20

  Dim Номер_символа As Byte
  Dim Счетчик_принятых_символов As Byte
  Dim Принятый_код_символа_usart As Byte

  Dim Буфер_приема_usart_str As String * 20
  Dim Буфер_передачи_usart_byte(20) As Byte
  Dim Буфер_передачи_usart As String * 20 At Буфер_передачи_usart_byte(1) Overlay
  Dim Pzem_004t As String * 25
'--------------  Разрешаем работу необходимых прерываний USART -----------------
  Enable Urxc
  Enable Timer1 : Start Timer1
'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts                                         ' Разрешаем работу прерываний
'===============================================================================
'                   Г Л А В Н Ы Й         Ц И К Л
'===============================================================================
  Главный_цикл:

    If Флаг_было_прерывание_timer1 = 1 Then
        Буфер_lcd_str = "{248}{004}{000}"                   ' Получаем строковую переменную для вывода на LCD
        Буфер_lcd_str = Буфер_lcd_str + "{000}{000}{010}"
        Буфер_lcd_str = Буфер_lcd_str + "{100}{100}"
        Буфер_передачи_usart = Буфер_lcd_str                ' Получаем строковую переменную для вывода по USART
        'Буфер_lcd_str = Format(буфер_lcd_str , "    0")     ' Форматируем переменную, для корректного вывода на LCD

'        Locate 1 , 1                                        ' Определяем номер строки и знакоместа
'        Lcd Буфер_lcd_str                                   ' Выводим переменную на LCD

        Enable Udre                                         ' Включаем прерывание, тем самым начиная передачу
        Флаг_было_прерывание_timer1 = 0                     ' Скидываем флаг
        Goto Главный_цикл                                   ' Проверяем, может ещё что-нибудь надо сделать
    End If

    If Флаг_есть_принятое_сообщ_usart = 1 And Флаг_буфер_uart_пуст = 1 Then
        Флаг_есть_принятое_сообщ_usart = 0                  ' Сбрасываем флаг

       ' Locate 2 , 1                                        ' Определяем номер строки и знакоместа
'        Lcd Spc(20)                                         ' Чистим строку

'        Locate 2 , 1                                        ' Определяем номер строки и знакоместа
'        Lcd Буфер_приема_usart_str                          ' Выводим на LCD
        Pzem_004t = Буфер_приема_usart_str
        Буфер_приема_usart_str = ""                         ' Чистим буфер приёма
        Enable Urxc                                         ' Включаем прерывание, тем самым начиная приём
        Goto Главный_цикл                                   ' Проверяем, может ещё что-нибудь надо сделать
        Флаг_есть_принятое_сообщ_usart = 0
     End If

  Goto Главный_цикл
End
'===============================================================================
'                        П О Д П Р О Г Р А М М Ы
'===============================================================================

'===============================================================================
  Принятые_данные_usart:
'-------------------------------------------------------------------------------

    Принятый_код_символа_usart = Udr                        ' Забираем содержимое аппаратного буфера USART

    If Счетчик_принятых_символов < 24 And Флаг_есть_принятое_сообщ_usart = 0 Then       ' Проверяем, не является ли этот символ "Enter"
         Буфер_приема_usart_str = Буфер_приема_usart_str + Chr(принятый_код_символа_usart)       ' Если нет, то добавляем его в буфер принятого по USART сообщения
        Incr Счетчик_принятых_символов                      ' Считаем количество принятых символов
      Else                                                  ' Иначе выключаем приём и ставим метку, что приём закончен (принято всё сообщение), можно что-то делать с принятым
        Disable Urxc                                        ' Выключаем приём, пока не обработаем принятое сообщение
        Счетчик_принятых_символов = 0                       ' Сбрасываем счётчик символов, готовим к следующему приёму
        Флаг_есть_принятое_сообщ_usart = 1                  ' Если символ оказался "Enter", тогда флаг устанавливаем в 1. "Enter"- конец сообщения
    End If

'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Прерывание_буфер_usart_пуст:
'-------------------------------------------------------------------------------

    Incr Номер_символа                                      ' Готовим переменную, что-бы взять следующий символ   = 7 мкс

    If Буфер_передачи_usart_byte(номер_символа) = 0 Then    ' Если все передали, запрещаем прерывание и готовим переменные для следующей передачи        = 6 мкс
        Udr = 13                                            ' Передаем "Enter" (перевод строки)
        Disable Udre                                        ' Запрещаем прерывание после опустошения буфера UART
        Буфер_передачи_usart = ""
        Номер_символа = 0                                   ' Какой символ будем читать при следующей передаче по USART
        Флаг_буфер_uart_пуст = 1                            ' Поднимаем флаг, говорящий о том, что аппаратный буфер USART пуст и можно что-нибудь принять или отправить
      Else
        Udr = Буфер_передачи_usart_byte(номер_символа)      ' Поочерёдно заносим байтовые значения в аппартный буфер МК, для передачи
    End If

'-------------------------------------------------------------------------------
  Return
'===============================================================================

'===============================================================================
  Обработка_прерывания_timer1:
'-------------------------------------------------------------------------------

    Incr Переменная_word                                    ' Увеличиваем переменную
    Флаг_было_прерывание_timer1 = 1                         ' Ставим флаг

'-------------------------------------------------------------------------------
  Return
'===============================================================================

Отредактировано olegkaras (2019-07-08 22:11:47)

0

95

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

Почему в строке Pzem_004t (......) пропускаются байты с значением 0x00 ?
Cчетчик принятых байтов такие байты считает ?

Счетчик будет считать, если они (эти байты) будут приняты.

Только вот тут:

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

'=====================================================================  Принятые_данные_usart:'-------------------------------------------------------------------------------
If Счетчик_принятых_символов < 24 And Флаг_есть_принятое_сообщ_usart = 0 Then....

У вас идет проверка только по счетчику (флаг не в счет), а значение "0" практически везде означает "конец строки".
Это ("конец строки") Bascom корректно обрабатывает, завершая строку и не добавляет лишние (на его взгляд) символы к принимаемой строке.
Но счетчик еще не достиг установленного значения, поэтому прием не прекращается.
Каждый следующий "0" Bascom так же игнорирует, а любое "ненулевое" значение прибавляет в принимаемую строку.
И так - до "срабатывания" счетчика, когда прием заканчивается.

Устаканивайте способы приема и критерии окончания приема. ;)
Очень даже работоспособный способ приема любой строки уже приводился здесь или в соседней теме.

Отредактировано Nord (2019-07-09 06:44:43)

0

96

Вот

ПРИВОДИЛСЯ

$map
  $regfile = "m128def.dat"
  $crystal = 16000000
  $baud = 9600
  $framesize = 120
  $hwstack = 120
  $swstack = 120

'Конфигурация RS232
Config Com1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config SERIALIN = BUFFERED , size = 50

Dim I As String * 25
Dim D As String * 25


main:
      If Ischarwaiting = 1 Then
         i = 1
         Waitms 100
         While _RS_HEAD_PTR1 <> _RS_TAIL_PTR1               'Проверка кольцевого буфера
            D(i) = Inkey
            Incr i
         Wend
         Clear Serialin

   CONFIG POWERMODE = IDLE                                  'Уснём
   GoTo Main

,только как его скомпелировать  ?
Этот

КОМПЕЛИТСЯ

$map
  $regfile = "m128def.dat"
  $crystal = 16000000
  $framesize = 120
  $hwstack = 120
  $swstack = 120

CONFIG SUBMODE = NEW
'Конфигурируем порт:
Config Com1 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config SERIALIN = BUFFERED , size = 50      'Размер выбирается такой, как нужно. Для примера 50, но не более 255
'Подпрограмма приёма строки:
Sub Modemdata
   StrRS = ""
   While _RS_HEAD_PTR0 <> _RS_TAIL_PTR0                   'Проверка кольцевого буфера. Цикл будет работать пока не совпадут указатели начала и конца буфера, что означает полную выборку из него.
      Rs = Inkey()
      If Asc(rs) > 24 Then                                  'Отсекаем ненужные символы
         StrRS = StrRS + Rs                           'Формируем строку
      End If
      Waitms 10
   Wend
End Sub
'Определяем переменные:
Dim StrRS As String * 50                                    'Сама строка с длиной равной объёму буфера
Dim RS As String * 1                                        'Переменная для чтения символа из буфера
Dim FlagStr As Byte
'Сама программа чтения:
Main:
    FlagStr = Ischarwaiting()                       'Если пришёл ответ от модуля
        If FlagStr = 1 Then
            ModemData
        End If
    CLEAR SERIALIN                                   'На всякий случай чистим буфер

'  (Здесь разбираем команду на запчасти)
CONFIG POWERMODE = IDLE                                  'Уснём
GoTo Main
Stop

но ни чего не принимает, какой то заколдоБОванный круг.
Может у кого есть рабочий код?Ссылка

Отредактировано olegkaras (2019-07-09 19:59:07)

0

97

Вместо этой строки (второй листинг) что-то вписывалось ? ;)

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

'  (Здесь разбираем команду на запчасти)

0

98

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

Вместо этой строки (второй листинг) что-то вписывалось ?


А что вписыВАть , все переменные равны нулю .

0

99

Пока попробовать не могу...
Доберусь - буду эксперименты ставить. ;)

Мой заказанный модуль вторую неделю лежит на таможне...

0

100

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

If Asc(rs) > 24 Then                                  'Отсекаем ненужные символы

Необходимо изменить на If Asc(rs) > 32
Строки с кодами меньше 32 не принимаются. Для меня это тоже загадка.
Частота кварца в 16 мГц также может давать хоть и небольшие, ошибки. На скорости 9600 где то 0,2%.
Напиши какую команду выдать чтобы получить ответ от модуля.
Я сделаю фрагмент рабочей программы.

Отредактировано sva-don (2019-07-10 10:02:26)

0

101

sva-don написал(а):

Необходимо изменить на If Asc(rs) > 32
Строки с кодами меньше 32 не принимаются.

Тогда If Asc(rs) >= 32 потому что 32 это пробел.

0

102

Пётр написал(а):

Тогда If Asc(rs) >= 32 потому что 32 это пробел.

Лично я придерживаюсь мнения, что лучше всего использовать вот это:
      If Ischarwaiting = 1 Then
         i = 1
         Waitms 100
         While _RS_HEAD_PTR1 <> _RS_TAIL_PTR1               'Проверка кольцевого буфера
            D(i) = Inkey
            Incr i
         Wend
         Clear Serialin
А уж потом можно из массива D выцыганить всё, что пожелает душа.
Например если принимается строка, то после D(i)=Inkey просто вставляем    StrRs = StrRs + Chr(D(i)) .
Тогда на 100% принимается всё.

0

103

А у меня Bascom на эту строку ругается... ;)

sva-don написал(а):

If Ischarwaiting = 1 Then

Если писать
a = Ischarwaiting()
If a = 1...
то условие прокатывает.

И вот эти переменные - откуда ?
В лексиконе Bascom не нашел...
Определены ранее ?

sva-don написал(а):

_RS_HEAD_PTR1 <> _RS_TAIL_PTR1


Возможно, тупанул, но запустить эту конструкцию адекватно не получается...  :blush:
Используется аппаратный UART.

Отредактировано Nord (2019-07-10 14:39:45)

0

104

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

А у меня Bascom на эту строку ругается...

У меня не ругается. Можно и так А= и т.д.
Переменные _RS_HEAD_PTR1 <> _RS_TAIL_PTR1 Создаются автоматически при использовании буферизированного ввода Config SERIALIN = BUFFERED , size = 50, Size на ваш выбор, но не более 255.
Они означают начало и конец буфера приема, т.е. организуется так называемый кольцевой буфер. (Можно прочесть в инете что это).
Когда при чтении забирается один символ из буфера, то их указатели декрементируются и когда они оба станут равны, то это означает, что всё содержимое буфера прочитано.
Да, это работает ТОЛЬКО на аппаратном UART!

Отредактировано sva-don (2019-07-10 14:59:59)

+1

105

sva-don написал(а):

Напиши какую команду выдать чтобы получить ответ от модуля.
Я сделаю фрагмент рабочей программы.

Строка команды-запроса для модуля:
F8 04 00 00 00 0A 64 64 (без пробелов).

Действительно с приемом значений менее Asc(32) проблемы...
Как-то не приходилось сталкиваться.
С тем же Nextion почему-то обычный прием UART по прерыванию прекрасно ловит любые числовые (не текстовые) значения, от 0 до 255, а из МК в МК передать - грабли... ;)

0

106

Вот накропал... ;)
Принимает чётко, но как удобнее привязывать в общей программе пока не думал.
http://s8.uploads.ru/t/n1ItO.jpg

Передатчик

$Regfile="m48pdef.dat"
$Crystal=8000000
$hwstack=16
$swstack=16
$framesize=32
$baud = 9600

'===================================================================

Waitms 100
'===================================================================
Dim a As Byte
Dim b As Byte
Dim snd(25) As Byte

'===================================================================
'Строка для передачи - F8041409368BF800017A7D0003073D000001F4005F0000930E

snd(1) = &HF8
snd(2) = &H04
snd(3) = &H14
snd(4) = &H09
snd(5) = &H38
snd(6) = &H8B
snd(7) = &HF8
snd(8) = &H00
snd(9) = &H01
snd(10) = &H7A
snd(11) = &H7D
snd(12) = &H00
snd(13) = &H03
snd(14) = &H07
snd(15) = &H3D
snd(16) = &H00
snd(17) = &H00
snd(18) = &H01
snd(19) = &HF4
snd(20) = &H00
snd(21) = &H5F
snd(22) = &H00
snd(23) = &H00
snd(24) = &H93
snd(25) = &H0E

'===================================================================
Do

For a = 1 To 25
      b = snd(a)
      Printbin b;
Next a

Wait 5
Loop
End
'===================================================================

Приемник

$Regfile="m48pdef.dat"
$Crystal=8000000
$hwstack=16
$swstack=16
$framesize=32
$baud = 9600

'===================================================================

'===================================================================
'                                                   Переменные для работы UART
Dim Флаг_есть_принятое_сообщ_usart As Byte        '
Dim priem As String * 3
Dim a As Byte
Dim b As Byte
Dim i As Byte
Dim d(25) As Byte

'===================================================================
'                                                    Определение прерываний
On Urxc Принятые_данные_usart
Enable Urxc
Enable Interrupts

'===================================================================

Do

If Флаг_есть_принятое_сообщ_usart = 1 Then

Inputbin d(1), 25
For i = 1 To 25
      b = d(i)
      priem = Hex(b)
      Print priem;
Next i
Print

Флаг_есть_принятое_сообщ_usart = 0
Enable Urxc

End If

Loop

End

'===================================================================
'                                                             РАБОТА  С  UART
'------------------------------------------------------------------------------------------------------------------------
Принятые_данные_usart:

Disable Urxc
Флаг_есть_принятое_сообщ_usart = 1

Return

0

107

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

Вот накропал...
Принимает чётко, но как удобнее привязывать в общей программе пока не думал.

Неплохо бы все это вылить в один флакон.

0

108

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

Неплохо бы все это вылить в один флакон.

Пробовал "сливать"... ;)

Вот так работает нормально.

'===================================================================
'                                                             РАБОТА  С  UART
'------------------------------------------------------------------------------------------------------------------------
Принятые_данные_usart:

Disable Urxc
Inputbin d(1), 25
Флаг_есть_принятое_сообщ_usart = 1
Enable Urxc

Return

В главном цикле МК мигает светиками, по приходу строки выдает принятое.
Светики, бывает, чуть притормаживаются. Думаю, это происки Протеуса.

Отредактировано Nord (2019-07-11 14:13:17)

0

109

Ну и вот что получилось в результате. Всё прекрасно работает. :flag:

Код:
$regfile = "m644Pdef.dat"                                   'Контроллер
$crystal = 1843200                                          'Определение частоты кварца
$baud = 9600                                                'Скорость обмена по COM1
$hwstack = 16                                               ' hardware stack
$swstack = 32                                               'software stack
$framesize = 64                                             'frame space
CONFIG SUBMODE = NEW

'Конфигурация RS232
Config Com2 = 9600 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
Config SERIALIN1 = BUFFERED , size = 25

'---------------------------------- ПЕРЕМЕННЫЕ --------------------------------
Dim D(25) , i as Byte                                       'Массив для приёма
'---------------------------------- Подпрограммы ------------------------------
'Очистка буфера
Sub ClearBuffer
   For i = 1 to 25
      D(i) = 0
   Next i
End Sub
'------------------------------------------------ Начало работы ------------------------------------------------------------------------------------
ENABLE INTERRUPTS

   Open "com2:" For Binary As #1

Main:
   If Ischarwaiting(#1) = 1 Then
      Call ClearBuffer
      i = 1
      While _RS_HEAD_PTR1 <> _RS_TAIL_PTR1                  'Проверка кольцевого буфера
         D(i) = Inkey(#1)                                   'Пишем в массив
         Incr i
         Waitms 10
      Wend
      Clear SERIALIN1
'Напечатаем принятое
      For i = 1 to 25
         Print #1 , "D(" ; i ; ") = " ; HEX(D(i));
      Next i
   End If

  'Уснём
   CONFIG POWERMODE = IDLE
   GoTo Main

   End

http://s3.uploads.ru/t/yYwTS.jpg
Теперь немного объяснений.
Я работал с COM2 т.к. у меня под рукой была плата где COM1 занят обменом с модулем, а обмен с ПК производится по COM2.
Думаю, что переход на СОМ1 всем ясен.
У меня нет модуля, поэтому передавал строку ответа из терминала. Как видите всё, что передано терминалом отлично принялось контроллером.
Саму строку ответа взял из поста №80.
Ну проще уже некуда. 8-)

Отредактировано sva-don (2019-07-11 10:45:30)

+1

110

sva-don написал(а):

Ну и вот что получилось в результате. Всё прекрасно работает


То-же , только на прерываниях и ASM

Const Usart_0_amount_rxd_symbols = 25       'Количество принимаемых символов 

частота МК=18,432 МГц

baud=460800

время между передачами = 5 ms

приёмник

'===============================================================================

  Const Simulation = 0

  $map       ' Получаем карту распределения памяти компилятором Bascom
  $regfile = "m328pdef.dat"       ' Используемый контроллер
  $crystal = 18432000       ' 8 МГц    , кварц для стабильной работы USART во всём диапазоне скоростей передачи и приёма
  $framesize = 128       'размер области используемой и необходимой для преобразований
  $hwstack = 128       ' Размер аппаратного стека
  $swstack = 128       ' Размер программного стека

  Const Const_baud_usart_0 = 230400       ' Скорость трансляции USART_0

  Const Usart_0_amount_rxd_symbols = 25       'Количество принимаех символов

  Const Usart_0_const_size_buffer = 100       ' Размер буферов приёма и передачи, USART_0

  Const Usart_0_input_const_size_buffer = 100       ' Размер буферов приёма и передачи, USART_0

  Config Com1 = Const_baud_usart_0 , Synchrone = 0 , Parity = None , Stopbits = 1 , Databits = 8 , Clockpol = 0
  Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'---------------  Обработчики прерываний USART_0  ------------------------------
  On Urxc Usart_0_input_data Nosave       ' Переход на подпрограмму обработки прерывания после окончания приёма данных по USART

'-----------------  Используемые переменные USART_0  ---------------------------
  Dim Usart_0_flag_resived_usart As Byte       ' Флаг сигнализирующий о том, что идёт приём по USART_0
  Dim Usart_0_flag_data_input As Byte       ' Флаг сигнализирующий о том, что приняты ноые данные по USART_0
'  Dim Usart_0_flag_transmitted As Byte       ' Флаг сигнализирующий о том, что идёт передача по USART_0
'  Dim Usart_0_count_transmitter As Byte       ' Считаем количество переданных символов по USART_0
  Dim Usart_0_count_received_symbols As Byte       ' Считаем количество принятых символов

  Dim Temp_usart_0_count_rxd_symbols As Byte       ' Временно считаем количество принятых символов

  Dim Temp_usart_0_input_buffer_str As String * Usart_0_input_const_size_buffer
  Dim Temp_usart_0_input_buffer_byte(usart_0_input_const_size_buffer) As Byte At Temp_usart_0_input_buffer_str Overlay

  Dim Usart_0_input_buffer_str As String * Usart_0_input_const_size_buffer
  Dim Usart_0_input_buffer_byte(usart_0_input_const_size_buffer) As Byte At Usart_0_input_buffer_str Overlay

'  Dim Usart_0_output_buffer_str As String * Usart_0_const_size_buffer       ' Строковый буфер приёма USART_0

  Dim Usart_0_temp_rxd_str As String * Usart_0_const_size_buffer

  Dim Count_usart As Byte
  Dim Temp_count_usart As Byte

'===============================================================================
'--------------  Разрешаем работу необходимых прерываний  ----------------------
'===============================================================================

  Gosub Usart_0_clearing_buffer_receive

'------------  Разрешаем работу всех включенных прерываний  --------------------
  Enable Interrupts
'===============================================================================

'         Предварительная проверка и запуск

'===============================================================================

  Print "Начало программы"

'===============================================================================

'                   Г Л А В Н Ы Й         Ц И К Л
  Main:
'===============================================================================

          If Usart_0_flag_data_input > 0 Then

              Print "Count " ; Usart_0_count_received_symbols

              Temp_count_usart = Usart_0_amount_rxd_symbols - 1

              For Count_usart = 1 To Temp_count_usart
                  Print Hex(usart_0_input_buffer_byte(count_usart));
              Next Count_usart

              Print Hex(usart_0_input_buffer_byte(usart_0_amount_rxd_symbols))

              Gosub Usart_0_clearing_buffer_receive

              Usart_0_flag_data_input = 0
              Goto Main
          End If



   Idle       ' Отправляем МК на тихий час
'===============================================================================
  Goto Main
End
'===============================================================================



'===============================================================================
  Usart_0_clearing_buffer_receive:
'-------------------------------------------------------------------------------
    For Count_usart = 1 To Usart_0_count_received_symbols
        Usart_0_input_buffer_byte(count_usart) = 0
    Next Count_usart

    Usart_0_count_received_symbols = 0       ' Сбрасываем счётчик принятых символов USART_0
    Usart_0_flag_data_input = 0
    Usart_0_flag_resived_usart = 0
    Enable Urxc
'-------------------------------------------------------------------------------
  Return
'===============================================================================


'===============================================================================
  Usart_0_input_data:
'-------------------------------------------------------------------------------
    !Push R16
    !In R16 , Sreg
    !Push R16
    !push R17
    !push R26
    !push R27

    !IN R17 , UDR0

   'Проверка на BootLoader
    !cpi R17 , 123
    !BREQ Apply_bootloader       'Перейти если равно

   'Если не BootLoader принимаем все символы
    !ldi R16 , 1
    !sts {Usart_0_flag_resived_usart} , R16

'    !cpi R17 , 13       'Если приняли "конец строки"
'    !BREQ Exit_input_data_usart

'    !cpi R17 , 10       'Если приняли "перевод каретки"
'    !Breq Copy_bufer_usart       'Input_sumbol

   Input_sumbol:
    Loadadr Temp_usart_0_input_buffer_str , X
    !lds R16 , {usart_0_count_received_symbols}
    !add R26 , R16
    !clr R16
    !adc R27 , R16

    !ST X , R17

    !lds R16 , {Usart_0_count_received_symbols}
    !inc R16
    !sts {Usart_0_count_received_symbols} , R16

    !cpi R16 , Usart_0_amount_rxd_symbols       'Если приняли нужное количество символов
    !BRSH Copy_bufer_usart       'Перейти если равно или больше

   Exit_input_data_usart:

    !pop R27
    !pop R26
    !pop R17
    !pop R16
    !Out Sreg , R16
    !Pop R16

    !reti
'-------------------------------------------------------------------------------
  Return
'===============================================================================
  Copy_bufer_usart:
'-------------------------------------------------------------------------------
   'Запрещаем прерывания от RxD
    !lds R16 , Ucsr0b
    !andi R16 , &B_0111_1111
    !sts Ucsr0b , R16

    !push R18
    !push R30
    !push R31

    Loadadr Temp_usart_0_input_buffer_byte(1) , X
    Loadadr Usart_0_input_buffer_byte(1) , Z
    !lds R16 , {usart_0_count_received_symbols}
    !ldi R18 , 0

   Repeat_copy_sumbol:
    !ld R17 , X       'Забираем данные
    !st X+ , R18       'Пишем "0"
    !st Z+ , R17       'Сохраняем данные
    !dec R16
    !brne Repeat_copy_sumbol

    !pop R31
    !pop R30
    !pop R18

    !sts {Usart_0_flag_resived_usart} , R18
    !ldi R18 , 1
    !sts {Usart_0_flag_data_input} , R18
    !rjmp Exit_input_data_usart

'===============================================================================
  Apply_bootloader:
'-------------------------------------------------------------------------------
    Config Watchdog = 16
    Reset Watchdog
    Start Watchdog

    Wait 1
'-------------------------------------------------------------------------------
  Return
'===============================================================================

передатчик

$regfile = "m328pdef.dat"
$crystal = 18432000
$hwstack=16
$swstack=16
$framesize=32

$baud = 230400
Ucsr0a.1 = 1       ' Двойная скорость работы USART, скорость трансляции = $baud * 2

'===================================================================

Waitms 100
'===================================================================
Dim a As Byte
Dim b As Byte
Dim snd(25) As Byte

'===================================================================
'Строка для передачи - F8041409368BF800017A7D0003073D000001F4005F0000930E

Snd(1) = &HF8
snd(2) = &H04
snd(3) = &H14
Snd(4) = &H09
snd(5) = &H38
snd(6) = &H8B
snd(7) = &HF8
snd(8) = &H00
snd(9) = &H01
snd(10) = &H7A
snd(11) = &H7D
snd(12) = &H00
snd(13) = &H03
snd(14) = &H07
snd(15) = &H3D
snd(16) = &H00
snd(17) = &H00
snd(18) = &H01
snd(19) = &HF4
snd(20) = &H00
snd(21) = &H5F
snd(22) = &H00
snd(23) = &H00
snd(24) = &H93
snd(25) = &H0E

'===================================================================
Do

For a = 1 To 25
      b = snd(a)
      Printbin b;
Next a

Waitms 5

Loop
End
'===================================================================

http://s9.uploads.ru/t/vTorR.jpg

+1

111

Осталось только выбрать наиболее приемлемый вариант... ;)

0

112

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

Осталось только выбрать наиболее приемлемый вариант...

При всём уважении к Александру я вижу несколько отрицательных моментов в его коде.
1. Довольно громоздкий код.
2. Окончание приёма должно определяться конкретным символом, что не всегда возможно. Ну не даёт устройство такого символа в конце строки и всё тут.
3. Ассемблер конечно это круто и хорошо, но не каждый пользователь способен в нём разобраться и внести в код свои особенности.
4. Я не сторонник использования таких длинных названий переменных от которых рябит в глазах. Может я и консерватор, но в моё время длина
имени переменной не могла превышать 8 символов, что и наложило отпечаток на моё восприятие кода. 8-)

Для примера я бы сделал так.
Не Const_baud_usart_0, а просто Baud_0.
Не Usart_0_input_const_size_buffer, а просто InputBuffer_0 и т.д.

Тогда строка Dim Temp_usart_0_input_buffer_str As String * Usart_0_input_const_size_buffer превратилась бы в строку Dim InputBuffer_Str_0 * InputBuffer_0
Мне кажется, что так было бы проще, но это моё личное мнение.

0

113

sva-don написал(а):

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


C чего это вдруг, в этом варианте конец приёма по количеству принятого !

Сколько здесь - Const Usart_0_amount_rxd_symbols = 25       'Количество принимаемых символов

столько и принимаем, независимо от того, что передаётся в пределах ( 0...255; &H00...&HFF; &B_0000_0000...&B_1111_1111 )

sva-don написал(а):

Довольно громоздкий код


Зато скорость и полный контроль

0

114

sva-don написал(а):

Я не сторонник использования таких длинных названий переменных

Вероятно это сделано для того чтобы не было повторений имен переменных при объединении частей кода. Обычно в языках программирования для этого предусмотрено пространство имен.
Но баском его не поддерживает как и многие другие языковые конструкции и приходится писать как получается.

0

115

sva-don написал(а):

Довольно громоздкий код.

Мой вариант - самый короткий... ;)
Принимает заявленные 25 значений безошибочно.
Проверялись разные "наборы", даже "10 00... все "нули" ...00 01" - всё байтик к байтику... ;)
Просто в выложенном примере использована уже известная тут цепочка.

Не тяну на себя одеяло, как будет работать в теле программы, где не только прием и разбор этой строки еще не проверял (светодиодики не в счет).

0

116

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

C чего это вдруг, в этом варианте конец приёма по количеству принятого !

Сколько здесь - Const Usart_0_amount_rxd_symbols = 25       'Количество принимаемых символов

Ну вот например опишу такой пример:
В моём устройстве самый короткий ответ от модуля 2 байта, тупо слово "ОК", а самый длинный может достигать 255 байт, при этом количество пришедших к МК байт заранее неизвестно. :dontknow:
Вот как тут быть?
Вот реальный ответ от модуля:
http://sh.uploads.ru/t/asUd3.jpg
Причём каждая строка начинается и заканчивается символами CR LF.

Отредактировано sva-don (2019-07-11 15:08:57)

0

117

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

Принимает заявленные 25 значений безошибочно.

И что это мы привязались именно к 25 символам.  o.O

0

118

sva-don написал(а):

В моём устройстве самый короткий ответ от модуля 2 байта, тупо слово "ОК", а самый длинный может достигать 255 байт, при этом количество пришедших к МК байт заранее неизвестно


Если не ошибаюсь, то речь шла о 25 байтах без (13; 10).

А у Вас кроме полезностей ещё и завершение строки.

В общем, от задачи зависит решение.

Универсальность - чистый Bascom
Скорость и прозрачность - ASM

0

119

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

Скорость и прозрачность - ASM

Со скоростью согласен, с прозрачностью не очень.  :disappointed:

0

120

sva-don написал(а):

с прозрачностью не очень


Аргументируйте ?

0