Справочник по программировани BASCOM-8051 (М.Л. Кулиш, 2001). Справочник по программированию bascom8051 Краснодар 2001
Скачать 6.61 Mb.
|
===================================== Справочник по программированию «Bascom-8051» == '------------------------------------------------------------- ' тестирование устройства на шине Microwire '------------------------------------------------------------- Dim Tmp1 As Byte , Tmp2 As Byte Dim Tmp3 As Byte , Tmp4 As Byte , Tmpw As Word Dim Tmp(20) As Word '-------------------------------- 'применим в 93C46 8-битном режиме Config Microwire = Pin , Cs = P1.0 , Din = P1.1 , Dout = P1.2 , _ Clock = P1.3 , Al = 7 Mw_cs Alias P1.0 : Mw_dout Alias P1.2 'определим имена портов линий Cs и Dout '-------------------------------- Mwinit Mwwopcode &B1001100000 , 10 'разрешим запись и стирание Mwwopcode &B1001000000 , 10 'проведем общее стирание Gosub Mwrdyw 'подождем стирания For Tmp1 = 1 To 20 'заполним массив Tmpw = Tmp1 : Tmpw = Tmpw * Tmpw 'квадратом индекса Tmp(tmp1) = Tmpw Next 'следующее значение '-------------------------------- Tmp2 = 0 'установим начальный адрес EEPROM For Tmp1 = 1 To 20 'запомним массив Tmpw = Tmp(tmp1) 'в EEPROM Mwwrite Low(tmpw) , &B101 , Tmp2 , 1 : Incr Tmp2 : Gosub Mwrdyw Mwwrite High(tmpw) , &B101 , Tmp2 , 1 : Incr Tmp2 : Gosub Mwrdyw Next 'следующее значение '-------------------------------- For Tmp1 = 1 To 20 'очистим массив Tmp(tmp1) = 0 Next '-------------------------------- Tmp2 = 0 'установим начальный адрес EEPROM For Tmp1 = 1 To 20 'считаем массив по одному байту Mwread Tmp3 , &B110 , Tmp2 , 1 : Incr Tmp2 'считаем по одному байту Mwread Tmp4 , &B110 , Tmp2 , 1 : Incr Tmp2 Tmpw = Makeint(tmp4 , Tmp3) : Tmp(tmp1) = Tmpw 'соберем из двух байт Next 'следующее значение Mwwopcode &B1000000000 , 10 'запретим запись и стирание '-------------------------------- ‘п/п ожидания готовности устройства на шине Microwire после операции записи Mwrdyw: $asm Setb {mw_cs} ;выберем микросхему Mov A , #100 ;сможем ждать 10 мс Mwrw1: Mov B , #50 ;подцикл 100 мкс Mwrw2: Djnz B , Mwrw2 Jb {mw_dout} , Mwrw3 ;проверим наличие бита готовности Djnz A , Mwrw1 ;если он не появился ждем готовности 10 мс Mwrw3: Clr {mw_cs} ;снимем сигнал выборки $end Asm Return End ============================================================================= 19-3 ===================================== Справочник по программированию «Bascom-8051» == 20. Программирование устройств I2C Для программирования устройств, подключенных к шине I2C, Bascom предоставляет два варианта: а) использовать готовые операторы записи и считывания данных, соответственно I2CSEND и I2CRECEIVE; б) использовать операторы I2CSTART, I2CSTOP, I2CRBYTE и I2CWBYTE и самостоятельно создавать программы взаимодействия с устройствами на шине I2C. В первом случае программа получается намного проще, однако, ограничен круг устройств, с которыми можно работать, т.к. операторы I2CSEND и I2CRECEIVE позволяют использовать только однобайтный адрес. К устройствам, имеющим однобайтный адрес, относятся микросхемы переменных резисторов (регуляторов уровня), ЦАП, АЦП, порты ввода-вывода, драйверы светодиодных индикаторов и реле. Когда подпрограммы записи и чтения данных написаны с использованием операторов I2CSTART, I2CSTOP, I2CRBYTE и I2CWBYTE, появляется возможность реализовать любой протокол обмена, содержащий сколько угодно байт адреса и данных. Это необходимо для работы с устройствами памяти, в которых адрес устройства является «ключом» доступа к массиву данных. Ниже приведена программа тестирования EEPROM, содержащая три набора подпрограмм чтения и записи: а) однобайтных данных с двухбайтным адресом (устройстве I2C); б) четырехбайтных данных и с двухбайтным адресом. В этих подпрограммах реализована страничная запись (четыре байта в странице при записи) и последовательное чтение (также четырех байт); в) однобайтных данных с однобайтным адресом. Эти подпрограммы функционально близки операторам I2CSEND и I2CRECEIVE, но используют меньше ресурсов памяти. Часть подпрограмм, представленных в примере, объявлено в виде функций для демонстрации возможностей Bascom. В составе программ использовано много ассемблерных вставок, что обусловлено необходимостью доступа к частям многобайтных переменных и для повышения эффективности кода. Операторы I2CRBYTE и I2CWBYTE, соответственно считываемые и записываемые данные, передают через аккумулятор. Это используется в представленных программах, где аккумулятор для экономии используется в качестве регистра временного хранения данных (источника и приемника). С помощью дисассемблирования было определено, что компилятор не использует регистр B в программах, работающих с интерфейсом I2С. Поэтому в представленных программах, и он такжже используется как временная переменная для хранения и обработки данных, позволяя уменьшить еще на одну, количество необходимых переменных. В демонстрационной программе имеются операторы для обслуживания отладочного кристалла эмулятора типа 80C51GB. Они намеренно оставлены в тексте программы, чтобы показать, как оформляются подобные фрагменты. '------------------------------------------------------------- ' Программа тестирование I2C EEPROM - 24c16 (2k*8) ' и утилиты работы с устройствами I2C ' строки, отмеченные знаками "!!!" относятся к местам программы, ' необходимых только для работы эмулятора на процессоре модели 80C51GB '------------------------------------------------------------- 'Определенные ниже п/п объявлены как функции переменных 'Таким способом можно определять п/п только с входящими целыми числами 'При использ. перем. с плав. точк. п/п приходится оформлять в обычном виде Declare Sub Write_eeprom(wadr As Word , Value As Byte) Declare Sub Read_eeprom(wadr As Word , Value As Byte) Declare Sub Wrb_24c01(badr As Byte , Value As Byte) Declare Sub Rdb_24c01(badr As Byte , Value As Byte) '--------------------- Dim Addressw As Const 160 , Addressr As Const 161 'объявление констант Dim Badr As Byte 'байтовый адрес Dim Temp As Byte 'временные данные Dim Value As Byte 'значение записываемых или считываемых данных Dim Wadr As Word 'двухбайтный адрес Dim Fld As Single 'число с плавающей точкой '--------------------- Config Sda = P1.5 'P1.5 как линия SDA Config Scl = P1.4 'P1.4 как линия SCL Config I2cdelay = 0 'ускорение линии I2C Config Timer0 = Timer , Gate = Internal , Mode = 1 : Start Timer0 '--------------------- 'назначение режимов прерываний On Timer0 Timer_0_int Nosave 'вектор прерывания ============================================================================= 20-1 ===================================== Справочник по программированию «Bascom-8051» == Enable Interrupts 'вообще разрешить прерывания Enable Timer0 'разрешить прерывания таймера 0 '!!! -------------------------------------- 'только в эмуляторе 80C51GB Th0 = &HD8 : Tl0 = &HFD 'чтобы прерывание наступило не позже 10 мс Oscr = &HE1 : Oscr = &H1E 'выключить контроль частоты генератора Wdtrst = &H1E : Wdtrst = &HE1'сбросить будильник P4 = &HFF : P5 = &HFF 'установить эмулирующие порты как в эмулируемые '--------------------- 'Цикл проверки программ записи чтения однобайтовых переменных 'Используем обе формы записи объявленных функций Mc: For Wadr = 0 To 1024 Step 3 'готовим адрес Value = Low(wadr) 'готовим данные Call Write_eeprom(wadr , Value) 'записываем в EEPROM Next For Wadr = 0 To 1024 Step 3 'готовим адрес Read_eeprom Wadr , Value 'считываем данные из EEPROM Print Value ; "=" ; Value 'печатаем данные Waitms 50 Next Goto Mc '--------------------- 'Цикл проверки программ записи чтения четырехбайтовых переменных 'Mc: For Wadr = 0 To 2044 Step 4 'готовим адрес Fld = Wadr Fld = 3 * Fld 'готовим данные Gosub Wrs_24c 'записываем в EEPROM Next For Wadr = 0 To 2044 Step 4 'готовим адрес Gosub Rds_24c 'считываем данные из EEPROM Print Wadr ; "=" ; Fld 'печатаем данные Waitms 50 Next Goto Mc '------------------------------------------ 'обработка прерывания таймера 0 Timer_0_int: Th0 = &HD8 : Tl0 = &HFD 'Ffffh-10000 = D8fdh - период прерыв. 10 мс '!!! только в эмуляторе с 80C51GB Wdtrst = &H1E : Wdtrst = &HE1 'сбросить будильник Return '------------------------------------------ 'п/п записи байта в EEPROM AT24с01A,AT24c02 - AT24c16 Sub Write_eeprom(wadr As Word , Value As Byte) $asm Mov A , {wadr + 1} ;готовим старший байт, содержащий Rl A ;старшие разряды адреса Orl A , #{Addressw} ;добавим код микросхемы Mov B , A $end Asm I2cstart 'старт I2cwbyte B 'первый байт режима $asm Mov A , {wadr + 0} $end Asm I2cwbyte Acc 'младший адрес в EEPROM I2cwbyte Value 'записывемое значение I2cstop 'стоп Waitms 10 'подождем 10 мс End Sub '------------------------------------------ ============================================================================= 20-2 ===================================== Справочник по программированию «Bascom-8051» == 'п/п считывания байта из EEPROM AT24с01A,AT24c02 - AT24c16 Sub Read_eeprom(wadr As Word , Value As Byte) $asm Mov A , {wadr + 1} ;готовим старший байт, содержащий Rl A ;старшие разряды адреса Orl A , #{Addressw} ;добавим код микросхемы Mov B , A $end Asm I2cstart 'старт I2cwbyte B 'первый байт режима $asm Mov A , {wadr + 0} $end Asm I2cwbyte Acc 'младший адрес в EEPROM Set B.0 'переключим в режим считывания I2cstart 'повторим старт I2cwbyte B 'байт режима I2crbyte Value , 9 'считали байт I2cstop 'стоп End Sub '------------------------------------------ 'п/п записи четырехбайтного числа в EEPROM AT24с01A,AT24c02 - AT24c16 Wrs_24c: $asm Mov A , {wadr + 1} ;готовим старший байт, содержащий Rl A ;старшие разряды адреса Orl A , #{Addressw} ;добавим код микросхемы Mov B , A $end Asm I2cstart 'старт I2cwbyte B 'первый байт режима $asm Mov A , {wadr + 0} $end Asm I2cwbyte Acc 'младший адрес в EEPROM $asm Mov A, {Fld + 0} $end Asm I2cwbyte Acc 'первый записываемый байт $asm Mov A , {Fld + 1} $end Asm I2cwbyte Acc '2-й $asm Mov A , {Fld + 2} $end Asm I2cwbyte Acc '3-й $asm Mov A , {Fld + 3} $end Asm I2cwbyte Acc '4-й I2cstop 'стоп Waitms 10 'подождем 10 мс Return '------------------------------------------ 'п/п считывания четырехбайтного числа из EEPROM AT24с01A,AT24c02 - AT24c16 Rds_24c: $asm Mov A , {wadr + 1} ;готовим старший байт, содержащий Rl A ;старшие разряды адреса Orl A , #{Addressw} ;добавим код микросхемы Mov B , A $end Asm ============================================================================= 20-3 ===================================== Справочник по программированию «Bascom-8051» == I2cstart 'старт I2cwbyte B 'первый байт режима $asm Mov A , {wadr + 0} $end Asm I2cwbyte Acc 'младший адрес в EEPROM Set B.0 'переключим в режим считывания I2cstart 'повторим старт I2cwbyte B 'байт режима I2crbyte Acc , 8 'считали 1-й байт с опцией ASC (8) $asm Mov {Fld + 0} , A $end Asm I2crbyte Acc , 8 '2-й байт $asm Mov {Fld + 1} , A $end Asm I2crbyte Acc , 8 '3-й байт $asm Mov {Fld + 2} , A $end Asm I2crbyte Acc , 9 'последний байт с опцией NOASC (9) $asm Mov {Fld + 3} , A $end Asm I2cstop 'стоп Return '------------------------------------------ 'п/п записи байта в EEPROM AT24с01 Sub Wrb_24c01(badr As Byte , Value As Byte) Acc = Badr 'готовим адрес $asm Rl A ; ------------------------------- Mov B , A ; | a6| a5| a4| a3| a2| a1| a0| 0 | $end Asm I2cstart 'старт I2cwbyte B 'адрес и бит режима I2cwbyte Value 'записывемое значение I2cstop 'стоп Waitms 10 'подождем 10 мс End Sub '------------------------------------------ 'п/п считывания байта из EEPROM AT24с01 Sub Rdb_24c01(badr As Byte , Value As Byte) Acc = Badr 'готовим адрес $asm Setb c ; ------------------------------- Rlc A ; | a6| a5| a4| a3| a2| a1| a0| 1 | Mov {Value} , A $end Asm I2cstart 'старт I2cwbyte Value 'первый байт режима I2crbyte Value , 9 'считали байт I2cstop 'стоп End Sub ============================================================================= 20-4 ===================================== Справочник по программированию «Bascom-8051» == 21. Программирование таймеров Наличие в составе Bascom операторов программирования таймеров позволяет во многих случаях обходится только этими средствами. При этом даже не нужны знания соответствующих управляющих регистров. Более глубокое программирование с использованием нестандартных приемов, без сомнения, потребует подробного изучения регистров управления таймерами и их взаимодействия с системой прерывания. Применения ассемблерных вставок для более эффективного управления таймерами не требуется, т.к. специальные команды Bascom достаточно оперативны, и имеется возможность непосредственного управления всеми регистрами и битами. В таблице, приведенной ниже, показано как компилируются операторы Bascom, работающие с таймерами. Мы видим, что компилятор не работает со всем таймерами по одинаковой схеме., поэтому всегда нужно быть готовым к тому, что в одних случаях компилятор поставит код команды остановки и запуска счетчика, а в других их нужно будет добавить. Оператор Bascom-8051 Результат компиляции Комментарий Load Timer0 , 100 MOV TL0,#9CH MOV TH0,#9CH Загрузка в режиме таймеров 0 или 1 в режиме 2. Коэффициент деления определяется только старшим байтом счетчика, но задаваться должен однобайтным числом! Load Timer1 , 1000 MOV TL1,#18H MOV TH1,#18H Здесь неправильно задан коэффициент деления – константа должна быть однобайтовой. Load Timer2 , 1024 MOV RCAP2L,#00H MOV CAP2H,#0FCH Для таймера 2 загрузочный коэффициент может быть двухбайтным Counter0 = 8192 MOV TL0,#00H MOV TH0,#20H Загрузка счетчика производится двухбайтовым числом. Применяется в режиме 1. Counter2 = 10 CLR TR2 MOV TL2,#0AH MOV TH2,#00H Аналогичная операция для таймера 2 начинается с остановки счетчика. Buf_ = Counter1 CLR TR1 MOV R0,#23H MOV @R0,TL1 INC R0 MOV @R0,TH1 Считывание в переменную Buf_ содержимого счетчика таймера 0, 1 и 2 производится после его остановки. Если счет необходимо продолжить, таймер нужно снова запустить. Buf_ = Capture CLR TR2 MOV R0,#23H MOV @R0,RCAP2L INC R0 MOV @R0,RCAP2H SETB TR2 Считывание в переменную Buf_ содержимого регистра захвата таймера 2 производится после его остановки. Далее счет снова запускается. Var1 = Tl0 Var2 = Th0 MOV Var1,TL0 MOV Var2,TH0 Непосредственное считывание содержимого счетчика в байтовые переменные. Это аналог ассемблера. Tl0 = &h00 Th0 = &hF0 MOV TL0,#00H MOV TH0,#F0H Непосредственная запись данных в счетчик ============================================================================= 21-1 ===================================== Справочник по программированию «Bascom-8051» == 22. Программирование устройств с последовательным вводом-выводом В других разделах много уделялось внимания проблемам ввода-вывода через последовательные интерфейсы. Было приведено много примеров программ, использующих операторы последовательного ввода- вывода. Поэтому в настоящем разделе рассмотрим только, оставшиеся неразрешенными, вопросы. Главный, из которых - как работают операторы Shiftin и Shiftout Bascom, и чем они отличаются друг от друга? Самыми удобными и универсальными представляются операторы записи и считывания данных (Shiftin и Shiftout). Эти операторы работают с однобайтными и многобайтными переменными, и могут быть применены при любом расположении данных и соотношении фазы синхронизирующего сигнала. В следующей ниже таблице, представлены упрощенные (и укороченные) временные диаграммы на линиях интерфейса во всех возможные режимах. Там же указана скорость передачи данных для однобайтовых (это максимальная или пиковая скорость) и многобайтовых данных (как средняя скорость) при частоте кварца 12 МГц. На основе операторов Shiftin и Shiftout могут быть построены практически все виды применяемых синхронных интерфейсов. Временные диаграммы, формируемые операторами последовательного вывода Оператор Временная диаграмма Скорость Shiftout, mode 0 ___ _____ _____ _____ _____ __ ___X_____X_____X_____X_____X__ Out_Data msb _____ ___ ___ ___ ____ lsb |_| |_| |_| |_| Clk Пиковая 100 Кбод, средняя 80 Кбод Shiftout, mode 1 ___ _____ _____ _____ _____ __ ___X_____X_____X_____X_____X__ Out_Data msb _ _ _ _ lsb _____| |___| |___| |___| |____ Clk Пиковая 100 Кбод, средняя 80 Кбод Shiftout, mode 2 ___ _____ _____ _____ _____ __ ___X_____X_____X_____X_____X__ Out_Data lsb _____ ___ ___ ___ ____ msb |_| |_| |_| |_| Clk Пиковая 100 Кбод, средняя 80 Кбод Shiftout, mode 3 ___ _____ _____ _____ _____ __ ___X_____X_____X_____X_____X__ Out_Data lsb _ _ _ _ msb _____| |___| |___| |___| |____ Clk Пиковая 100 Кбод, средняя 80 Кбод В последних версиях компилятора расширены возможности оператора Shifin. Теперь он работает во всех четырех режимах при внешней синхронизации и позволяет считывать данные до начала синхроимпульса (в обычном режиме считывание дланных производится после начала синхроимпульса). Режим предварительного считывания включается применением дополнительной опции PRE. В режимах внешней синхронизации применение предварительного считывания не предусмотрено. ВНИМАНИЕ! При использовании внешней синхронизации нужно представлять себе, что операторы считывания данных Shiftin в этом случае являются скрытыми циклами ожидания (необходимого количества импульсов синхронизации). Если происходит сбой на передающей стороне и, хотя бы один импульс пропадает, то происходит «зависание» программы на операторе Shiftin. Это же может происходить, если случается прерывание во время приема данных и один или несколько импульсов будет пропущено. ============================================================================= 22-1 |