Справочник по программированию «Bascom-AVR» (М.Л. Кулиш). Справочник по программированию Bascomavr Создание микропроцессорной системы Теория
Скачать 1.18 Mb.
|
===================================== Справочник по программированию «Bascom-AVR» == Return '---------------------------------------------------------------------------------- Здесь проведена оптимизация исходно текста Подпрограммы Add_vtmpb и Add_sz появились в результате оптимизации 'обновить индикатор по завершению одной из операций в соответствии с текущим состоянием New_led: Bufr = "" 'очистить строку If Mdisp = 1 Then 'выбрать вариант обработки индикатора Goto Nled2 'на формирования отображения ММСС Elseif Mdisp = 2 Then Goto Nled3 'на гашение End If 'сформировать символьное изображение времени в виде ЧЧММ Tmpb = Rhour : Gosub Add_vtmpb 'добавить значение часов Tmpb = Rmin : Gosub Add_vtmpb 'добавить значение минут '--------- Nled1: Gosub Asc_seg : Buf_dis(1) = Tmpb 'получить код первого знакоместа '--------- Gosub Asc_seg2 : Buf_dis(2) = Tmpb 'получить код второго знакоместа '--------- Gosub Asc_seg2 : Buf_dis(3) = Tmpb 'получить код третьего знакоместа '--------- Gosub Asc_seg2 : Buf_dis(4) = Tmpb 'получить код четвертого знакоместа Return '--------- 'сформировать символьное изображение времени в виде ММСС Nled2: Tmpb = Rmin : Gosub Add_vtmpb 'добавить значение минут Tmpb = Rsec : Gosub Add_vtmpb 'добавить значение секунд Goto Nled1 '--------- 'погасить индикатор Nled3: Buf_dis(1) = 255 'погасить все сегменты Buf_dis(2) = &HFF Buf_dis(3) = &B11111111 Buf_dis(4) = 255 Return '--------- 'п/п результат оптимизации Add_vtmpb: If Tmpb < 10 Then 'если значение выражается одной цифрой Gosub Add_sz 'добавить символ лидирующего нуля End If Bufr = Bufr + Str(tmpb) 'добавить значение Return '--------- Add_sz: Bufr = Bufr + "0" 'добавить символ лидирующего нуля Return '---------------------------------------------------------------------------------- ' программы клавиатуры '--------------------------------------------------------- ' --------------------------------------- ' | AVR-WATCH | ' | --------------------------------- | ' | | --- --- --- --- | | ' | | | | | | | | | | | | ' | | --- --- --- --- | | ' | | | | | | | | | | | | ' | | --- [] --- [] --- [] --- [] | | ' | --------------------------------- | ' | 1 2 3 4 | ' | _ _ _ _ | ' | |_| |_| |_| |_| | ' | | ' | Reset + + Shift | ' | Min Hour Min | ' --------------------------------------- ' выполнение программ обработки кнопок - основной список ' 0: пустой переход из-за того, что кнопки нумеруются с 1-й, а не с 0-й ' 1: Сбросить минуты 2: Добавить час 3: Добавить минуту 4: Второе назначение ' ' | _ _ _ _ | ' | |_| |_| |_| |_| | ============================================================================= 15 ===================================== Справочник по программированию «Bascom-AVR» == ' | | ' | ЧЧММ ММСС ON/OFF ON/OFF | ' | Формат врем. Sound Disp | ' --------------------------------------- ' выполнение программ обработки кнопок - дополнительный список ' 0: пустой переход из-за того, что кнопки нумеруются с 1-й, а не с 0-й ' 1: Отображать ЧЧММ 2: Отображать ММСС 3: Вкл.Выкл. Звук 4: Вкл.Выкл. Индикацию '--------------------------------------------------------- W_klb: On Buf_kl Goto Kn , Km1 , Km2 , Km3 , Km4 '---------------------------------------------- W_skl: On Buf_kl Goto Km1_1 , Ks1 , Ks2 , Ks3 , Ks4 '--------- Km1: Rsec = 0 : Rmin = 0 'сбросить секунды и минуты If Rmin > 30 Then 'при необходимости округления Goto Km2 'скорректировать счетчик минут End If Km1_1: Ddat = 255 'поставить признак обновления индикации Kn: Return '--------- Km2: Incr Rhour 'плюс час If Rhour > 23 Then 'при необходимости Rhour = 0 'скорректировать счетчик часов End If Goto Km1_1 '--------- Km3: Incr Rmin 'плюс минута If Rmin > 59 Then 'при необходимости Rmin = 0 'скорректировать счетчик минут End If Goto Km1_1 '--------- ' переключить режим второго назначения кнопок Km4: Index = 2 : Gosub Dis_tr 'выдать приглашение " SH " Gosub Waitklc 'ожидание нажатий 2.5 с If Buf_kl <> 0 Then 'есть нажания кнопки? Goto W_skl 'да - переходим к обработке списка End If Goto Km1_1 'на обновление индикации '--------- Ks1: Mdisp = 0 'установить режим отображения ЧЧММ Goto Km1_1 'на обновление индикации '--------- Ks2: Mdisp = 1 'установить режим отображения ММСС Goto Km1_1 'на обновление индикации '--------- Совет Необходимо выбирать такие способы обработки управляющих переменных, чтобы ложные значения не могли создаваться, а при появлении исключались автоматически. Пример тому обработка пере- менной Msnd. Избыточности кода при этом не происходит. Ks3: If Msnd <> 0 Then 'изменить режим звука на противоположенный Msnd = 0 Else Msnd = 255 End If Goto Km1_1 'на обновление индикации '--------- Ks4: If Mdisp <> 2 Then 'изменить режим гашения на противоположенный Mdisp = 2 'установить режим гашения Else Mdisp = 0 'снять режим гашения End If Goto Km1_1 'на обновление индикации '---------------------------------------------------------------------------------- 'обработка прерывания таймера 0 ============================================================================= 16 ===================================== Справочник по программированию «Bascom-AVR» == 'используется как часы реального времени с частотой 244 Гц (4 мс) 'для этого нужно организовать схему деления 1 МГц/64/64 = 0,000244140625 МГц Timer0_int: $asm Push R31 'сохраним регистры In R31 , Sreg Push R31 Push R30 '----- Ldi R31 , 192 'переустановим счетчик Out Tcnt0 , R31 '--------------------- Rcall Led_out 'вывод в индикатор Rcall In_kl 'опрос клавиатуры '--------------------- 'обработка счетчика времени Lds R31 , {s_tim} 'считать счетчик Dec R31 'уменьшить Sts {s_tim} , R31 'сохранить Andi R31 , &h0f 'маска Brne Intt2_4 'каждое 16 прерывание (64 мс) обрабатываем еще два счетчика '--------------------- 'обработка счетчика переменных временных интервалов Lds R31 , {w_tim} 'считать счетчик Dec R31 'может уменьшаться только от 127 до нуля. Brmi Intt2_1 Sts {w_tim} , R31 '--------------------- 'обработка счетчика времени звонка Intt2_1: Lds R31 , {Msnd} 'проверим, а звонок разрешен? And R31 , R31 Brne Intt2_2 'если не равен 0 - переход на отключение 'разрешен Lds R31 , {r_btim} 'считаем счетчик времени звонка And R31 , R31 Breq Intt2_2 'если он равен 0 - переход Dec R31 'уменьшить Sts {r_btim} , R31 Ldi R31 , &B00001001 'и разрешить пищать Rjmp Intt2_3 Intt2_2: Ldi R31 , &B00001000 'запретить пищать Intt2_3: Out Tccr2 , R31 'в регистр управления таймером 2 '----- Intt2_4: Pop R30 'восстановим регистры Pop R31 Out Sreg , R31 Pop R31 $end Asm Return '---------------------------------------------- 'обработка прерывания таймера 2. Происходит 1 раз в секунду Timer2_int: $asm push R31 'сохраним регистры ' In R31 , Sreg ' Push R31 '----- ldi R31 , 255 Sts {ndat} , R31 '----- ' Pop R31 'восстановим регистры ' Out Sreg , R31 Pop R31 Reti $end Asm Return '---------------------------------------------------------------------------------- ' ВВОД ДАННЫХ С КЛАВИАТУРЫ ' клавиатура опрашивается при выводе очередного знакоместа на индикатор ' код кнопки совпадает с номером знакоместа. Осуществляется подавление дребезга ' срабатывание фиксируется при удержании более 6 циклов опроса In_kl: $asm Lds R31 ,{Buf_kl} 'пока буфер клавиатуры не опустеет And R31 , R31 ============================================================================= 17 ===================================== Справочник по программированию «Bascom-AVR» == Breq Inkl 'сканирование не проводится Ret '--------- ' НАЧИНАЕМ Inkl: Lds R31 , {r_ckl} 'подготовим счетчика нажатий к обработке Sbic Pinc , 4 'считать состояние линии опроса кнопки Rjmp N_st 'нет нажатия - переход '--------- ' НАЖАТИЯ ЕСТЬ Y_st: Cpi R31 , 6 'если равен 6 - нажатие уже было зафиксировано Breq Y_st1 'на выход без запоминания. Inc R31 'иначе нужен инкремент Sts {r_ckl} , R31 'и сохранить Cpi R31 , 6 Brne y_st1 'меньше 6 - тоже выход без действий '--------- ' НАЖАТИЕ ЗАФИКСИРОВАТЬ Ldi R31 , 3 'звонить 60 мс Sts {r_btim} , R31 Lds R31 , {Cnt_dis} 'преобразуем код знакоместа (от 0 до 3) Inc R31 'в код кнопки (от 1 до 4) Sts {Buf_kl} , R31 Y_st1: Ret '--------- ' НАЖАТИЯ НЕТ N_st: And R31 , R31 'проверим счетчик "удержания" Breq N_st1 'не равен нулю Dec R31 'декремент Sts {r_ckl} , R31 'и сохранить N_st1: Ret $end Asm '---------------------------------------------------------------------------------- 'данные константы позволяют учесть и скорректированит "нерегулярность" монтажа индикатора Const N_scn = &B11110000 ' МАСКА СКАНИРОВАНИЯ ДЛЯ ИНДИКАТОРА С ОА Const N_sc1 = &B11111110 ' МАСКА ДЛЯ ПОДСВЕТКИ 1-ГО ЗНАКОМЕСТА Const N_sc2 = &B01111101 ' МАСКА ДЛЯ ПОДСВЕТКИ 2-ГО ЗНАКОМЕСТА Const N_sc3 = &B11111011 ' МАСКА ДЛЯ ПОДСВЕТКИ 3-ГО ЗНАКОМЕСТА Const N_sc4 = &B11110111 ' МАСКА ДЛЯ ПОДСВЕТКИ 4-ГО ЗНАКОМЕСТА '----------------------------- 'обслуживание светодиодного 7-сегментного индикатора Led_out: $asm Lds R31 , {Cnt_dis} 'считать значение счетчика сканирования Inc R31 Andi R31 , 3 Sts {Cnt_dis} , R31 'и сохранить '--------- Cpi R31 , 1 Breq Led_1 '--------- Cpi R31 , 2 Breq Led_2 '--------- Cpi R31 , 3 Breq Led_3 Led_0: '--------- Lds R30 , {buf_dis} Ldi R31 , N_sc1 ' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 1-ГО ЗНАКОМЕСТА Rjmp Led_e '--------- Led_1: Lds R30 , {buf_dis+1} Ldi R31 , N_sc2 ' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 2-ГО ЗНАКОМЕСТА Rjmp Led_e '--------- Led_2: Lds R30 , {buf_dis+2} Ldi R31 , N_sc3 ' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 3-ГО ЗНАКОМЕСТА Rjmp Led_e '--------- Led_3: Lds R30 , {buf_dis+3} Ldi R31 , N_sc4 ' ЗНАЧЕНИЕ ДЛЯ ПОДСВЕТКИ 4-ГО ЗНАКОМЕСТА ============================================================================= 18 ===================================== Справочник по программированию «Bascom-AVR» == Led_e: Out Portd , R30 In R30 , Portc Ori R30 , N_scn ' МАСКА СКАНИРОВАНИЯ And R30 , R31 Out Portc , R30 Ret $end Asm '---------------------------------------------------------------------------------- ' УТИЛИТЫ '---------------------------------------------------------------------------------- 'ВЫВОД СООБЩЕНИЯ СООБЩЕНИЯ, НОМЕР КОТОРОГО УКАЗАН Index Dis_tr: For Value = 1 To 4 'определим число считываемых символов Tmpb = Index * 4 'вычислить индекс, указывающих на начало сообщения Tmpb = Tmpb + Value 'вычислить индекс, указывающих на текущий символ Decr Tmpb 'коррекция индекса Tmpb = Lookup(tmpb , Tr_led) 'считать из таблицы код символа Gosub Pos_seg 'преобразовать в код сегментов Buf_dis(index) = Tmpb 'записать в буфер индикации Next Index Return '---------------------------------------------------------------------------------- 'П/П ВЫБОРА ИЗ ТАБЛИЦЫ КОДА ЧИСЛА В 7-СЕГМЕНТНОМ КОДЕ ИЗ ASCII (ВТОРОГО СИМВОЛА) Asc_seg2: Bufr = Mid(bufr , 2) 'сдвинуть строку влево на одну позицию '--------- 'П/П ВЫБОРА ИЗ ТАБЛИЦЫ КОДА ЧИСЛА В 7-СЕГМЕНТНОМ КОДЕ ИЗ ASCII Asc_seg: Tmpb = Asc(bufr) 'считать первый символ строки Tmpb = Tmpb - &H30 'преобразовать ASCII в число '--------- 'П/П ПРЕОБРАЗОВАНИЯ ПОЗИЦИОННОГО КОДА В 7-СЕГМЕНТНЫЙ КОД Pos_seg: Tmpb = Lookup(tmpb , Tabseg0) 'считать из таблицы, используя число как смещение 'при необходимости подключить следующую строчку ' Gosub Tr_seg 'исправить монтаж сегментов индикатора Return '--------- 'П/П ПЕРЕСЫПКИ БИТОВ 7-СЕГМЕНТНОГО КОДА ДЛЯ КОРРЕКЦИИ "НЕПРАВИЛЬНОГО" МОНТАЖА Tr_seg: Value.0 = Tmpb.7 : Value.1 = Tmpb.6 : Value.2 = Tmpb.5 'например "отзеркалить" Value.3 = Tmpb.4 : Value.4 = Tmpb.3 : Value.5 = Tmpb.2 : Value.6 = Tmpb.1 : Value.7 = Tmpb.0 Tmpb = Value : Return '---------------------------------------------------------------------------------- 'ТАБЛИЦА РАСПОЛОЖЕНИЯ СЕГМЕНТОВ ИНДИКАТОРА - ПРОТОТИПА '--------- ' D7 D6 D5 D4 D3 D2 D1 D0 ' ----------------------------------------------- 'BUF_DIS(4) ¦ h1 g1 f1 e1 d1 c1 b1 a1 'BUF_DIS(3) ¦ h2 g2 f2 e2 d2 c2 b2 a2 'BUF_DIS(2) ¦ h3 g3 f3 e3 d3 c3 b3 a3 'BUF_DIS(1) ¦ h4 g4 f4 e4 d4 c4 b4 a4 '------------------------------------------- ' РАСПОЛОЖЕНИЕ СЕГМЕНТОВ НА ПОЛЕ ИНДИКАТОРА ' =============================================== ' ¦ ¦ ' ¦ -a4- -a3- -a2- -a1- ¦ ' ¦ I I I I I I I I ¦ ' ¦ f4 b4 f3 b3 f2 b2 f1 b1 ¦ ' ¦ I I I I I I I I ¦ ' ¦ -g4- -g3- -g2- -g1- ¦ ' ¦ I I I I I I I I ¦ ' ¦ e4 c4 e3 c3 e2 c2 e1 c1 ¦ ' ¦ I I I I I I I I ¦ ' ¦ -d4- -d3- -d2- -d1- ¦ ' ¦ [h4] [h3] [h2] [h1]¦ ' ¦ ¦ ' =============================================== '----------------------------------------------------------- ' ТАБЛИЦА КОДОВ СЕГМЕНТОВ , СВЕЧЕНИЕ "0" '----------------------------------------------------------- 'ШЕСТНАДЦАТИРИЧНЫЕ ЦИФРЫ ОТ 0(00h) ДО 15(0Fh) Tabseg0: Data &HC0 , &HF9 ' 0 , 1 -d0 - Data &HA4 , &HB0 ' 2 , 3 I I Data &H99 , &H92 ' 4 , 5 D5 D1 Data &H82 , &HF8 ' 6 , 7 I I Data &H80 , &H90 ' 8 , 9 -d6 - ============================================================================= 19 ===================================== Справочник по программированию «Bascom-AVR» == Data &H88 , &H83 ' A , B I I Data &HC6 , &HA1 ' C , D D4 D2 Data &H86 , &H8E ' E , F I I ' -D3- [D7] '----------------------------------------------------------- 'ДРУГИЕ СИМВОЛЫ (УСЛОВНАЯ НУМЕРАЦИЯ) Data &HAF ' R *(16) Data &HE3 ' U *(17) Data &HC7 ' L(18) Data &HFF ' ПРОБЕЛ(19) Data &H0B ' H *(20) Data &HB7 ' =(21) Data &HF7 ' _(22) Data &HC3 ' ЛЕВАЯ ЧАСТЬ БУКВЫ "W"(23) Data &HE1 ' ПРАВАЯ ЧАСТЬ БУКВЫ "W"(24) Data &H0C ' P(25) Data &HFB ' I *(26) Data &H07 ' T *(27) Data &HAB ' П *(28) Data &HA3 ' O *(29) Data &HE7 ' L *(30) Data &H09 ' H(31) Data &H9C ' ГРАДУС(32) Data &HAF ' ФРОНТ -(33) Data &HBB ' СПАД ¬(34) Data &HBF ' МИНУС -(35) 'ПРИМЕЧАНИЕ. * - МАЛЫЕ СИМВОЛЫ '----------------------------------------------------------- 'сообщения индикатора, записанные в номерах символов таблицы Tabseg0 Tr_led: Data 17 , 22 , 1 , 2 ' "v_12" (0) |