Закрыть ... [X]

Bascom как сделать кнопку

Dim DDSWord as Long

Const DDSClock = '100MHz

Declare Function MakeDDSWord(byref Frequency as Long) as Long

DDSWord = MakeDDSWord(Frequency)

Function MakeDDSWord(byref Frequency as Single) as Long

MakeDDSWord = 2 ^ 32

MakeDDSWord = MakeDDSWord / DDSClock

MakeDDSWord = MakeDDSWord Frequency

End Function

В строке DDSWord = MakeDDSWord(Frequency) функция MakeDDSWord вызывается с аргументом Frequency. Функкция должна вернуть хотя бы одно значение, но возможно (хотя и жутко нелогично для функций) изменение аргументов, данных функции. Чтобы разрешить это сделать, используйте параметры Byval и Byref, как и для подпрограмм.

Локальные переменные

В подпрограмме или функции можно объявить переменные, существующие только внутри неё. Они недоступны из основной программы. Для объявления такой переменной используйте оператор Local:

Local Temporaryval as Integer
Local Justfornow as Long

Все типы переменных, за исключением Bit, могут быть объявлены как локальные. Переменные типа Bit всегда глобальные.

Прерывания и таймеры 

Допустим, у вас есть BASCOM программа, которая зацикленно выполняет какое-то сложное и запутанное действо, и вам вдруг захотелось остановить это задание и заставить контроллер сделать что-то другое. Очевидное аппаратное решение - добавить кнопку "STOP".

Обычно вы бы стали проверять нажатие кнопки примерно таким кодом:

...

Config Pind.2 as Input

...

Do

...

... 'что-то запутанное...

...

If Pind.2 = 0 Then

Lcd "stopъ!"

Goto Othertask

End If

Loop

...

OtherTask:

...

Главный недостаток этого метода заключается в том, что мы потратим кучу времени на выполнение чего-то запутанного, и в итоге мы просто пропустим момент нажатия кнопки. Другими словами, кнопка будет нажата и уже отпущена к тому моменту, как программа дойдет до процедуры проверки Pind.2. Очевидно, что нам нужен другой способ проверить нажатую кнопку, независимо от хода выполнения других процедур.
Такое решение предоставляют нам прерывания. Прерывания изменяют нормальный ход выполнения программы и заставляют МК реагировать на внешние события так же, как и на внутренние. Нам достаточно немного изменить код:
interrupt-stopbutton. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Pind.2 = Input

Config Int0 = Falling

Dim Wtime As Byte

On Int0 Stopbutton

Cls

Wtime = 255

Enable Interrupts

Enable Int0

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Loop

Stopbutton:

Lcd "stopъ!"

Return

End

Pind.2 настроен на вход. Не забудьте про подтягивающий резистор 10кОм!
Config Int0 = Falling заставляет сработать прерывание по спаду сигнала, т. е. при переходе с высокого уровня на низкий.
Когда происходит прерывание Int0, программа переходит на метку Stopbutton.
Нужно включить прерывания как в целом, так и конкретно Int0!
В цикле Do-Loop "какое-то запутанное задание" - это мигание светодиодом.
Подпрограмма Stopbutton выводит "stopъ!" на ЖК индикатор, затем продолжает работу основной программы с того места, где она была прервана.

Здесь светодиод зацикленно включается и выключается, а большая часть времени ухожит на задержку Waitms. При нажатии на кнопку происходит переход на метку Stopbutton. На ЖКИ выводится "stopъ!", и программа возвращается к светодиоду.
Однако написание слов на ЖК индикаторе - далеко не единственое применение прерываний. Почему? Узнаете сами, немного позже. Для начала обзор прерываний, реализуемых в AT90S2313:

Прерывания AT90S2313

A. Внешние прерывания:
Int0 внешнее прерывание на PortD.2, pin 6
Int1 внешнее прерывание на PortD.3, pin 7
Counter0 прерывание по переполнению, PortD.4, pin 8
Counter1 прерывание по переполнению, PortD.5, pin 9
Timer1 прерывание по захвату, PortD.5, pin 9
Timer1 прерывание по сравнению, PortD.5, pin 9
Serial Rx прерывание по окончании приема
Analog comparator0 прерывание компаратора, PortB.0, pin 12
Analog comparator1 прерывание компаратора, PortB.1, pin 13

