Файл: Справочник по программированию «Bascom-AVR» (М.Л. Кулиш).pdf

ВУЗ: Не указан

Категория: Не указан

Дисциплина: Не указана

Добавлен: 17.06.2025

Просмотров: 755

Скачиваний: 3

ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.

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

Пример 5 - Прерывание от изменения уровня на линиях порта

'----------------------------------------------------------------------------------

"m644def.dat"

'для чипа ATMega644

$regfile =

' ......

Dim Num_port As Byte

'номер порта с изменившимся уровнем

Dim Dub_pa

As Byte

'дублер порта A

Dim Dub_pb

As Byte

'дублер порта B

Dim Dub_pc

As Byte

'дублер порта C

Dim Dub_pd

As Byte

'дублер порта D

Dim Tmpb As Byte

'временные байтовые данные

' ......

'определим действующие линии портов как константы

Const Pcamsk = &B11111111

'порта PA

Const Pcbmsk = &B11111111

'порта PB

Const Pccmsk = &B00000011

'порта PC

Const Pcdmsk = &B00111100

'порта PD

' ......

On Pcint0 Pc_int0

'векторы прерывания от изменения уровней на линиях портов

On Pcint1 Pc_int1

On Pcint2 Pc_int2

On Pcint3 Pc_int3

' ......

'настроить систему

'разрешим прерывания от изменения уровны во всех портах

Pcicr = &B00001111

Pcmsk0

= Pcamsk

'определим действующие линии портов: порта PA

Pcmsk1

= Pcbmsk

'порта PB

Pcmsk2

= Pccmsk

'порта PC

Pcmsk3

= Pcdmsk

'порта PD

Dub_pa

= Pina And Pcamsk

'запомнить текущее состояние линий портов

Dub_pb

= Pinb And Pcbmsk

Dub_pc

= Pinc And Pccmsk

Dub_pd

= Pind And Pcdmsk

Enable

Interrupts

' ......

'главный цикл

Mc:

Num_port <> 0 Then

If

Print Num_port : Num_port = 0

End If

Goto Mc

'--------------------------------------

обработки прерываний от изменения уровня, сообщающие главной программе

'программы

'о наличии

изменения ненулевым значением переменной Num_port

'--------------------------------------

порта A

'по линиям

Pc_int0:

Pina Xor Pcamsk : Tmpb = Pina Xor Dub_pa : Num_port = 0

Tmpb =

Gosub Search_pin

'добавить в Num_port номер позиции единицы

Return

'--------------------------------------

порта B

'по линиям

Pc_int1:

Tmpb = Pinb Xor Pcbmsk : Tmpb = Pinb Xor Dub_pb : Num_port = 8

Gosub Search_pin

'добавить в Num_port номер позиции единицы

Return

'--------------------------------------

'по линиям порта C

Pc_int2:

Tmpb = Pinc Xor Pccmsk : Tmpb = Pinc Xor Dub_pc : Num_port = 16

Gosub Search_pin

'добавить в Num_port номер позиции единицы

Return

'--------------------------------------

'по линиям порта D Pc_int3:

Tmpb = Pind Xor Pcdmsk : Tmpb = Pind Xor Dub_pd : Num_port = 24

Gosub Search_pin

'добавить

в Num_port номер позиции единицы

Return

'--------------------------------------

"1" в измененного

уровня, на

самом деле, это преобразование

'подпрограмма поиска

'позиционного кода в

Tmpb в двоичный в

Num_port. Методом сдвига вправо и искремента результата

============================================================================= 30


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

Search_pin:

'повторять пока регистр Tmpb не станет равным нулю

While Tmpb <> 0

Shift Tmpb , Right : Incr Num_port

Wend

Return

'----------------------------------------------------------------------------------

Обработчик прерывания, написанный без применения ассемблера, не может иметь оптимального кода. Это показывает дисассемблированный текст (пример 6). Мы видим, что обработчик с одной стороны не выполняет недопустимых действий, а с другой – имеет явную избыточность и расточителен.

Пример 6 - Ассемблерный текст обработчика прерывания (листинг) из программы примера 5, получаемый при компиляции Bascom-AVR

'----------------------------------------------------------------------------------

Pc_int0:

;сохранение регистрового блока

push

r0

push

r1

push

r2

push

r3

push

r4

push

r5

push

r7

push

r10

push

r11

push

r16

push

r17

push

r18

push

r19

push

r20

push

r21

push

r22

push

r23

push

r24

push

r25

push

r26

push

r27

push

r28

push

r29

push

r30

push

r31

in

r24,$3F

push

r24

;Tmpb = Pina Xor Pcamsk

in

r16,$0

ldi

r20,#255

eor

r16,r20

ldi

r26,#5

ldi

r27,#1

st

x,r16

;Tmpb = Pina Xor Dub_pa

in

r16,$0

lds

r20,$101

eor

r16,r20

ldi

r26,#5

ldi

r27,#1

st

x,r16

;Num_port = 0

r24,#0

ldi

sts

$100,r24

'добавить в Num_port номер позиции единицы

;Gosub Search_pin

