Главная страница
Навигация по странице:

  • ===================================== Справочник по программированию «Bascom-8051» ==

  • ===================================== Справочник по программированию «Bascom-8051» == 17. Программирование последовательного порта

  • Справочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001). Справочник по программированию bascom8051 Краснодар 2001


    Скачать 6.61 Mb.
    НазваниеСправочник по программированию bascom8051 Краснодар 2001
    АнкорСправочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001).pdf
    Дата26.04.2017
    Размер6.61 Mb.
    Формат файлаpdf
    Имя файлаСправочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001).pdf
    ТипСправочник
    #5699
    КатегорияПромышленность. Энергетика
    страница13 из 25
    1   ...   9   10   11   12   13   14   15   16   ...   25
    ===================================== Справочник по программированию «Bascom-8051» ==
    Lcd_od:
    Lcd Temp 'наконец выводим цифровое значение
    Gosub Lcd_attr2 'и добавляем размерность показаний
    Goto Mc
    '--------------------------------------------------------------
    'обработка прерывания таймера 0
    Timer_0_int:
    $asm
    Mov Th0 , #&HD8
    Mov Tl0 , #&HFD ;уст. периода прерыв. 10 мс
    $end Asm
    Set B_tim 'прошло 10 мс
    Return
    '--------------------------------------------------------------
    'подпрограмма вывода сообщения о режиме работы
    Lcd_attr1:
    Temp = Lookupstr(rang , _tab_att1) 'считали из таблицы
    Locate 1 , 1 : Lcd Temp : Lcd ":" 'вывели и добавили двоеточие
    Return
    '--------------------------------------------------------------
    'подпрограмма вывода сообщения о размерности показаний
    Lcd_attr2:
    Temp = Lookupstr(rang , _tab_att2) 'считали из таблицы
    Locate 1 , 13 : Lcd Temp 'вывели
    Return
    '--------------------------------------------------------------
    ' форматы отображения данных мультиметра 'DCV: ±000.00 mV ±0.0000 V ±00.000 V ±000.00 V ±0000.0 V
    'ACV: 000.00 mV 0.0000 V 00.000 V 000.00 V 0000.0 V
    'Ohm: 000.00 W 0.0000 kW 00.000 kW 000.00 kW 0.0000 MW
    'DCI: ±000.00 uA ±0.0000 mA ±00.000 mA ±000.00 mA ±0.0000 A
    'ACI: 000.00 uA 0.0000 mA 00.000 mA 000.00 mA 0.0000 A
    '--------------------------------------------------------------
    'подпрограммы форматирования показаний положительной полярности
    F2:
    Temp = Fusing(rfld , #.####) : Return
    F3:
    Temp = Fusing(rfld , ##.###) : Return
    F4:
    Temp = Fusing(rfld , ###.##) : Return
    F5:
    Temp = Fusing(rfld , ####.#) : Return
    'подпрограммы форматирования показаний отрицательной полярности 'требуется дополнительное место перед цифрами для знака минуса.
    M2:
    Temp = Fusing(rfld , ##.####) : Return
    M3:
    Temp = Fusing(rfld , ###.###) : Return
    M4:
    Temp = Fusing(rfld , ####.##) : Return
    M5:
    Temp = Fusing(rfld , #####.#) : Return
    '--------------------------------------------------------------
    ' значения первого аттрибута - режима измерений
    _tab_att1:
    Data "DCV" , "DCV" , "DCV" , "DCV" , "DCV"
    Data "ACV" , "ACV" , "ACV" , "ACV" , "ACV"
    Data "Ohm" , "Ohm" , "Ohm" , "Ohm" , "Ohm"
    Data "DCI" , "DCI" , "DCI" , "DCI" , "DCI"
    Data "ACI" , "ACI" , "ACI" , "ACI" , "ACI"
    '--------------------------------------------------------------
    ' управление отображением полярности: 0 - нет, 1 - есть
    _tab_polar:
    =============================================================================
    16-4

    ===================================== Справочник по программированию «Bascom-8051» ==
    Data 1 , 1 , 1 , 1 , 1
    Data 0 , 0 , 0 , 0 , 0
    Data 0 , 0 , 0 , 0 , 0
    Data 1 , 1 , 1 , 1 , 1
    Data 0 , 0 , 0 , 0 , 0
    '--------------------------------------------------------------
    ' значения второго аттрибута - размерности показаний
    _tab_att2:
    Data " mV" , " V" , " V" , " V" , " V"
    Data " mV" , " V" , " V" , " V" , " V"
    'формируем формат строковых констант с дополнительным нулем данных 'это константы: " W", " kW", " kW"
    Data &H20 , &H20 , 2 , 0 , &H20 , 107 , 2 , 0 , &H20 , 107 , 2 , 0
    'это константы: " kW", " MW". W - это символ Омега (код 2)
    Data &H20 , 107 , 2 , 0 , &H20 , 77 , 2 , 0
    Data " uA" , " mA" , " mA" , " mA" , " A"
    Data " uA" , " mA" , " mA" , " mA" , " A"
    '--------------------------------------------------------------
    'масштабирующие коэффициенты, преобразующие размерность данных 'к размерности отображаемых данных с другим положение дес.точки
    _tab_zc:
    Data 1000! , 1! , 1! , 1! , 1! 'из Вольт
    Data 1000! , 1! , 1! , 1! , 1! 'из Вольт
    Data 1000! , 1! , 1! , 1! , 0.001! 'из килоом
    Data 1000! , 1! , 1! , 1! , 0.001! 'из миллиампер
    Data 1000! , 1! , 1! , 1! , 0.001! 'из миллиампер '--------------------------------------------------------------
    'иммитируемые измеренные значения в соответствующей размерности
    _tab_mes:
    Data 0.001! , -1.9999! , -1.999! , 199.99! , 1999.9! 'DCV: Вольт
    Data 0.001! , 0.0123! , 10.000! , 100.00! , 1000.0! 'ACV: Вольт
    Data 0.09999! , 1.9999! , 19.9! , 199.99! , 1999.9! 'Ohm: Килоом
    Data 0.20000! , -2.0000! , -20.0! , -19.00! , 20.0! 'DCI: Миллиампер
    Data 0.12345! , 1.2345! , 12.345! , 123.45! , 1234.5! 'ACI: Миллиампер '--------------------------------------------------------------
    При программировании вывода на индикатор (и вывода в COM-порт тоже) нужно учитывать, что всегда имеет место погрешность представления чисел в формате с плавающей точкой. Погрешность также возникает после арифметических действий и преобразований в результате неопределенности младшего разряда мантиссы, который или теряется, или округляется. Значение погрешности обычно не превышает ±0.000012 %, и намного ниже погрешности отображаемых данных. При отображении измеренных (или других определяемых) данных и записанных в формате с плавающей точкой, погрешность представления чисел не имеет большого значения, т.к. этого не видно. Однако, при индикации задаваемых значений чисел, например, с помощью оператора INPUT и представленных в переменных типа Single, с этим могут возникать проблемы. Например, введенное число 100 после обработки на индикаторе будет записано, как 99.999993. С точки зрения математики, ничего страшного не произошло, но для наблюдателя это явление очень неприятно и, зачастую, непонятно. Более того, будучи отформатировано, отображаемое значение приобретет вообще недопустимый вид. Например, если, указанное выше, число 100 записать без дробной части, то получится 99. Чтобы исключить подобные неприятности, следует применять округление чисел перед форматированием. Самый простой метод округления заключается в добавлении к числу значения равного половине младшего отображаемого разряда. В нашем примере, чтобы получить правильное изображение, нужно к числу 100 добавить число 0.5. Во многих случаях, округляющая добавка может быть значительно меньше и, вообще, приближаться к погрешности представления числа. Так как для округления используется операция суммирования, то нужно учитывать и знак округляемого числа.
    Рассмотрим еще один способ форматирования выводимых чисел, применимый при малом числе отображаемых разрядов (до пяти включительно). Этот простой способ заключается в суммировании отображаемого числа с другим, заведомо большим числом, и выделении после преобразования в символьный вид необходимой средней части. Ниже приведен пример, демонстрирующий этот метод и округление для придания изображению строгого вида.
    Dim R_fld As Single 'индицируемые данные
    Dim Temp As String * 16 'временная строка
    R_fld = -345.678
    Locate 1 , 6 'курсор в позицию вывода знака
    =============================================================================
    16-5

    ===================================== Справочник по программированию «Bascom-8051» ==
    If R_fld < 0 Then 'какая полярность?
    Goto Lcd_fn 'отрицательная - переход
    End If
    'положительное: предстоит отображать число в R_fld в следующем виде: +xxx.xx
    R_fld = R_fld + 1000.005 'добавим заведо большее число и добавку округления
    Temp = Str(r_fld) 'преобразуем в строку
    Temp = Mid(temp , 2 , 6) 'выделим из середины то, что нужно – 6 символов
    Lcd "+" ; Temp 'выведем со знаком полярности
    Goto Lcd_e
    Lcd_fn:
    'отрицательное: предстоит отображать число в R_fld в следующем виде: -xxx.xx
    R_fld = R_fld - 1000.005 'добавим заведо большее число и добавку округления
    $asm
    Anl {r_fld + 3} , #&H7f ;сделаем показания безусловно положительными
    $end Asm
    Temp = Str(r_fld) : Temp = Mid(temp , 2 , 6) : Lcd "-" ; Temp
    Lcd_e:
    End
    В последних версиях компилятора расширены возможности функции Fusing. Теперь по умолчанию включается режим округления и предусмотрена возможность добавления лидирующих нулей. Однако неприятности представления отрицательных чисел остались. Когда в маску записываются лидирующие нули, то требуется записать их на один больше, чем количество выводимых цифр перед точкой. Все это демонстрирует следующий пример.
    $large
    Dim X As Single , Y As Single , Result As Single
    Dim I As Integer , Buf As String * 16
    X = 142 : Y = 3.157
    Print "X+Y=" : Result = X + Y 'вычисления
    Print Result 'печать результата "145.69977"
    Buf = Fusing(result , 000000.#) 'форматирование строки c округлением
    Print Buf 'печать строки "00145.2"
    Buf = Fusing(result , 0000.&&) 'с лидирующими нулями и без округления
    Print Buf 'печать строки "145.15"
    X = -12 : Y = 3.157
    Print "X+Y=" : Result = X + Y 'вычисления
    Print Result 'печать результата "-8.8430004"
    Buf = Fusing(result , 000000.#) 'форматирование строки c округлением
    Print Buf 'печать строки "000-8.8"
    Buf = Fusing(result , ####.&&) 'обычное, без округления
    Print Buf 'печать строки "-8.84"
    End
    =============================================================================
    16-6

    ===================================== Справочник по программированию «Bascom-8051» ==
    17. Программирование последовательного порта
    Применение последовательного асинхронного порта предусматривается в большинстве микропроцессорных систем. Даже в тех случаях, когда он не нужен для работы схемы, его используют (и необходимо использовать) на этапе отладки программы, для технологической настройки или при испытаниях.
    Последовательный порт процессора 8051 способен одновременно принимать и передавать данные, что требует такого построения программ, в которых процессы приема и передачи независимы. А вследствие того, что последовательный порт относится к разряду медленных устройств, то часто при программировании требуется осуществлять прием и передачу параллельно работе основной программы. Чтобы организовать параллельную работу программ ввода (приема), вывода (передачи) и обработки данных приходится задействовать прерывание.
    Лучше всего для этого использовать прерывание последовательно интерфейса, происходящего при заполнении регистра SBUF-приемника (после приема байта) и опустошении регистра SBUF-передатчика (после выдачи байта). Возможен и экзотический вариант временного разделения задач приема, передачи и обработки с помощью прерывания одного из таймеров. В любом случае, реализация всех возможностей и интенсивной работы последовательного порта представляется очень сложной программной задачей.
    Использование в системе последовательного интерфейса почти всегда обусловлено работой в многопроцессорной среде непосредственно или в скрытой форме, как например, при работе с COM-портом персонального компьютера. При программировании подобных интерфейсов возникают проблемы учета глобальных временных соотношений, то есть учета в текущей программе времени реакции другой системы на переданные данные и наоборот. Эти проблемы часто и напрасно игнорируются, хотя именно глобальные процессы определяют скорость взаимодействия систем, а не только физическая скорость передачи данных, как принято думать. В результате таких просчетов может быть потеряна работоспособность многопроцессорной системы только из-за изменения производительности одного компонента, например, при его модернизации. При программировании также необходимо предусматривать и возможность возникновения аварийных ситуаций в периферии одного из компонентов в момент взаимодействия.
    Следующий важный компонент программирования системы с последовательным портом - выбор протокола связи и формата данных. Считается, что чем короче передаваемое сообщение, тем лучше. В принципе это правильно, но при одном условии, что это сообщение должно быть понятным, и, самое главное, оставаться понятным в искаженном виде. Имеется в виду, не то, что в сообщении должна содержаться избыточная информация, позволяющая восстановить потерянное, а только то, что принимающая сторона должна обнаружить факт сбоя. Особенно опасно применение протоколов с чисто двоичными данными. Искажение таких данных может оказаться не только незамеченным, но и привести к потере синхронизации (опознаванию начала и конца пакетов данных). Автор продолжает настаивать на необходимость применения в протоколах только текстовых структур с разделителями в виде символов 0Dh («ВК» - возврат каретки) и 0Ah («ПС» - перевод строки). Передача данных в виде чисел, также должна производится символами. Особенно это важно для открытых систем. Причем, чем более система открыта, тем понятней должен быть язык передаваемых сообщений. За применение протоколов с текстовым форматом данных приходится платить приблизительно двукратным увеличением длины передаваемых сообщений и физическим усложнением канала связи (чтобы при необходимости скомпенсировать потерю скорости). Однако это окупает себя надежностью работы, простотой мониторинга (наблюдения) за каналом связи, отличной совместимостью со стандартными языками программирования, в том числе Bascom-
    8051.
    В проектируемой программе интерфейса, с самого начала, должен быть заложен резерв производительности (не менее чем двукратный), включающий в себя возможности расширения протокола
    (введения дополнительных команд) и запасы по скорости передачи и обработки данных, например, увеличения тактовой частоты процессора. Опыт программирования и эксплуатации микропроцессорных систем связи показывает, что почти всегда эти ресурсы оказываются востребованными - на этапе отладки для покрытия ошибок планирования, а позднее для модернизации.
    Учет указанных факторов должен проводится на этапе проектирования системы и при оптимальном решении может обеспечить значительное сокращение времени программирования и отладки, а также объем используемых ресурсов процессора. Напротив, непродуманное прямолинейное решение протокола связи и игнорирование реальных временных соотношений в системе могут привести к значительному усложнению программы, и даже невозможности завершения работы ввиду того, что раньше будут исчерпаны ресурсы процессора. Столь длинное вступление, не касающееся непосредственного программирования на языке Bascom, тем не менее, необходимо. Это обусловлено особой важностью правильного решения части программы, обеспечивающей интерфейс с другими микропроцессорами.
    Ниже предлагается программы некоторого типичного периферийного устройства, принимающего команды в виде текстовых строк и возвращающего данные также в виде текстовой строки. В программе имеются все обычные для данного случая (но немного упрощенные) компоненты: настройки системы, вхождения в стационарное состояние, декодирования и исполнения принятых сообщений, генератора событий реального времени, формирования передаваемых сообщений, системы ввода и вывода через раздельные буферы. Структура программы обеспечивает возможность параллельно (или почти параллельно) принимать и передавать данные,
    =============================================================================
    17-1

    ===================================== Справочник по программированию «Bascom-8051» == обрабатывать принятые сообщения и формировать выходные данные. Программа может быть дополнена операторами, которые позволят обрабатывать внешние события (через внешние прерывания) и совершать действия, задаваемые счетчиком реального времени. Особенностью программирования последовательного порта в данном примере является использование в прерывании подпрограмм буферированного ввода-вывода, написанных на ассемблере. Представляется, что это самый оптимальный вариант, который не ограничивает скорость работы последовательного интерфейса даже при частоте тактового генератора 3 МГц.
    '----------------------------------------------
    'Демонстрационная программа буферированного ввода-вывода данных через 'последовательный канал. Программа принимает сообщения и анализирует '----------------------------------------------
    'Если обнаруживается следующие сообщения, то:
    '"R" - выдается строка с данными состояния системы '"Lxxxxx" - загружаются данные в ЦАП
    '"Sx" - устанавливается режим 'Формат строки состояния системы: "SxLxxxxxTxxx"
    ' режим_____^ ^ ^
    ' Напряжение ЦАП_______| |
    ' Текущее время_____________|
    '----------------------------------------------
    $large 'большая модель памяти
    Dim B_nd As Bit 'бит "Приняты новые данные"
    Dim B_sd As Bit 'бит "Передать новые данные"
    Dim B_entx As Bit 'бит "Передача разрешена"
    Ri Alias Scon.0 'бит RI
    Ti Alias Scon.1 'бит TI
    Dim Rang As Byte 'регистр состояния системы
    Dim Tmp As Byte 'временные байтовые данные
    Dim Cnt As Byte 'счетчик времени
    Dim R_ch As Byte 'принятый или передаваемый символ
    Dim R_bui As Byte 'указатель буфера ввода
    Dim R_buo As Byte 'указатель буфера вывода
    Dim Udac As Integer 'регистр данных ЦАП
    Dim Temp As String * 6 'временная строка
    Dim Inp_buf As String * 10 'буфер ввода
    Dim Out_buf As String * 32 'буфер вывода '---------------------
    'подключение ЦАП AD766
    B_datu Alias P1.0 : B_clku Alias P1.1 : B_ldu Alias P1.2
    '----------------------------------------------
    Config Timer0 = Timer , Gate = Internal , Mode = 1 : Start Timer0
    '---------------------
    'TIMER2 в режиме 16-бит. таймера с внутр. тактир. для синхронизации UART
    Config Timer2 = Timer , Gate = Internal , Mode = 2
    $baud = 9600 'скорость 9.6 кБ
    $crystal = 12000000 'при кварце 12 МГц 'инициализируем регистры, определяющие режим последовательного канала
    Scon = &H52 'режим
    Rcap2h = &HFF : Rcap2l = &HD9 : Start Timer2 'скорость, только таким образом '---------------------
    On Timer0 Timer_0_int Nosave 'вектор прерывания
    On Serial Ser_int Nosave 'вектор прерывания
    Enable Interrupts 'вообще разрешить прерывания
    Enable Timer0 'разрешить прерывания таймера 0
    '!!! --------------------------------------
    B_entx = 0 : Reset Ri : Reset Ti
    Enable Serial 'разрешить прерывания посл.интерфейса
    Out_buf = "Test_com" + Chr(13) + Chr(10)
    R_buo = Varptr(out_buf) 'указатель буфера на начало
    Tmp = Peek(r_buo) : Sbuf = Tmp 'первый символ на передачу
    Incr R_buo 'укажем на второй символ 'ВНИМАНИЕ! Следующая строка принципиально важное место!
    Waitms 100 'ждем пока стартовое сообщение будет передано
    =============================================================================
    17-2

    1   ...   9   10   11   12   13   14   15   16   ...   25


    написать администратору сайта