B. Внутренние прерывания:
Timer0 прерывание по переполнению
Timer1 прерывание по переполнению
Serial data register прерывание по опустошению
Serial Tx прерывание по окончании передачи

Все прерывания в AVR имеют одинаковый приоритет. Это отличает их от других микроконтроллеров, где вы можете задать приоритет для каждого вида прерывания по отношению к другому.
Если вы используете другой AVR микроконтроллер, используйте BASCOM файл .def для определения доступных видов прерывания. А также почитайте даташит (обязательно!).

ВКЛ/ВЫКЛ прерываний

Когда вы пишете программу на BASCOM, прерывания по умолчанию отключены. Их нужно включить с помощью команды:

Enable Interrupts

Прерывания включаются всей группой. Аналогично, они могу быть и отключены:

Disable Interrupts

Это может оказаться полезным, если у вас есть серьезный фрагмент в коде, выполнение которого нельзя прервать ни под каким предлогом:

Enable Interrupts

Enable Int0

Enable Timer0

...

Disable Interrupts

...

Очень важный фрагмент кода...

...

Ладушки, справились...

...

Enable Interrupts

...

Здесь за раз включаются/отключаются ВСЕ прерывания. Отдельные прерывания включаются в индивидуальном порядке:

Enable Interrupts

Enable Int0

Enable RX0

Enable Counter0

...

Так же точно они и отключаются:

...

Disable Counter0

...здесь нет прерываний counter0...

Enable Counter0

...

Подпрограммы прерываний

Каждое прерывание должно иметь свою подпрограмму обработки событий. Подпрограмма - это фрагмент кода с меткой, набором команд и функцией возврата Return. Для каждого включенного прерывания вы должны указать подпрограмму, на которую нужно перейти при происхождении события:

On Int0 Stopbutton

On Int1 LcdMenu

On Counter0 Revcalc

...

Enable Interrupts

Enable Int0

Enable Int1

Enable Counter0

...

Главная программа

...

Stopbutton:

Lcd "stop!"

...

Return

LcdMenu:

Cls

Lcd "Калибровка: дави A!"

...

Return

Revcalc:

Revs = Counter0 Revfactor

Counter0 = 0

...

Return

Помните, что все подпрограммы начинаются с метки - названия, оканчивающимся ":" (двоеточием).

Нет прерываниям в прерывании!

В тот момент, когда программа прерывается и переходит к подпрограмме обработки прерывания, все включенные прерывания отключаются на время работы этой подпрограммы. Когда ее выполнение достигает оператора Return и переходит к тому месту в главном коде, на котором его выполнение было прервано, отключенные прерывания снова включаются. Это делается для того, чтобы подпрограммы обработки не прерывали сами себя (это как змея начала бы кушать себя с хвоста!). Такое поведение, отличающееся от микроконтроллеров большинства других фирм, заложено в самой AVR архитектуре, не в BASCOM.

Кратк. - сест. тал.

Делайте подпрограммы обработки прерываний как можно короче! Помните, что ваша программа прерывается, чем бы она ни занималась, и она не должна быть прервана надолго. Старайтесь не делать в прерываниях ничего сложнее, чем изменение счетчиков или флагов. Фрагменты обработки этих данных лучше всего разместить в главном коде. Сравните две программы - вот эту:

On Int0 Stopbutton

Enable Interrupts

Enable Int0

Do

...

Loop

End

Stopbutton:

Lcd "stop!"

...

Делаем что-то сложное...

Return

С вот этой:

Dim Stopflag as Bit

On Int0 Stopbutton

Enable Interrupts

Enable Int0

Do

...

If Stopflag = 1 Then

Reset Stopflag

...

Делаем что-то сложное...

...

End If

Loop

End

Stopbutton:

Set Stopflag

Return

Во втором случае подпрограмма Stopbutton максимально сокращена, в ней только устанавливается флаг Stopflag. А он уже обрабатывается в главном коде. Однако будьте внимательны! В таком случае прерывание может быть обработано намного позже, чем оно произошло!

Еще про int0/int1

Int0 и Int1 - внешние прерывания. Обычно они вызываются кнопками, переключателями, импульсами или логическими уровнями с других цепей. Вы можете предопределить, как обработчик прерываний будет реагировать на изменение сигнала:

Config Intx = Low Level

Config Intx = Falling

Config Intx = Rising