call

0000036A

;восстановление регистрового блока

pop

r24

out

$3F,r24

pop

r31

pop

r30

pop

r29

pop

r28

pop

r27

pop

r26

pop

r25

pop

r24

pop

r23

pop

r22

pop

r21

============================================================================= 31


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

pop

r20

pop

r19

pop

r18

pop

r17

pop

r16

pop

r11

pop

r10

pop

r7

pop

r5

pop

r4

pop

r3

pop

r2

pop

r1

pop

r0

;Return

Reti

;------

;подпрограмма Search_pin:

0000036A:

'повторять пока регистр Tmpb не станет равным нулю

While Tmpb <> 0

r16,$105

lds

cpi

r16,#0

brne

00000376

jmp

0000038E

00000376:

;Shift Tmpb , Right

ldi

r25,#1

ldi

r26,#5

ldi

r27,#1

;вызов библиотечной программы

call

000003C6

;Incr Num_port

r26,#0

ldi

ldi

r27,#1

ld

r24,x

subi

r24,#255

st

x,r24

;Wend

0000036A

jmp

0000038E:

ret

;------

;библиотечная подпрограмма сдвига вправо на число в R25

000003C6:

r25,#0

cpi

breq

000003D4

ld

r24,x

000003CC:

r24

lsr

dec

r25

brne

000003CC

st

x,r24

000003D4:

ret

'----------------------------------------------------------------------------------

============================================================================= 32


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

Вопросы и ответы (1-10)

---------------------------------------------------------------------------------------------------------------------------------------------------

Вопрос 1

Но вот не могу понять только одного, почему в такой короткой программе, как эта:

Dim A As Byte

For A=1 to 30

Print A

Next A

End

…при компиляции размер кода составляет более 300 байт?? Абсурд! Баском конечно кушает память, но чтобы так!.. Может я в чём не прав?

Ответ 1

1 Насчет размера вашего примера. Такой же будет для любого компилятора. В этот размер входит:

-заголовок программы, включаемый в код автоматически (по умолчанию) и содержащий место под все вектора прерывания по 4 байт на вектор, очистку памяти 20-30 байт и инициализацию оборудования 30 - 100 байт;

-библиотека используемой функции и плюс 2-3 стандартных - около 100 байт;

-и собственно код вашей программы. Т.е. все сходится. Зато еще один вызов данной функции приводит к добавлению всего 20 - 30 байт.

---------------------------------------------------------------------------------------------------------------------------------------------------

Вопрос 2

Да и вообще, здесь много подводных камней, про которые даже в pdf-файле не найдешь…Я изучал когда-то давно Бейсик, сейчас плохо помню, приходиться заново учить. К какому Бейсику ближе Баском?

Ответ 2

Синтаксис и мнемоника, в принципе, отвечают стандарту Basic для DOS с учетом особенностей, ограничений и дополнительных возможностей. Лучше на стандартный Basic не ориентироваться. Слишком много ограничений, обусловленных различными возможностями процессоров. Главное отличие в том, что нужно определить тип переменных заранее, не допускать скрытого преобразования типов и не применять больше одного действия в одном операторе.) Лучше ориентироваться на оригинальное описание Bascom-AVR – оно отличное. На русском имеется только описание Bascom-8051. И еще на примеры - их очень много.

--------------------------------------------------------------------------------------------------------------------------------------------------

Вопрос 3

Я сначала ничего не подозревал. Пытался спокойно делать себе программки в Баскоме, как вдруг понял, что реализация протокола I2C(TWI) в любом микроконтроллере происходит программно, независимо от того, есть ли в нём аппаратная поддержка данного протокола или нет. Я бы ничего этого не заметил, если бы не наткнулся на проблему нехватки памяти микроконтроллера. В конечном итоге выяснилось, что реализация аппаратного протокола возможна только в лицензионной версии Баскома, так как в демо-версии нет соответствующей библиотеки.

Ответ 3

По моему наблюдению, использование аппаратного контроллера с точки зрения размера кода совершенно неэффективно. При программной реализации размер кода получается равноценным. Потому, что работа с аппаратным портом конечно проще, но при этом требуется организовать обработку соответствующего прерывания. Преимущество аппаратного I2C только в возможности осуществлять "прозрачную" работу одновременно с другими процессами и при наличии очень медленных устройств. Когда, например, в фоновом режиме нужно постоянно считывать или дописывать данные. При этом в коде "весит" именно программа организации МАССИВА записываемых или считываемых данных, а не сам драйвер. Вот пример работающей программы на BAS и на ASM. В основной программе применяются готовые функции. В прерывании используется ассемблерная программа (а ее размер минимален). Если устройство более медленное - нужно вместо NOP-ов добавить в программу подпрограммы более продолжительной задержки. Не забывать, что когда работаешь с I2C, нужно бы запретить прерывания. Если длительность импульса SCL превысит 10 мкс устройство может само отключится! В последующем примере переключение уровней делается изменение направления порта. Это важно. Так можно манипулировать с им намного быстрее.

'--------------------------------------------------------------

============================================================================= 33