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

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

  • ===================================== Справочник по программированию «Bascom-8051» == 18. Программирование аналоговых преобразователей

  • Справочник по программировани 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
    КатегорияПромышленность. Энергетика
    страница14 из 25
    1   ...   10   11   12   13   14   15   16   17   ...   25
    ===================================== Справочник по программированию «Bascom-8051» ==
    'теперь буфер пуст и его уже нельзя испортить 'инициализировать систему
    B_entx = 1 : B_nd = 0 : B_sd = 1 : Cnt = 0 : Rang = 0 : Udac = 0
    R_bui = Varptr(inp_buf) 'указатель буфера на начало
    Mc:
    Do 'главный цикл
    If B_nd = 1 Then 'активизируется по приходу сообщения
    Reset B_nd : Goto N_dat
    End If
    If B_sd = 1 Then 'активизируется при необходимости передачи
    Goto S_dat
    End If
    'Idle
    Loop
    '------------------------------------------
    'обработка принятых данных
    N_dat:
    Temp = Left(inp_buf , 1) 'выделим первый символ для анализа '-----
    If Temp = "R" Then 'запрос состояния?
    Set B_sd : Goto Mc 'строка обработана - в главный цикл
    End If
    '-----
    If Temp = "L" Then 'данные ЦАП?
    Temp = Mid(inp_buf , 2 , 5)
    Udac = Val(temp) 'преобр. строку в число с полярностью
    Gosub Sload_766 'загрузим ЦАП
    Goto Mc 'строка обработана - в главный цикл
    End If
    '-----
    If Temp = "S" Then 'данные режима?
    Temp = Mid(inp_buf , 2 , 1)
    Rang = Val(temp) 'преобразуем строку в число
    P2 = Rang 'загрузим в порт P2
    Goto Mc 'строка обработана - в главный цикл
    End If
    Goto Mc
    '------------------------------------------
    'обработка данных на вывод
    S_dat:
    If B_entx = 1 Then 'начнем, если передача разрешена
    Reset B_sd 'сбрасываем бит, вызв. передачу
    Reset B_entx 'и запр. передачу до полн. Выв. буфера 'Формируем строку состояния системы: "SxLxxxxxTxxx,ВК,ПС"
    Out_buf="S"+Str(rang)+"L"+Str(udac)+"T"+Str(cnt)+Chr(13)+Chr(10)
    R_buo = Varptr(out_buf) 'указатель буфера на начало
    Tmp = Peek(r_buo) : Sbuf = Tmp 'первый символ на передачу 'этой операцией инициализируем систему вывода по прерыванию 'остальные символы буфера будут выводиться автоматически
    Incr R_buo поставим указатель буфера на второй символ
    End If
    Goto Mc
    '---------------------
    'подпрограмма загрузки данных в ЦАП AD766, AD1851
    Sload_766:
    'выдвинуть данные из Udac в режиме 0 (ст. сначала , -_-)
    Shiftout B_datu , B_clku , Udac , 0
    Reset B_ldu : Set B_ldu 'загрузить данные
    Return
    '----------------------------------------------
    'обработка прерывания таймера 0
    Timer_0_int:
    $asm
    =============================================================================
    17-3

    ===================================== Справочник по программированию «Bascom-8051» ==
    Mov Th0 , #&HD8
    Mov Tl0 , #&HFD ;уст. периода прерыв. 10 мс
    $end Asm
    Incr Cnt 'считаем прерывания
    Return
    '----------------------------------------------
    'обработка прерывания последовательного интерфейса
    Ser_int:
    $asm
    Jbc {Ri} , Intsr ;ищем источник прерывания
    Jbc {Ti} , Intst ;заодно и сбрасываем бит вызвавший прерывание
    $end Asm
    Return
    $asm
    ; прерывание приемника
    Intsr:
    Push Psw
    Push Acc
    Mov {R_ch} , Sbuf ;сохранить принятый символ
    Mov A , {R_ch}
    Ints1:
    Cjne A , #&h0d , Ints3
    Setb {B_nd} ;0Dh - принята строка
    Ints2:
    Mov A , {R_bui} ;указатель буфера
    Xch A , R0 ;сохранить R0
    Mov @R0 , #&h00 ;записать в буфер конец строки
    Xch A , R0 ;восстановить R0
    Mov {R_bui} , #{inp_buf} ;переинициализировать указатель буфера
    Intse:
    Pop Acc
    Pop Psw
    Reti
    Ints3:
    Cjne A , #&h0a , Ints4
    Sjmp Intse ;0Ah - игнорировать
    Ints4:
    Mov A , #{inp_buf + 10}
    Cjne A , {R_bui} , Ints5
    Sjmp Intse
    Ints5:
    Mov A , {R_bui} ;указатель буфера
    Xch A , R0
    Mov @R0 , {R_ch} ;все остальное записывать в буфер
    Xch A , R0
    Inc {R_bui} ;если буфер незаполнен - изменим указатель
    Sjmp Intse
    ; прерывание передатчика
    Intst:
    Push Psw
    Push Acc
    Mov A , {R_buo} ; считаем символ из буфера вывода
    Xch A , R0
    Mov {R_ch} , @R0
    Xch A , R0
    Mov A , #{out_buf + 10} ;если это произошло за пределами буфера
    Cjne A , {R_bui} , Ints6 ;заканчиваем сообщение
    Sjmp Ints7
    Ints6:
    Mov A , {R_ch} ; очередной символ равен 0?
    Jz ints7
    Mov Sbuf , {R_ch}
    Inc {R_buo} ; изменим указатель буфера вывода
    =============================================================================
    17-4

    ===================================== Справочник по программированию «Bascom-8051» ==
    Sjmp Intse
    Ints7:
    Setb {B_entx} ; установим указатель разрешения передачи
    Sjmp Intse ; вначале символа "возврат каретки"
    $end Asm
    '------------------------------------------
    Для многих систем оказывается достаточным компромиссное решение, когда по прерыванию осуществляется только ввод данных, которые могут поступать в произвольный момент времени, а вывод данных производится прямо из главной программы с помощью оператора Print. При этом программы вывода данных и программа прерываний приобретают другой вид и упрощаются. В примере, приведенном выше, при этом также становятся ненужными переменные B_entx, R_bui и Out_buf. Упрощается фрагмент в стартовом блоке программы:
    Enable Serial 'разрешить прерывания посл.интерфейса
    Print "Test_com"
    'инициализировать систему
    Программа формирования и вывода строки состояния также может быть построена проще:
    '------------------------------------------
    'обработка данных на вывод
    S_dat:
    'сбрасываем бит, вызвавший передачу и печатаем строку состояния системы:
    ' "SxLxxxxxTxxx,ВК,ПС"
    Reset B_sd : Print "S" ; Rang ; "L" ; Udac ; "T" ; Cnt
    Goto Mc
    При этом больше всего изменяется программа обработки прерывания последовательного интерфейса. Она также упрощается и в ней необходимо обрабатывать только прерывание приемника. Бит Ti теперь обрабатывается внутри оператора Print. В состав новой подпрограммы прерывание дополнительно введен полезный модуль преобразования строчных латинских символов в прописные.
    '------------------------------------------
    'обработка прерывания последовательного интерфейса
    Ser_int:
    $asm
    Jbc {Ri} , Intsr
    Reti
    Intsr:
    Push Psw ;прерывание приемника
    Push Acc
    Mov {R_ch} , Sbuf ;сохранить принятый символ
    Mov A , {R_ch} ;преобразуем малый символ в большой
    Add A , #&h9f ;код символа 'a'? (нижняя граница)
    Jnc Ints0 ;(.not.'a'+1)
    Mov A , {R_ch} ;код символа 'z'? (верхняя граница)
    Add A , #&h85 ;(.not.'z')
    Jc Ints0
    Mov A , {R_ch} ;скорректировать
    Anl A , #&hdf
    Mov {R_ch} , A
    Sjmp Ints1
    Ints0:
    Mov A , {R_ch}
    Ints1:
    Cjne A , #&h0d , Ints3
    Setb {B_nd} ;0Dh - принята строка
    Ints2:
    Mov A , {R_bui} ;указатель буфера
    Xch A , R0 ;сохранить R0
    Mov @R0 , #&h00 ;записать в буфер конец строки
    Xch A , R0 ;восстановить R0
    Mov {R_bui} , #{inp_buf} ;переинициализировать указатель буфера
    Intse:
    Pop Acc
    Pop Psw
    =============================================================================
    17-5

    ===================================== Справочник по программированию «Bascom-8051» ==
    Reti
    Ints3:
    Cjne A , #&h0a , Ints4
    Sjmp Intse ;0Ah - игнорировать
    Ints4:
    Mov A , #{inp_buf + 10}
    Cjne A , {R_bui} , Ints5
    Sjmp Intse
    Ints5:
    Mov A , {R_bui} ;остальное записывать в буфер
    Xch A , R0
    Mov @R0 , {R_ch}
    Xch A , R0
    Inc {R_bui}
    Sjmp Intse
    $end Asm
    '------------------------------------------
    Далее рассмотрим программу, в которой вообще не используется прерывание. Это программа является частью классического монитора, обеспечивающего просмотр памяти в текстовом виде и HEX-кодах. Ядро этой программы может служить основой многих других инструментальных программ. Это медленная программа, которая, исполнив команду или совершив действие, находится в режиме ожидания прихода символа в последовательный канал.
    '--------------------------------------------------------------
    'Демонстрационная программы монитора, работающего 'через последовательный канал.
    '--------------------------------------------------------------
    $large 'большая модель памяти
    Dim Tmp As Byte 'временные байтовые данные
    Dim R_ch As Byte 'принятый или передаваемый символ
    Dim L_adr As Word 'начальный адрес
    Dim H_adr As Word 'конечный адрес
    Dim S_adr As Word 'текущий адрес
    Dim Big_buf As String * 64 'большой буфер ввода-вывода '---------------------
    'TIMER2 в режиме 16-бит. таймера с внутр. тактир. для синхронизации UART
    Config Timer2 = Timer , Gate = Internal , Mode = 2
    $baud = 9600 'скорость 9.6 кБ
    $crystal = 12000000 'при кварце 12 МГц '---------------------
    Print "Monitor" 'выведем стартовое сообщение
    Goto Begin 'на начало
    _error: 'точка входа по ошибке
    Gosub Dis_err 'перевод строки и сообщение об ошибке
    Begin:
    ' выведем приглашение "BC>" без разделителей ВК и ПС
    Gosub _promt
    R_ch = Waitkey 'ждать ввода символа
    If R_ch = &H0D Then 'это символ ВК?
    Goto Ignore 'да - его нельзя печатать
    End If
    Beg1:
    Printbin R_ch 'вывести введеный символ в той же строке!
    Select Case R_ch 'выбрать программу обработки
    Case &H44 : Goto Dump_mem 'это символ D?
    Case &H4C : Goto List_mem 'это символ L?
    Case &H48 : Goto Help 'это символ H?
    Case Else : Goto _error 'все остальное воспринимается как ошибка
    End Select
    ' внимание! важный момент - обработка символа ВК.
    ' он может приходить в паре с символом ПС, который нужно игнорировать ' а может быть это уже следующая команда или опять символ ВК
    =============================================================================
    17-6

    ===================================== Справочник по программированию «Bascom-8051» ==
    Ignore:
    Waitms 50 'ждем прихода второго символа 50 мс
    R_ch = Inkey 'опрашиваем входной буфер
    If R_ch = 0 Then 'если считали нуль, значит буфер пустой
    Goto _error 'можно индицировать сообщение об ошибке
    Elseif R_ch = &H0A Then 'пришел ПС
    Goto _error 'тоже считаем, что ошибка
    Elseif R_ch = &H0D Then 'если опять пришел ВК
    Goto Ignore 'значит все повторить
    End If 'остальное - считаем это простым вводом
    Gosub Dis_err 'перевод строки и сообщение об ошибке
    Gosub _promt 'вывод приглашения
    Goto Beg1 'и на обработку новой команды '--------------------------------------------------------------
    'вывести содержимое памяти в HEX-коде
    Dump_mem:
    Print " - Damp of memory" 'расшифровать название команды
    Gosub Inp_ladr : Gosub Inp_hadr 'введем адреса нач. и конца блока
    S_adr = L_adr 'текущий адрес начнем с начального
    D_mem0:
    Big_buf = Hex(s_adr) + " " 'адрес начала строки данных
    Goto D_mem2 'переход при первом входе
    D_mem1:
    Tmp = Low(s_adr) 'анализируем: младшие разряды адреса?
    If Tmp = 0 Then 'равны нулю - начать новый блок
    Gosub E_cnk 'запросить: продолжать или выйти?
    If R_ch = &H1B Then 'если введен ESC,
    Goto Begin 'выйти
    End If
    End If
    Tmp = Tmp And &H0F 'анализируем:
    If Tmp = 0 Then 'младший полубайт равен 0?
    Print Big_buf 'да - печатать буфер
    Goto D_mem0 'и в начало следующей строки
    End If
    D_mem2:
    Tmp = Cpeek(s_adr) 'считывание из памяти
    Big_buf = Big_buf + " " + Hex(tmp) 'и добавим изображение в буфер
    Incr S_adr 'изменим текущий адрес
    If S_adr > H_adr Then 'он достиг верхней границы?
    Goto D_mem3 'да - на выход
    End If
    Goto D_mem1 'нет - повторить
    D_mem3:
    Print Big_buf 'перед выходом отпечатам последнюю строку
    Goto Begin
    '--------------------------------------------------------------
    'вывести содержимое памяти в в текстовом виде
    List_mem:
    Print " - List of memory" 'расшифровать название команды
    Gosub Inp_ladr : Gosub Inp_hadr 'ввести границы просмотра
    S_adr = L_adr 'текущий адрес в начало блока
    L_mem0:
    Big_buf = Hex(s_adr) + " " 'формируем начальный адрес данных с строке
    Goto L_mem2 'переход при первом входе
    L_mem1:
    Tmp = Low(s_adr) 'анализируем: младшие разряды адреса?
    If Tmp = 0 Then 'равны нулю - начать новый блок
    Gosub E_cnk 'запросить: продолжать или выйти?
    If R_ch = &H1B Then 'если введен ESC, выйти
    Goto Begin
    End If
    End If
    =============================================================================
    17-7

    ===================================== Справочник по программированию «Bascom-8051» ==
    Tmp = Tmp And &H0F 'анализируем:
    If Tmp = 0 Then ' младший полубайт равен 0
    Print Big_buf 'да - печатать буфер
    Goto L_mem0 'и в начало следующей строки
    End If
    L_mem2:
    Tmp = Cpeek(s_adr) 'считывание байта из памяти
    If Tmp > 127 Then 'непечатные символы преобразуем в точку
    Tmp = &H2E 'с кодами выше 7fh
    Elseif Tmp < &H20 Then 'и также с кодами ниже 20h
    Tmp = &H2E 'это пример использования оператора Elseif
    End If
    Big_buf = Big_buf + Chr(tmp) 'добавим символ
    Incr S_adr 'переходим к следующему адресу
    If S_adr > H_adr Then 'проверим: не перешли верхнюю границу
    Goto L_mem3 'да - переход
    End If
    Goto L_mem1 'нет - повторим
    L_mem3:
    Print Big_buf 'печать буфера перед выходом
    Goto Begin
    '--------------------------------------------------------------
    'выдать таблицу помощи
    Help:
    Print ""
    Print " ------ MONITOR ------ "
    Print "| D - Display memory |"
    Print "| L - List memory |"
    Print "| H - This help |"
    Print " --------------------- "
    Print ""
    Goto Begin
    '--------------------------------------------------------------
    'подпрограммы: все, что повторяется более одного раза '--------------------
    'ввод начального адреса
    Inp_ladr:
    Inputhex "Begin=" , L_adr : Return
    '--------------------
    'ввод конечного адреса
    Inp_hadr:
    Inputhex "End=" , H_adr : Return
    '--------------------
    'запрос: выйти или продолжать?
    E_cnk:
    Print "Exit - Esc, Continue - any key"
    R_ch = Waitkey : Return 'ждем ввода символа '--------------------
    'перевод строки и сообщение об ошибке
    Dis_err:
    Print "" : Print "Error" : Return
    '--------------------
    'вывод приглашение "BC>" без символов ВК ПС
    _promt:
    Printbin &H42 ; &H43 ; &H3E : Return 'запишем коды символов '--------------------------------------------------------------
    End
    В приведенных программах даны примеры использования почти всех операторов, работающих с последовательным портом. При программировании вывода некоторые неудобства доставляют операторы, завершающие передаваемое сообщение разделителем (ВК ПС). Для устранения этого явления, недопустимого при выводе составных сообщений, применяется буфер, в котором формируется результирующая строка, или используется оператор Printbin.
    =============================================================================
    17-8

    ===================================== Справочник по программированию «Bascom-8051» ==
    Другая проблема вывода данных заключается в том, что иногда требуется включение в выдаваемое сообщение цифровых данных в форматированном виде. Для решения этой задачи необходимо использовать те же приемы, что и при выводе данных в символьный LCD-модуль.
    =============================================================================
    17-9

    ===================================== Справочник по программированию «Bascom-8051» ==
    18. Программирование аналоговых преобразователей
    К аналоговым преобразователям, программирование которых будут рассмотрено ниже, относятся аналого-цифровые (АЦП), цифро-аналоговые преобразователи (ЦАП). К АЦП также можно отнести все схемы преобразования аналогового сигнала в частоту или длительность с устройством измерения частоты или периода. К устройствам ЦАП также относятся всевозможные регуляторы уровня, цифровые синтезаторы частоты, генераторы широтно-импульсной модуляции и даже просто управляемые генераторы частоты. Принципиальное различие
    АЦП и ЦАП с точки зрения программиста, независимо от того с каким аналоговым сигналом работает устройство, заключается в направлении передачи и порядке преобразования данных. При работе с АЦП данные считываются и после многократного преобразования приобретают вид, понятный наблюдателю или субъекту, принимающему решение. Очевидные данные ЦАП, напротив, должны многократно преобразовываться перед загрузкой преобразователь. Задачи и проблемы программирования ЦАП и АЦП можно сформулировать следующим образом: а) организация работы программы преобразования; б) обеспечение интерфейса ЦАП или АЦП с процессором; в) выбор формы представления цифрового значения измеряемого или устанавливаемого параметра; г) преобразование из кода АЦП в формат пригодный для вычисления и преобразование устанавливаемого значения в код загрузки ЦАП д) оптимальная цифровая калибровки преобразователей; е) накопление, усреднение и вывод данных АЦП; ж) ввод и подготовка данных ЦАП; з) ускорение принятия решений на основании данных АЦП.
    Рассмотрим эти задачи подробнее в том же порядке. Начнем с организации работы программы – с выбора двигателя. Для приведения в действия любой программы, работающей с аналоговыми устройствами, всегда нужен какой-то двигатель. В роли двигателя может выступать: а) внешнее событие, например, приход команды с клавиатуры или из внешнего интерфейса на установку нового значения воспроизводимого параметра (или запрос измеренных данных). Обычно, таким образом, работают системы с ЦАП; б) команда от таймера, задающего периодичность операций установки, смены или измерения параметров системы. Системы с периодически воспроизводимым циклом преобразования характерны для измерительных устройств, например, таких как цифровой вольтметр, и применяются наиболее часто; в) команда измерительного устройства о готовности данных. Самый характерный пример таких систем – устройства, в основе которых лежит медленный АЦП (интегрирующего типа). Привязка всех системы к медленному АЦП является лучшим решением, позволяющим исключить нежелательные переходные процессы и разрывы потока данных. Основной недостаток подобных систем возможность остановки программы при перегрузке или отказе измерительного устройства (впрочем, легко устранимый); г) команда другой программы, являющейся ведущей или передающей запрос на действие по цепочке. С точки зрения измерительной программы, такая команда является внешней, однако относительно системы в целом могут быть и другие механизмы приведения ее в действие, в том числе, и упомянутые выше.
    При планировании взаимодействия других частей программы с измерительной необходимо учитывать время исполнения каждой из них. Например, недопустимо, если обработка и вывод (всегда обращайте внимание на время вывода!) измеренных данных, выполняемых в измерительной цикле, превышает время готовности данных АЦП. Также недопустимо, если частота измерения АЦП меньше частоты считывания данных из него. Все это приводит к потере данных и появлению неявной погрешности измерения. Аналогично, нужно учитывать реальное время установления воспроизводимого параметра, задаваемого с помощью ЦАП. Причем учитывать не время установления выходного сигнала ЦАП, а время установления всей аналоговой схемы (если такая есть).
    Периодичность загрузки ЦАП должна быть намного больше электрической постоянной времени аналоговой части схемы. Также, время обработки устанавливаемых данных и загрузки кода в ЦАП не должно превышать период повторения операций загрузки.
    Рассмотрим с проблему интерфейса. Почти всегда АЦП или ЦАП, с которыми работает микроконтроллер, являются однокристальными устройствами. Номенклатура этих устройств, чрезвычайно широка и всегда, за исключением особых случаев, может быть выбрана модель, удовлетворяющая метрологическим требованиям, скорости, конфигурации входа (выхода) и напряжению питания. Выбранный по указанным критериям, преобразователь чаще оказывается с последовательным портом. В результате возникают сложности достижения высокого быстродействия при считывании (записи) данных. Это обусловлено отсутствием большинства у процессоров семейства 8051 высокоскоростного аппаратного последовательного порта, а с другой стороны использование АЦП и ЦАП с параллельным портом также не всегда возможно из-за дефицита свободных линий портов. Таким образом, задача интерфейса сводится к программному формированию сигналов управления на выводах преобразователя и перемещению данных из регистров процессора в устройство или наоборот. В общем случае, создание программы считывания (из АЦП) и тем более записи данных (в ЦАП) с помощью операторов Bascom не представляет большой сложности. Для этого предусмотрены операторы SHIFTIN,
    =============================================================================
    18-1

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


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