Таким образом, прерывания генерируются, пока сигнал на Intx низкий, по спаду и по фронту. Low Level создает прерывания все время, пока управляющий уровень низкий. Например:

$regfile = "2313def. dat"

$crystal = 4000000

Dim Cntr As Integer

On Int0 Button

Config Int0 = Low Level

Cls

Enable Interrupts

Enable Int0

Do

Locate 1 , 1

Lcd Cntr

Waitms 250

Loop

Button:

Incr Cntr

Return

End

В подпрограмме обработки значение счетчика увеличивается и отображается на дисплее четыре раза в секунду.

В справке BASCOM недокументирован (как считает pa3ckr) тот факт, что Low Level - конфигурация прерывания по умолчанию. Однако прерывание по фронту или по спаду намного распространеннее.

Неприятное явление дребезга

Идеальная кнопка переключает состояние строго с разомкнутого на замкнутое и наоборот. Однако, реальные кнопки обладают "дребезгом". При нажатии кнопка "генерирует" серию импульсов, причем у некоторых экземпляров эта серия длится до 50 миллисекунд. Вот осциллограмма сигнала нажатия кнопки, подключенной к земле через 10килоомный подтягивающий резистор:

На самом деле это очень даже хорошая кнопочка - дребез у нее длится всего 0.5 мс. Таким образом, если ваша программа реагирует на спад или фронт, вы получите кучу прерываний вместо одного. Поэтому нам необходимо реализовать функцию антидребезга, например, добавив задержку:
interrupt-debounce-self. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Pind.2 = Input

Config Int0 = Falling

Config Debounce = 50

Dim Wtime As Byte

Const Debouncetime = 75

On Int0 Stopbutton

Cls

Wtime = 255

Enable Interrupts

Enable Int0

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Loop

Stopbutton:

Lcd "stop!"

Waitms Debouncetime

Gifr = 64

Return

End

В эту продпрограмму всего лишь добавлен оператор задержки waitms. Поскольку на время обработки прерывания отключаются, программа среагирует только на первый импульс. Выберите значение константы Debouncetime так, чтобы оно было больше наибольшего времени дребезга используемых кнопок. Также в BASCOM есть команда Debounce, которую тоже можно использовать в прерываниях.

Что за GIFR?

В вышеприведенном примере, в подрограмме прерывания есть странная строка Gifr=64. Что это за Gifr за такой? Уберите эту строчку и посмотрите, что получится: практически в любом случае "stop!" будет выведено на ЖКИ два раза. Как же такое возможно?
А посмотрите вот этот пример: interrupt-deb-pre. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Pind.2 = Input

Config Int0 = Falling

Dim Wtime As Byte

On Int0 Stopbutton

Cls

Set Portd.6

Waitms 3000

Reset Portd.6

Wtime = 255

Enable Interrupts

Enable Int0

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Loop

Stopbutton:

Lcd "stop!"

Waitms 75

Return

End

