Справочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001). Справочник по программированию bascom8051 Краснодар 2001
Скачать 6.61 Mb.
|
===================================== Справочник по программированию «Bascom-8051» == 25. Применение логических функций Сущность логических функций, очевидно, не требует пояснений, поэтому остановимся только на особенностях их применения. Логические операции производятся только над битовыми, одно-, двух- и четырехбайтовыми переменными и правильно выполняются только при одинаковой размерности исходных переменных. Использование разных типов переменных недопустимо, т.к. получаются непредсказуемые результаты, и происходит модификация регистров, не участвующих в назначенной операции. В качестве операнда логических операций могут применяться и константы. Форма записи констант должна быть “понятной” компилятору, т.к. неоднозначная запись также может дать неверный результат. Логические операции с числами с плавающей точкой не выполняются и даже не компилируются (пропускаются). К сожалению, компилятор совершенно не определяет ошибки назначения неверных операндов логических операций. Эта задача предоставлена программисту. Ниже приведена демонстрационная программа логических операций. В ней показана возможность (или невозможность) их применения и время исполнения. '---------------------------------------------------- ' Тестирование логических операций '---------------------------------------------------- $large Dim Cnt As Const 5 'число 5 Dim Bt As Bit Dim , Byt1 As Byte 'определим по паре переменных всех типов Dim Byt As Byte , Byt1 As Byte Dim Wrd As Word , Wrd1 As Word Dim Intg As Integer , Intg1 As Integer Dim Lng As Long , Lng1 As Long Dim Sng As Single , Sng1 As Single '---------------------------------------------------- Set Bt : Reset Bt1 'установить биты Bt = Bt And Bt1 : Bt = Not Bt 'операция над битами Print Bt 'вывод значения бита '---------------------------------------------------- Byt = Byt Or Bt 'это совершенно недопустимо Byt1 = Byt1 Or &HAA 'правильно Byt1 = Byt And Byt1 'правильно Wrd1 = &H1234 : Byt = &H77 : Intg = 0 Intg1 = Byt Or Wrd1 'неверно. операция произойдет 'только с младшими разрядами Intg = 1277H смотри следующую строку Intg = &H1234 : Wrd1 = &H77 Intg1 = Byt : Intg1 = Wrd1 Or Intg1 'нужно делать так 'результат: Intg = 0077H Wrd = 1234 Or 5678 'операнды десятичные константы Wrd1 = Wrd Xor 131112 'результат будет неправильным Lng = Lng Xor &H10000000 'правильно '---------------------------------------------------- Sng = -1 : Sng1 = 1000 'над числами с плав. точкой лог. оп. Sng1 = Not Sng1 'не выполняются! '---------------------------------------------------- 'производительность логических операций Byt = Byt And Byt1 '11 тактов Byt = Byt Or Byt1 '11 тактов Byt = Byt Xor Byt1 '11 тактов Wrd = Wrd And Wrd1 '20 тактов Intg = Intg And Intg1 '20 тактов Lng = Lng And Lng '93 такта End '---------------------------------------------------- ============================================================================= 25-1 ===================================== Справочник по программированию «Bascom-8051» == 26. Организация циклов и систем реального времени Bascom предлагает полный набор операторов для построения повторяющихся программ. При программировании могут применяться три основные конструкции: а) безусловный цикл, который применяется при постоянном повторении одних и тех же действий. Конструкция такого цикла строится с помощью операторов DO … LOOP и служит основой главного цикла почти каждой программы. Конструкция безусловного цикла применяется там, где требуется за один проход проверять несколько условий (точнее более одного условия); б) условный цикл повторяется, пока выполняется, определяющее его, условие. Такой цикл строится с помощью операторов WHILE … WEND. Естественно, эта конструкция может применяться реже, там, где требуется проверять выполнение единственного условия; в) условный цикл, построенный с помощью операторов DO … LOOP UNTIL, также может использоваться в ограниченных случаях, но его исполнение зависит от невыполнения условий или, наоборот, выполнение заданных условий становится причиной его прекращения. Далее, в качестве примера использования циклических конструкций, приведена упрощенная программа цифрового синтезатора частоты и с регулируемым уровнем выхода. Программа, находясь в главном цикле, ожидает прихода управляющей команды, которая должна содержать значение устанавливаемой частоты или напряжения. Определение типа команды производится по первому символу (“V” или “H”). Далее следует цифровое значение, выраженное в вольтах или килогерцах. Принятое сообщение преобразуется и направляется в исполнительные устройства: ЦАП уровня выходного напряжения, цифровой синтезатор и группу реле (или аналоговых ключей), включающих выходной фильтр, соответствующий воспроизводимой частоте. В приведенной программе используются конструкции всех видов циклов. Также имеются основные элементы системы отсчета реального времени, работающей параллельно с основной программой. Для этого введен счетчик, модифицируемый в прерывании, с периодичностью в 10 мс. Конечно, в данном примере такая система используется по ничтожному поводу – создания временной задержки, однако при необходимости ее функции можно существенно расширить, например, для формирования в портах сигналов управления заданной длительности или частоты. '------------------------------------------ ' Программа синтезатора частоты '------------------------------------------ Dim B_tim As Bit 'бит "идет счет времени" Dim Temp As Byte 'временные данные Dim R_tim As Byte 'счетчик коротких интервалов Dim Frng As Byte 'номер предела частоты Dim R_bw As Integer 'код ЦАП и 16-битные данные Dim R_bd As Long '32-битные данные Dim R_fld As Single 'напряжение или число с плавающей точкой Dim R_frq As Single 'значение частоты с плавающей точкой Dim Ibuf As String * 16 'приемный буфер '--------------------- 'подключение синтезатора AD9850 B_data Alias P3.3:B_clk Alias P3.2:B_fqud Alias P3.1:B_ress Alias P3.4 '--------------------- 'подключение ЦАП уровня AD766 B_datu Alias P1.0 : B_clku Alias P1.2 : B_ldu Alias P1.1 '--------------------- 'TIMER1 в режиме 8-бит. таймера с внутр. тактир. для синхронизации UART Config Timer1 = Timer , Gate = Internal , Mode = 2 $crystal = 12000000 'при кварце 12 МГц $baud = 4800 'скорость 4.8 кБ Th1 = 243 : Start Timer1 'константа скорости '--------------------- 'назначение режимов прерываний On Timer0 Timer_0_int Nosave 'вектор прерывания Enable Timer0 'разрешить прерывания таймера 0 Enable Interrupts 'вообще разрешить прерывания Th0 = &HD8 : Tl0 = &HFD 'чтобы прерывание наступило не позже 10 мс '--------------------- Mc: Do 'Главный цикл Input Ibuf 'здесь ждем прихода управляющей команды ============================================================================= 26-1 ===================================== Справочник по программированию «Bascom-8051» == Temp = Asc(ibuf) 'считаем код первого символа принятой строки If Temp = &H48 Then 'это частота "HXXXXXXXX"? Goto Herz End If If Temp = &H56 Then 'это напряжение "VXXXXXXXX"? Goto Volt End If Loop '--------------------- 'обработка данных о напряжении Volt: Temp = Len(ibuf) 'определим длину принятой строки Ibuf = Mid(2 , Temp) 'отбросим префикс "V" R_fld = Val(ibuf) 'преобразуем в число (в вольтах) R_fld = R_fld * 10922.67 '2^15/3 = 10922.67 преобр. разряды ЦАП R_bw = R_fld 'преобразовать в целое число Gosub Sload_766 'загрузка данных в ЦАП AD766, AD1851 Goto Mc '--------------------- 'обработка данных о частоте Herz: Temp = Len(ibuf) 'определим длину принятой строки Ibuf = Mid(2 , Temp) 'отбросим префикс "H" R_frq = Val(ibuf) 'преобразуем в число (в килогерцах) R_fld = R_frq * 71582.788 '2^32 / Fclk = 4294967296 / 60000 kHz R_bd = R_fld 'преобр. в целое 32-разр. число Gosub Sload_9850 'загрузка данных в синтезатор AD9850 Gosub Sel_rf 'опр. номер диапазона, соотв. частоте Gosub Set_com 'подключим соответствующий фильтр Goto Mc '------------------------------------------ 'подпрограмма вычисления предела частоты. Результат в Frng: '0 - DC (менее 5 Гц), 1 - 0.005-110 kHz, 2 - 110-175 kHz, 3 - 175-280 kHz '4 - 280-440 kHz, 5 - 440-700 kHz, 6 - 700-1100 kHz, 7 – 1.1-1.75 МHz '8 – 1.75-2.8 МHz, 9 – 2.8-4.4 М, 10 – 4.4-7 МHz, 11 - 7-11 МHz '----- Sel_rf: Frng = 0 'инициализируем счетчик пределов Do R_fld = Lookup(frng , Hlim_fr)'считаем очередное значение верхней границы If R_fld > R_frq Then 'сравним с текущей частотой Goto S_rfe 'если ниже верхней границы - выходим End If Incr Frng 'перейдем к следующему пределу и повторить цикл Loop Until Frng = 12 'пока все пределы не будут пройдены S_rfe: Return 'таблица значений верхней граница диапазонов воспроизводимой частоты в кГц Hlim_fr: Data 0.005! , 110! , 175! , 280! , 440! , 700! Data 1100! , 1750! , 2800! , 4400! , 7000! '------------------------------------------ 'подпрограмма загрузки данных в синтезатор AD9850 Sload_9850: Set B_fqud : Reset B_fqud 'сбросить интерфейс Set B_clk : Reset B_clk 'защелкнуть код последовательного режима Set B_fqud : Reset B_fqud 'разрешить последовательный режим 'выдвинуть данные из R_bd в режиме 3 (мл. сначала , _-_) Shiftout B_data , B_clk , R_bd , 3 'выдвинуть последний байт с режимом и фазой Temp = 0 : Shiftout B_data , B_clk , Temp , 3 Set B_fqud : Reset B_fqud 'исполнять загруженные данные Return ============================================================================= 26-2 ===================================== Справочник по программированию «Bascom-8051» == '--------------------- 'подпрограмма загрузки данных в ЦАП AD766, AD1851 Sload_766: 'выдвинуть данные из R_bw в режиме 0 (ст. сначала , -_-) Shiftout B_datu , B_clku , R_bw , 0 Reset B_ldu : Set B_ldu 'загрузить данные Return '------------------------------------------ 'подпрограмма загрузки данных коммутации для подключения на выход 'синтезатора соответствующего фильтра с помощью поляризованных реле Set_com: Set P2.3 : Gosub Wait_30ms 'включить отбойную обмотку всех реле на 30 мс R_bw = Lookup(frng , Tab_com) 'загрузка данных портов P2 = High(r_bw) : P0 = Low(r_bw) 'перезапись в порты Gosub Wait_30ms 'включить обмотку нужного реле на 30 мс P2 = &b11110000 : P0 = 0 'очистить порты Return '----- Tab_com: 'Таблица сост. портов упр. реле, в зависимости от диапазона частоты ' ПОРТ 2 ПОРТ 0 ' реле ф. до 4.4 МГц--¬ -- реле фильтра до 2.8 МГц ' реле ф. до 7 МГц --¬¦ ¦ -- реле фильтра до 1.75 МГц ' реле ф. до 11 МГц-¬¦¦ ¦¦ -- реле фильтра до 1.1 МГц ' отбойная обмотка-¬¦¦¦ ¦¦¦ -- реле фильтра до 700 кГц ' всегда 1 -¬¦¦¦¦ ¦¦¦¦ -- реле фильтра до 440 кГц ' всегда 1 -¬¦¦¦¦¦ ¦¦¦¦¦ -- реле фильтра до 280 кГц ' всегда 1 -¬¦¦¦¦¦¦ ¦¦¦¦¦¦ -- реле фильтра до 175 кГц ' всегда 1 -¬||||||| ||||||| -- реле фильтра до 110 кГц Data &B11110000 , &B00000001 'DC Data &B11110000 , &B00000001 '5-110 КГЦ Data &B11110000 , &B00000010 '110-175 КГЦ Data &B11110000 , &B00000100 '175-280 КГЦ Data &B11110000 , &B00001000 '280-440 КГЦ Data &B11110000 , &B00010000 '440-700 КГЦ Data &B11110000 , &B00100000 '700-1100 КГЦ Data &B11110000 , &B01000000 '1.1-1.75 МГЦ Data &B11110000 , &B10000000 '1.75-2.8 МГЦ Data &B11110001 , &B00000000 '2.8-4.4 МГЦ Data &B11110010 , &B00000000 '4.4-7 МГЦ Data &B11110100 , &B00000000 '7-11 МГЦ '------------------------------------------ 'обработка прерывания таймера 0 Timer_0_int: Counter0 = &HD8FD : Start Timer0 ;период прерыв. 10 мс 'компилируется проще, если загружать счетчики следующим образом: 'Th0 = &HD8 : Tl = &HFD 'Ffffh-10000 = D8fdh - период прерыв. 10 мс $asm Jnb {b_tim} , Tim0_i1 ;обработка счетчика реального времени Djnz {r_tim} , Tim0_i1 ;уменьшать до нуля Clr B_tim ;когда достигнем нуля - очистим бит Tim0_i1: $end Asm Return '------------------------------------------ 'подпрограмма задержки, использующая прерывание Wait_30ms: Set B_tim : R_tim = 3 While B_tim = 1 'цикл будет повторять пока, не очистится B_tim Idle 'ждем в останове Wend Return '------------------------------------------ ============================================================================= 26-3 ===================================== Справочник по программированию «Bascom-8051» == Кроме циклов, задаваемых с помощью упомянутых специальных конструкций, Bascom использует скрытые циклы, выполняемые внутри некоторых операторов: а) WAIT, WAITMS, DELAY - временной задержки. Условие выхода из цикла (окончание выполнения оператора) – истечение заданного интервала времкени; б) BITWAIT - ожидания заданного уровня бита. Выход из цикла – поступление заданного логического уровня бита; в) DEBOUNCE - периодического опроса состояния бита. Выход из цикла – также поступление заданного логического уровня бита; г) WAITKEY - ожидания приема символа. Выход их цикла – прием символа; д) INPUT, INPUTHEX - ожидания ввода символьного значения переменной. Выход из цикла – прием символа разделителя; е) INPUTBIN - ожидания ввода двоичной переменной. Выход из цикла – прием необходимого количества байтов для заполнения переменной. Циклическая конструкция FOR … NEXT является, по сути, оператором многократного действия, обеспечивающего выполнение других операций заданное число раз. Bascom обеспечивает работу этой конструкции со всеми типами числовых переменных и констант. Необходимо, чтобы обеспечить правильную работу цикла FOR … NEXT, задавать одинаковые значения размерности переменных (или констант), определяющих начальное и конечное значения, а также приращения. Рекомендуется так строить программу, чтобы циклы FOR … NEXT использовали только байтовые или двухбайтовые параметры. При этом скомпилированный код работает быстро и надежно. При использовании в качестве параметров цикла чисел в формате с плавающей точкой, быстродействие резко снижается (приблизительно до 10 мс на шаг), и возрастает объем генерируемого кода. В следующес разделе приведен интересный пример использования циклов FOR … NEXT. ============================================================================= 26-4 ===================================== Справочник по программированию «Bascom-8051» == 27. Программирование с использованием индексированных переменных Bascom Компилятор Bascom допускает использование массивов переменных, записываемых под одним именем и различающихся порядковым номером расположения. Параметр, указывающий номер переменной в массиве называется индексом. В качестве индекса (указателя) может использоваться константа, одно- или двухбайтная числовая переменная. Массив может располагаться во внутренней или во внешней памяти. Массивы могут строиться из одинаковых переменных любого типа, за исключением битовых. С индексированными переменными во многих случаях можно работать как с обычными переменными соответствующего типа. Однако, некоторые операторы не рассчитаны на подстановку в качестве операндов индексированных переменных и воспринимают их как обычные переменные, т.е. считывают и записывают данные только первого элемента массива, имеющего адрес, совпадающий с адресом массива. Ниже приведен небольшой пример программы с использованием индексированных переменных. В ней также указано два случая невозможности использования индексированных переменных и варианты замены неработающего оператора. '--------------------------------------------------- ' Использования массивов индексированные переменных '--------------------------------------------------- Dim Ni As Const 5 'объем массива Dim Nm As Byte , Jm As Byte , Jmd As Byte , Tmp As Byte Dim Stmp As String * 8 Dim Ar(ni) As Byte 'массив Dim Sa(ni) As String * 8 'строковый массив For Nm = 1 To Ni 'заполнить массив Ar(nm) = Lookup(nm , Da) ' Sa(nm) = Lookupstr(nm , Ds) 'это работает только с первым элементом Stmp = Lookupstr(nm , Ds) : Sa(nm) = Stmp 'поэтому нужно через буфер Next 'сортировка методом "пузырька" - наибольшее (или наименьшее) всплывает For Nm = 2 To Ni 'начинаем сортировку чисел с начала For Jm = Ni Downto Nm 'проверяя пары соседних чисел Jmd = Jm - 1 'формируем второй указатель ' If Ar(jmd) < Ar(jm) Then 'в порядке убывания значений If Ar(jmd) > Ar(jm) Then 'в порядке возрастания значений Tmp = Ar(jmd) : Ar(jmd) = Ar(jm) : Ar(jm) = Tmp 'поменять местами ' Swap Ar(jmd) , Ar(jm) 'с индексированными переменными не работает! End If Next Next 'посмотрим, что получилось For Nm = 1 To Ni : Print Sa(nm) ; Ar(nm) : Next End 'байтовые числовые значения, записываемые в массив для сортировки Da: Data 0 , 12 , 222 , 45 , 6 , 78 , 4 , 5 , 99 , 45 , 146 , 100 'строковые значения, записываемые в массив Ds: Data "1=" , "2=" , "3=" , "4=" , "5=" , "6=" , "7=" , "8=" , "9=" , "10=" ============================================================================= 27-1 ===================================== Справочник по программированию «Bascom-8051» == 28. Программирование EEPROM AT89S82252 Микроконтроллер модели AT89S8252 содержит электрически перепрограммируемую память EEPROM (емкостью 2 Кбайта), которая доступна для записи и считывания средствами программы пользователя. EEPROM представляет собой энергонезависимую память, обеспечивающую хранение данных неограниченное время и при выключенном питании. Bascom имеет два оператора (WRITEEEPROM и READEEPROM), дающих возможность простого доступа к этой памяти. Эти операторы позволяют сохранять и воспроизводить значения переменных всех типов за исключением индексированных (элементов массивов). Каждый из операторов может использоваться в двух вариантах: а) без указания адреса расположения записываемой или считываемой переменной в EEPROM. При компиляции не указанный адрес вычисляется автоматически и подставляется соответственно применяемой переменной, т.е. каждой сохраняемой переменной будет соответствовать только одна ячейка EEPROM (того же размера). Это удобно, когда достаточно обеспечить простое сохранение каких-то значений, размещенных в регистрах, а затем произвести их восстановление; б) с указанием адреса расположения данных в EEPROM. Этот вариант обеспечивает большую гибкость и лучше подходит для сложных задач. Ниже приведены два примера программ с использованием операторов записи и чтения данных EEPROM. В первом примере запись и чтение выполняется без указания адреса. Компилятор занимает ячейки EEPROM в порядке применения операторов записи. Расположение данных в EEPROM после компиляции всегда можно посмотреть в файле сообщений, но программа пользователя, естественно, этого сделать не может. '-------------------------------------------- ' пример простого доступа к EEPROM AT89S8252 '-------------------------------------------- Dim Byt As Byte , Wrd As Word , Intg As Integer , Lng As Long , Sng As Single 'инициализируем переменные всех типов. С индексированными не работает Byt = 10 : Wrd = 2000 : Intg = -10000 : Lng = 10000000 : Sng = 3.3333 'запишем их значения в EEPROM без указания адреса Writeeeprom Byt : Writeeeprom Wrd : Writeeeprom Intg Writeeeprom Lng : Writeeeprom Sng 'очистим переменные Byt = 0 : Wrd = 0 : Intg = 0 : Lng = 0 : Sng = 0 'считаем записанные значения также без указания адреса Readeeprom Byt : Readeeprom Wrd : Readeeprom Intg Readeeprom Lng : Readeeprom Sng 'посмотрим, что получилось Print Byt ; "_" ; Wrd ; "_" ; Intg ; "_" ; Lng ; "_" ; Sng End В другом примере операторы WRITEEEPROM и READEEPROM применяются с указанием адреса расположения данных, что позволяет производить запись или чтение любой необходимой области EEPROM, благодаря чему, становится возможным произвольный порядок доступа к памяти. Теперь рассмотрим вопрос обеспечения достоверности сохраняемых данных. Известно, что при выключении питания микроконтроллера существует короткий момент (несколько миллисекунд), когда происходит сбой текущей программы, но способность исполнять команды, записанные в ПЗУ еще сохраняется. В результате появляется возможность повреждения записанных данных, если при сбое происходит попадание на участок программы, выполняющей запись в EEPROM. Для повышения надежности хранения данных применяют аппаратные средства в виде устройств быстрого сброса или выключения питания при сбоях электропитания. Кроме этого, важными составляющими системы защиты данных остаются и программные средства, первое из которых - контроль исправности блока записанных данных. В приведенном примере содержатся элементы такой защиты: а) введена дополнительная ячейка для хранения контрольной суммы блока данных. Причем данные, записываемые в регистр контрольной суммы, лишь дополняют ее, до одного и того же значения - 5AH («нормальной контрольной суммы»); б) после каждой операции записи производится балансировка контрольной суммы блока данных до нормального значения; в) перед считыванием данных (или после включения питания) производится проверка контрольной суммы блока данных, на основании которой принимается решение о дальнейших действий. '--------------------------------------------------------- ' использование EEPROM AT89C8252 как калибровочной памяти '--------------------------------------------------------- Dim K0 As Const 0 'блок из 8-ми констант ============================================================================= 28-1 |