После очистки ЖКИ включается светодиод. Затем следует трехсекундная задержка, после чего гаснет светодиод и включаются прерывания. Теперь сбросьте МК и попробуйте нажать кнопку, пока включен светодиод. У вас есть три секунды, так что думаю, у вас не возникнет проблем (а иначе - вам делать нечего тут! прим. WildCat'a). После погасания светодиода включается Int0, и вы заметите, что программа переходит к подпрограмме Stopbutton. Поэтому, даже если вы нажмете кнопку перед включением прерываний, данные о срабатывании где-то сохранятся, и после включения прерывание немедленно выполнится.

Вот что происходит в AT90S2313 (да и в других МК AVR). Даже если соответствующее прерывание НЕ включено, данные о его срабатывании хранятся в "General Interrupt Flag Register" (GIFR или Главный Регистр Флагов Прерываний). Это один из тех редчайших случаев, когда даже пользователям BASCOM придется вникнуть во внутреннее строение AVR (я вас не заставляю!) Регистр GIFR имеет восемь бит, из которых шестой и седьмой зарезервированы для Int0 и Int1 соответственно:

И вот что происходит в нашей программе interrupt-debounce-self. bas: В подпрограмме обработки, когда прерывания выключены, данные о срабатывании все равно приходят из-за дребезга контактов. Прерывания отмечаются в GIFR нулевым битом. Для Int0 это шестой бит, для Int1 - седьмой. Все, что нужно сделать для устранения нашей проблемы - это установить соответствующие биты в GIFR перед командой Return в подпрограмме обработки. Тогда дальнейшие (бесполезные) прерывания после продолжения работы обрабатываться не будут.

Зарегистрированные имена регистров

Теперь мы знаем, что есть несколько зарегистрированных имен регистров. Избегайте их использования в ваших программах. Используйте справку BASCOM (запустите справку, нажмите "Поиск" и введите "AVR internal registers") и даташит AT90S2313 (table 1, страницы 15 и 16).

Таймеры и счетчики

В AT90S2313 есть два таймера/счетчика (убедитесь, что вы прочитали 27 страницу... ну вы поняли, чего). Timer0 - это восьмибитный таймер/счетчик, может принимать значения от 0 до 255.
С командой Config мы можем настроить его, как нам заблагорассудится:

Config Timer0 = Timer, Prescale = 1|8|64|256|1024

Здесь Timer0 настроен на счет тактовых импульсов. Он считает тактовые импульсы с выхода делителя с настраиваемым коэффициентом 1, 8, 64, 256 или 1024. Таймер считает время, в течение которого он изменяется с 0 до 255. Пусть в нашем проекте стоит кварц 4МГц и делитель на 1024. Тогда таймер будет увеличивать значение каждые (коэффициент/тактовая частота, 1024/4.000.000)=0,256 миллисекунд. Тогда переполняться он будет каждые 2550,256=65 миллисекунд. Time1 аналогичен Timer0, но он 16-битный, он считает до 65535 до переполнения. Таймеры начинают отсчет с момента конфигурации.
Вот пример использования timer0 (вам нужен AT90S2313 с подключенным дисплеем):
interrupt-timer0-free. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Pinb.1 = Output

Config Timer0 = Timer, Prescale = 1024

Dim Wtime As Byte

Dim Timercounter As Byte

Wtime = 100

Timercounter = 0

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Cls

Timercounter = Timer0

Lcd "tmrcntr: " ; Timercounter

Loop

End

И пример использования Timer1:
interrupt-timer1-free. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Pinb.1 = Output

Config Timer1 = Timer, Prescale = 1024

Dim Wtime As Byte

Dim Timercounter As Word

Wtime = 100

Timercounter = 0

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Cls

Timercounter = Timer1

Lcd "tmrcntr: " ; Timercounter

Loop

End

Конечно, главное отличие в том, что здесь переменная Timercounter представлена как Word. Текущие значения таймеров в любой момент могут быть прочитаны и записаны в переменную соответствующего типа.
Эти два примера используют свободно запущенные таймеры. Их можно запустить и остановить в любой момент:

Start Timer0

Stop Timer0

Start Timer1

Stop Timer1

И поскольку это обычные регистры AVR, вы можете не только считать их, но и записать в них значение:

Stop Timer1

...

Timer1 = 132

...

Start Timer1

Прерывания по таймеру

Наиболее распространенное использование таймеров - создание прерываний через равные промежутки времени для выполнения какого-то задания, например, проверки состояния порта, или наоборот, вывод импульса.
Вот пример генератора импульсов (используйте схему с кнопкой "Stop", выход на portb.1):
interrupt-timer0-pulse. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Pinb.1 = Output

Config Timer0 = Timer, Prescale = 64

Dim Wtime As Byte

On Timer0 Pulse:

Wtime = 100

Enable Interrupts

Enable Timer0

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Loop

Pulse:

Toggle Portb.1

Return

End

Делитель настроен на коэффициент 64, timer0 будет увеличиваться каждые 16 микросекунд. Так как он считает до 255, переполнение будет через 25616=4096 микросекунд. На каждом прерывании по переполнению генерируется импульс. В подпрограмме обработки состояние portb.1 переключается, т. е. уровень в зависимости от предыдущего состояния меняется на противоположный.
В результате на выходе мы получим красивый меандр с периодом примерно 8 миллисекунд на portb.1:

AT90S2313 довольно шустрый! Попробуйте настроить деление на 1 и проверьте результат на portb.1. Период сигнала примерно 120 микросекунд.

Вся эта прелесть работает, пока время работы подпрограммы меньше времени включения/выключения сигнала. Попробуйте вставить команду Cls в прерывание. Вы увидите, что период возрастет со 120 микросекунд до 12 миллисекунд!

Длительность задержки

Во всех этих примерах прерывание создается по переполнению счетчика таймера. Это значит, что мы ограничены в выборе времени тактовой частотой, коэффициентом деления и размерностью регистра таймера. Один из способов создания определенного промежутка времени - не давать таймеру свободно заполняться от 0 до максимального значения, а задавать некоторое ненулевое значение регистра после каждого переполнения. Мы можем выбрать его таким образом, чтобы получить нужное время заполнения от этого значения до максимума:
interrupt-timer1-preload. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Pinb.1 = Output

Config Timer1 = Timer, Prescale = 1

Const Timer1pre = 65100

Dim Wtime As Byte

Stop Timer1

Timer1 = Timer1pre

On Timer1 Pulse:

Start Timer1

Wtime = 100

Enable Interrupts

Enable Timer1

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Loop

Pulse:

Stop Timer1

Timer1 = Timer1pre

Toggle Portb.1

Start Timer1

Return

End

После каждого переполнения Timer1 в его регистр помещается значение 65100, поэтому перед каждым прерыванием он считает от 65100 до 65535. Это занимает (65 0,25 = 109 микросекунд. Изменяя константу Timer1pre, вы можете задать время включения/выключения с точностью 0,25 микросекунд.

Подсчет внешних импульсов

Timer0 и Timer1 могут быть настроены на счет внешних импульсов на выводах T0 и T1:

Config Timer0 = Counter, Prescale = 1|8|64|256|1024, Edge = Rising|Falling

Config Timer1 = Counter, Prescale = 1|8|64|256|1024, Edge = Rising|Falling

Вы можете выбрать счет по фронту или по спаду. Также вы можете задать предделитель для счета. Особенно интересен Timer1, так как он может считать до 65535 перед переполнением.
Имена Timerx, Counterx и Capturex в BASCOM соответствуют именам регистров, поэтому нельзя использовать одноименные переменные в программе, что не есть хорошо.
Когда Timer0 и Timer1 используются для подсчета внешних импульсов, контроллер будет квантовать входы со своей тактовой частотой. Это значит, что для точного подсчета частота следования импульсов не должна превышать половины тактовой частоты. Для безопасности старайтесь подавать импульсы на вход с частотой ниже 40% от тактовой. Так, для кварца 4МГц частота следования импульсов не должна превышать 1,6МГц. Проверьте это на ТТЛ генераторе, подключенном к T1 (Portd.5, 9 нога для AT90S2313):
counter1.bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Timer1 = Counter, Edge = Falling, Prescale = 1

Stop Counter1

Set Portd.6

Waitms 1000

Reset Portd.6

Waitms 1000

Cls

Do

Counter1 = 0

Start Counter1

Waitms 25

Stop Counter1

Cls

Lcd "Counter1: " ; Counter1

Waitms 100

Loop

End

В Do-Loop цикле Counter1 очищается и запускается. После задержки 25 мс Counter1 останавливается, и его значение выводится на ЖКИ. Заметьте: отсчет времени командой Waitms не очень точный. Есть более точные способы создания задержек.

Постепенно повышайте частоту импульсов с генератора и следите за тем, что происходит после 1.6 МГц.

Timer1 считает до 65535. Если вам этого мало, вы можете подсчитывать общее число срабатываний таймера в подпрограмме:
counter2.bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Timer1 = Counter, Edge = Falling, Prescale = 1

Dim Wtime As Byte

Dim Timercounter As Word

Dim Overflcounter As Word

Dim Totalcounter As Long

On Counter1 Uphigh

Wtime = 100

Timercounter = 0

Totalcounter = 0

Enable Interrupts

Enable Counter1

Do

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Cls

Timercounter = Counter1

Lcd Timercounter ; " " ; Overflcounter

Lowerline

Totalcounter = Overflcounter

Shift Totalcounter, Left, 16

Totalcounter = Totalcounter + Timercounter

Lcd "total: " ; Totalcounter

Loop

Uphigh:

Incr Overflcounter

Return

End

Здесь заданы три переменные:
Overflowcounter (16-битное слово) хранит количество переполнений Timer1.
Timercounter (16-битное слово) хранит текущее значение Timer1.
. Totalcounter (32-битная Long) хранит значение Overflowcounter, сдвинутое на 16 разрядов влево + значение Timercounter.

Timer1 в режиме захвата

Timer1 может работать в режиме "Capture" (захвата). Это значит, что Timer1 считает тактовые импульсы через предделитель, и, когда на вход ICP (portd.6, 11 нога) приходит импульс, содержимое Timer1 копируется в регистр Input Capture. Таким способом можно точно измерить время между двумя импульсами:

Config Timer1 - Timer, Prescale = 1|8|64|256|1024, Capture Edge = Rising|Falling

interrupt-timer1-capture. bas

$regfile = "2313def. dat"

$crystal = 4000000

'Config Pind.6 = Output

Config Timer1 = Timer, Prescale = 64 , Capture Edge = Rising

Dim Wtime As Byte

Dim Timercounter As Word

On Capture1 Captmr

Wtime = 100

Timercounter = 0

Enable Interrupts

Enable Capture1

Do

'Set Portd.6

Waitms Wtime

'Reset Portd.6

Waitms Wtime

Cls

Lcd "pwidth: " ; " " ; Capture1

Loop

Captmr:

Timercounter = Capture1

Timer1 = 0

Return

End

В подпрограмме прерывания значение Timer1 (Capture1 - это второе имя этого регистра) копируется в Timercounter. Затем Timer1 очищается. При последующем импульсе на ICP входе цикл повторяется. Следовательно, Timercounter считает время между импульсами на ICP.

Компаратор на Timer1

У Timer1 есть регистр сравнения CompareA (в BASCOM также есть регистр CompareB, но он отсутствует в AT90S2313). В этот регистр можно положить конкретное значение. Когда значение Timer1 сравняется со значением CompareA, предописанное действие даст результат на OC1 (Portb.3, 15 нога):

Config Timer1 = Timer, Prescale = 1|8|64|256|1024, Compare A = Clear|Set|Toggle|Disconnect, Clear Timer = 0|1

Действием может быть:
- Установить OC1
- Сбросить OC1
- Переключить OC1
- Отключить OC1

С помощью Clear Timer можно очистить Timer1, когда произойдет прерывание CompareA.

Наиболее используемая функция - Toggle (переключение). Она используется для генерирования точной частоты на OC1.
compare. bas

$regfile = "2313def. dat"

$crystal = 4000000

Config Pind.6 = Output

Config Timer1 = Timer, Prescale = 1 , Compare A = Toggle, Clear Timer = 1

Dim Wtime As Byte

Dim Compval As Word

Wtime = 100

Do

For Compval = 100 To 10000 Step 100

Compare1a = Compval

Waitms 10

Next Compval

Set Portd.6

Waitms Wtime

Reset Portd.6

Waitms Wtime

Loop

End

В цикле Do-Loop в регистр CompareA помещается значение Compval, находящееся в промежутке Когда Timer1 сравняется с CompareA, вывод OC1 меняет значение на противоположное, и таймер очищается.

Подключите маленький динамик последовательно с резистором в несколько сот Ом к OC1 (Portb.3, 15 нога) и слушайте музыку...

Прерывания UART

В AT90S2313 есть три вида UART прерываний:
1. Tx ready - когда последний бит передан и буфер отправки пуст. Такой вид используется при работе в полудуплексном режиме, и вы должны знать, когда переходить с передачи на прием. В полнодуплексном режиме (по умолчанию) такое прерывание не требуется.
2. Буфер передачи пуст. Это прерывание возникает, когда символ из буфера данных переписан в буфер отправки. Его можно использовать, чтобы знать, что пора отправлять следующий символ. Вам это прерывание особенно не потребуется, так как при передаче строки BASCOM все сделает за вас.
3. Rx ready - когда по UART получен символ и помещен в буфер данных. Этот символ нужно считать как можно скорее, пока не пришел следующий. BASCOM также сам обрабатывает и прием строк по UART, но это прерывание можно использовать, например, для изменения порядка выполнения программы:
interrupt-rs232rx. bas

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6
Источник: http://pandia.ru/text/78/240/43300-2.php


Поделись с друзьями



Рекомендуем посмотреть ещё:



Как сделать включение и выключение питания девайса на AVR кнопкой? Форум Пресс скамья своими руками

Bascom как сделать кнопку Bascom как сделать кнопку Bascom как сделать кнопку Bascom как сделать кнопку Bascom как сделать кнопку Bascom как сделать кнопку Bascom как сделать кнопку Bascom как сделать кнопку Bascom как сделать кнопку

ШОКИРУЮЩИЕ НОВОСТИ