BASCOM AVR в вопросах и ответах
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: BASCOM AVR в вопросах и ответах
Если че, то АЦП может заниматься несколькими процессами. Еще можно подтяжки менять на ноге и проверять что на входе.
Re: BASCOM AVR в вопросах и ответах
zero648 писал(а):Если че, то АЦП может заниматься несколькими процессами. Еще можно подтяжки менять на ноге и проверять что на входе.
А можно примерчик?
В моем случае, АЦП принимает значение до 1023.
Не представляю, как заставить его принимать (-) и (+)...
И еще вопрос - Как работать с таймером?
Написал примитивный код и все работает, но имеется один баг - кнопка тупит и срабатывает в моем случае 1 раз в 5 сек.
Это из-за того, что в коде имеется задержка типа:
Код: Выделить всё
For Count = 0 To 500 'считаем до 500
Waitms 10 '10 * 500 = 5 сек
С waitms/wait происходит то же самое.
Даже, если кнопку повесить на прерывание INT0 - и даже тут крах!
А я почему-то думал, что внешнее прерывание сразу уходит в обработку без всяких задержек и условий.
Не тут-то было! Тоже срабатывает через раз.
Погуглил и понял, что без таймера не обойтись.
Вопрос в другом: кнопку на таймер сажать или саму задержку?
Код: Выделить всё
...
Config Timer0 = Timer , Prescale = 64
On Timer0 Button:
...
Do
...
...
Loop
Button:
....
Return
End
И как из этой строки узнать, через сколько мск произойдет прерывание?
Товарищи коты, помогите примерчиком с комментариями или ссылку для разбора подкиньте.
Буду признателен

Продолжаю лопатить интернет - все не то...

Не срабатывает прерывание на кнопках
Подскажите, где может быть ошибка?
Не реагирует на кнопки.

Не реагирует на кнопки.
Код: Выделить всё
$regfile = "m32def.dat" ' specify the used micro
$crystal = 8000000 ' used crystal frequency
$baud = 19200 ' use baud rate
$hwstack = 32 ' default use 32 for the hardware stack
$swstack = 10 ' default use 10 for the SW stack
$framesize = 40 ' default use 40 for the frame space
'$sim
'===============
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.1 , Rs = Portb.0
Config Lcd = 20 * 4
Config Debounce = 75
Config Int2 = Falling
Config Portc.2 = Input : Portc.2 = 1
Config Portc.3 = Input : Portc.3 = 1
Config Portc.4 = Input : Portc.4 = 1
Config Portc.5 = Input : Portc.5 = 1
Config Portc.6 = Input : Portc.6 = 1
Config Portb.2 = Input : Portc.2 = 1
'====ïåðåìåííûå äëÿ îïðîñà êëàâèàsòóðû
Dim Keycode As Byte
'====îñíîâíîé öèêë================
On Int2 Button
Enable Interrupts
Enable Int2
Cursor Off
Do
Locate 1 , 1
Lcd Keycode
Waitms 500
Keycode = 0
Loop
Button:
Do
If Pinc.2 = 0 Then
Keycode = 1
End If
If Pinc.3 = 0 Then
Keycode = 2
End If
If Pinc.4 = 0 Then
Keycode = 3
End If
If Pinc.5 = 0 Then
Keycode = 4
End If
If Pinc.6 = 0 Then
Keycode = 5
End If
Loop Until Keycode <> 0
Waitms 10
Gifr = 64
Return
End
- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: Не срабатывает прерывание на кнопках
Для начала можно прогнать кекс в Avr Studio. Тогда будет понятно железо это либо программа. И вообще больше половины написанного только догадываюсь что значит, хотя и Изучал в универе паскаль, а дома баловался с Бейсиком. Это, кстати что за язык??
Где тут производятся действия, в результате которых Keycode становится равным 0???
Сдается мне, что при нажатии любой кнопки код тупо зацикливается в этом месте, даже если кнопку отпустили.
Лучше уж тогда проверять (Pinc&MASK) <>0 или в вашем случае 7С
Где MASK это маска используемых кнопок.
Код: Выделить всё
Do
If Pinc.2 = 0 Then
Keycode = 1
End If
If Pinc.3 = 0 Then
Keycode = 2
End If
If Pinc.4 = 0 Then
Keycode = 3
End If
If Pinc.5 = 0 Then
Keycode = 4
End If
If Pinc.6 = 0 Then
Keycode = 5
End If
Loop Until Keycode <> 0 'возвращаемся к Do пока Keycode не равен нулюГде тут производятся действия, в результате которых Keycode становится равным 0???
Сдается мне, что при нажатии любой кнопки код тупо зацикливается в этом месте, даже если кнопку отпустили.
Лучше уж тогда проверять (Pinc&MASK) <>0 или в вашем случае 7С
Где MASK это маска используемых кнопок.
- amv2000
- Опытный кот
- Сообщения: 717
- Зарегистрирован: Вт апр 26, 2011 13:58:36
- Откуда: Ростовская область
Re: BASCOM AVR в вопросах и ответах
Ниже
Последний раз редактировалось amv2000 Пт дек 06, 2013 11:51:31, всего редактировалось 1 раз.
- amv2000
- Опытный кот
- Сообщения: 717
- Зарегистрирован: Вт апр 26, 2011 13:58:36
- Откуда: Ростовская область
Re: BASCOM AVR в вопросах и ответах
amv2000 писал(а):KOTик писал(а):как из этой строки узнать, через сколько мск произойдет прерывание?
Прерывание произойдет, когда выполнится подпрограмма Button, здесь скорее всего при нажатии кнопки.
А дребезг кнопки можно устранить с помощью Debounce.
Код: Выделить всё
Debounce Pind.2 , 0 , left_booton , Sub ' проверяем пин на наличие ноля, если условия выполненно - переходим к подпрограммеRe: BASCOM AVR в вопросах и ответах
KOTик писал(а):Имеется задачка:
Включать светодиод, замыкая кнопку и на плюс, и на минус.
Т.е. и то, и др. должно включать LED.
А почему обязательно пытаться решать программно?
Можно аппаратно. Организовываете кнопку на минус с подтяжкой резистором как обычно. А сигнал с плюса подаете на тот же пин через инвертор, которым может служить тот же транзистор в ключевом режиме.
Последний раз редактировалось serg_svd Пт дек 06, 2013 15:54:17, всего редактировалось 1 раз.
"Чтобы правильно задать вопрос, нужно знать бо́льшую часть ответа." Ро́берт Ше́кли
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Я правильных ответов знаю мало, поэтому не стесняюсь и много спрашиваю.
Re: BASCOM AVR в вопросах и ответах
serg_svd писал(а):KOTик писал(а):Имеется задачка:
Включать светодиод, замыкая кнопку и на плюс, и на минус.
Т.е. и то, и др. должно включать LED.
А почему обязательно пытаться решать программно?
Можно аппаратно. Организовываете кнопку на минус с подтяжкой резистором как обычно. А сигнал с плюса подаете на тот же пин через инвертир, которым может служить тот же транзистор в ключевом режиме.
А это, кстати, идея!
И как сам не додумался
Мррррррррр
Спасибо!
Re: BASCOM AVR в вопросах и ответах
amv2000 писал(а):Прерывание произойдет, когда выполнится подпрограмма Button, здесь скорее всего при нажатии кнопки.
А дребезг кнопки можно устранить с помощью Debounce.Код: Выделить всё
Debounce Pind.2 , 0 , left_booton , Sub ' проверяем пин на наличие ноля, если условия выполненно - переходим к подпрограмме
Спасибо! С дебонсами работаю и все отлично!
А какое событие вызовет прерывание Button:?
Переполнение таймера?
Образно ввиду в курс дела.
Имеются 2 кнопки (прижаты к земле): старт (PINB.2), стоп (PINB.1) и один LED (PORTB.0).
Кнопка "старт" включает светодиод на 10сек. и по истечению этого времени он тухнет - это работает.
А вот кнопка "стоп" нужна для экстренного выключения светодиода, т.е. до 10 сек.
"Стоп" вешал и так, и сяк, и на прерывание INT0 (тинька13) - бестолку
Она срабатывает только после 10сек.
Только не бейте
Собственно вопрос: задержку на таймер сажать или как?
И как вообще работать с таймером - просветите, учитель
Буду признателен за образец кода с комментариями - это у вас хорошо получается
- amv2000
- Опытный кот
- Сообщения: 717
- Зарегистрирован: Вт апр 26, 2011 13:58:36
- Откуда: Ростовская область
Re: BASCOM AVR в вопросах и ответах
KOTик писал(а):А какое событие вызовет прерывание Button:?
Переполнение таймера?
Вы немного не понимаете в Вашем коде
Код: Выделить всё
...
Config Timer0 = Timer , Prescale = 64
On Timer0 Button:
не забываем
Enable Interrupts - Включить прерывания
Enable Timer0
...Вот нашел по моему почти Ваш случай. http://decada.org.ru/project/lessons/bascom_avr/10/
Обратите внимание нашел на этой странице http://habrahabr.ru/post/151544/
Код: Выделить всё
Работа с прерываниями:
On Int0 Button - Имя подпрограммы
Config Int0 = Low Level - Прерывание по низкому уровню
Enable Interrupts - Включить прерывания
Enable Int0
Button:
Incr Cntr
Return
С таймерами:
Config Timer0 = Timer , Prescale = 64 - Настраиваем таймер и предделитель
On Timer0 Pulse: - Имя подпрограммы
Enable Interrupts - Включить прерывания
Enable Timer0
Pulse:
Incr Cntr
Return- vitalik_1984
- Поставщик валерьянки для Кота
- Сообщения: 2482
- Зарегистрирован: Пт авг 27, 2010 05:57:06
- Откуда: Тюмень
- Контактная информация:
Re: BASCOM AVR в вопросах и ответах
amv2000 писал(а):KOTик писал(а):как из этой строки узнать, через сколько мск произойдет прерывание?
Прерывание произойдет, когда выполнится подпрограмма Button, здесь скорее всего при нажатии кнопки.
Тут не совсем так. Прерывание в Мк Avr произойдет как правило через четыре такта после последней команды.
На картинке в графике справа видно пусть он и не совсем для этого случая.
А вот ваша подпрограмма Button вызовется уже в том месте где её вызовут, возможно и в прерывании...
- zero648
- Вымогатель припоя
- Сообщения: 650
- Зарегистрирован: Пн июн 18, 2012 12:01:04
- Откуда: Челябинская область, Копейск
Re: BASCOM AVR в вопросах и ответах
А можно примерчик?
В моем случае, АЦП принимает значение до 1023.
Не представляю, как заставить его принимать (-) и (+)...
Примерчиком помочь не смогу, прогаю только на асме.
По поводу АЦП, ставим на кнопку делитель 1:1 на плюс и минус, например 10кОм + 10кОм и периодически читаем АЦП, будем считать, что в этом состоянии кнопка висит т.к. АЦП =~512, если нажать кнопку на минус, то АЦП уйдет на ноль, если на плюс, то АЦП примет максимум, вот такая вот не сложная технология.
Re: BASCOM AVR в вопросах и ответах
zero648 писал(а):Примерчиком помочь не смогу, прогаю только на асме.
По поводу АЦП, ставим на кнопку делитель 1:1 на плюс и минус, например 10кОм + 10кОм и периодически читаем АЦП, будем считать, что в этом состоянии кнопка висит т.к. АЦП =~512, если нажать кнопку на минус, то АЦП уйдет на ноль, если на плюс, то АЦП примет максимум, вот такая вот не сложная технология.
И как Я не додумался
При том с АЦП очень хорошие отношения
Все гениальное - просто!
Спасибо!
Тааак.
Ща пойду с таймерами разбираться...
Re: BASCOM AVR в вопросах и ответах
Главное, не смочь нажать одновременно обе кнопки, на плюс и на минус.
А вообще, при большом желании, можно и больше кнопок повесить на один вход АЦП.
А вообще, при большом желании, можно и больше кнопок повесить на один вход АЦП.
Re: BASCOM AVR в вопросах и ответах
SmarTrunk писал(а):Главное, не смочь нажать одновременно обе кнопки, на плюс и на минус.
А вообще, при большом желании, можно и больше кнопок повесить на один вход АЦП.
Да, уже вешал.
И в зависимости от значения АЦП светики загорались
-
Александр 2677
- Встал на лапы
- Сообщения: 89
- Зарегистрирован: Пн фев 22, 2010 11:16:00
- amv2000
- Опытный кот
- Сообщения: 717
- Зарегистрирован: Вт апр 26, 2011 13:58:36
- Откуда: Ростовская область
Re: BASCOM AVR в вопросах и ответах
Модели HC-SR04 нет, это народ делает рисунки.
Re: BASCOM AVR в вопросах и ответах
Салют, коты
Наконец-таки (хоть и примитивный пример) удалось что-то сделать на таймере. Правда не могу рассчитать частоту мигания светодиода.
У меня тинька13 ($crystal = 4800000), светодиод (PORTB.0) и настроен TIMER0 (8бит) с предделителем 1024.
Получается 1024/4800000*255 = 0,0544мс - это шаг увеличения значения.
А время переполнения таймера каждые 255*0,0544 = 13,8мс. Значит, за 13,8мс таймер натикает число 255 с шагом 0,0544мс (поправьте, если неправильно посчитал)
А теперь вопрос, что с чем перемножить/разделить, чтобы мерцание светика было, например, 1 раз в секунду.
По какой формуле всё это вычислять?
Наконец-таки (хоть и примитивный пример) удалось что-то сделать на таймере. Правда не могу рассчитать частоту мигания светодиода.
У меня тинька13 ($crystal = 4800000), светодиод (PORTB.0) и настроен TIMER0 (8бит) с предделителем 1024.
Получается 1024/4800000*255 = 0,0544мс - это шаг увеличения значения.
А время переполнения таймера каждые 255*0,0544 = 13,8мс. Значит, за 13,8мс таймер натикает число 255 с шагом 0,0544мс (поправьте, если неправильно посчитал)
А теперь вопрос, что с чем перемножить/разделить, чтобы мерцание светика было, например, 1 раз в секунду.
По какой формуле всё это вычислять?
- edm2007
- Поставщик валерьянки для Кота
- Сообщения: 2255
- Зарегистрирован: Вт апр 21, 2009 22:24:10
- Откуда: Иркутск
- Контактная информация:
Re: BASCOM AVR в вопросах и ответах
Привет.
На деле все очень просто. Допустим, 16-ми битный таймер молотит на частоте 4 МГц без предделителя. Счетный регистр увеличивает свое значение с каждым тактом, а значит период таймера (величина, обратная частоте) составит 1 / 4 000 000 = 0,00025 мс. Это один тик таймера. Так как он у нас 16-ти битный, то переполнится при переходе через FFFF (65535). Отсюда:
16-ти битный таймер при тактовой частоте 4 МГц с прескаллером 1 будет переполняться каждые 0,00025 мс * 65536 = 16,384 мс
- // - с прескаллером 8 -16,384 * 8 = 131.072 мс
- // - с прескаллером 64 -16,384 * 64 = 1048.576 мс
- // - с прескаллером 256 - 16,384 * 256 = 4194.304 мс
- // - с прескаллером 1024 - 16,384 * 1024 = 16777.217 мс
Если же нужны четко заданные промежутки времени, то самый простой способ - настроить таймер в режим СТС (сброс по совпадению). В этом режиме таймер будет считать от 0 до заданного значения (записанного в регистр сравнения), после чего обнуляться и начинать счет заново. По переполнению можно будет генерировать прерывание.
Как рассчитать число, которое необходимо записать в регистр сравнения? Да проще некуда. Допустим, нам необходимо чтоб таймер вызывал прерывание каждую секунду. Берем предделитель с заведомо большим временем. Это 64 (1048.576 мс). Если тактовая частота таймера в 64 раза меньше частоты МК, то ее период в 64 раза больше: 0,00025 * 64 = 0,016 мс. Осталось только выяснить, сколько тиков таймера нужно для отсчета 1 секунды: 1000 мс / 0,016 мс = 62500.
Теперь если настроить таймер в режим СТС, соответствующим образом настроить прерывание и записать в регистр сравнения число 62500, МК будет вызывать прерывание по совпадению каждую секунду. При помощи такого нехитрого расчета можно отсчитывать любые временные интервалы. Если диапазона не хватает, то в обработчике можно считать переполнения.
На деле все очень просто. Допустим, 16-ми битный таймер молотит на частоте 4 МГц без предделителя. Счетный регистр увеличивает свое значение с каждым тактом, а значит период таймера (величина, обратная частоте) составит 1 / 4 000 000 = 0,00025 мс. Это один тик таймера. Так как он у нас 16-ти битный, то переполнится при переходе через FFFF (65535). Отсюда:
16-ти битный таймер при тактовой частоте 4 МГц с прескаллером 1 будет переполняться каждые 0,00025 мс * 65536 = 16,384 мс
- // - с прескаллером 8 -16,384 * 8 = 131.072 мс
- // - с прескаллером 64 -16,384 * 64 = 1048.576 мс
- // - с прескаллером 256 - 16,384 * 256 = 4194.304 мс
- // - с прескаллером 1024 - 16,384 * 1024 = 16777.217 мс
Если же нужны четко заданные промежутки времени, то самый простой способ - настроить таймер в режим СТС (сброс по совпадению). В этом режиме таймер будет считать от 0 до заданного значения (записанного в регистр сравнения), после чего обнуляться и начинать счет заново. По переполнению можно будет генерировать прерывание.
Как рассчитать число, которое необходимо записать в регистр сравнения? Да проще некуда. Допустим, нам необходимо чтоб таймер вызывал прерывание каждую секунду. Берем предделитель с заведомо большим временем. Это 64 (1048.576 мс). Если тактовая частота таймера в 64 раза меньше частоты МК, то ее период в 64 раза больше: 0,00025 * 64 = 0,016 мс. Осталось только выяснить, сколько тиков таймера нужно для отсчета 1 секунды: 1000 мс / 0,016 мс = 62500.
Теперь если настроить таймер в режим СТС, соответствующим образом настроить прерывание и записать в регистр сравнения число 62500, МК будет вызывать прерывание по совпадению каждую секунду. При помощи такого нехитрого расчета можно отсчитывать любые временные интервалы. Если диапазона не хватает, то в обработчике можно считать переполнения.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Re: BASCOM AVR в вопросах и ответах
Что-то совсем запутался 
А ж голова опухла
1/4 000 000 = 0,000 000 25
разве нет?
16-битный таймер переполнится через 65535, а у вас 65536 - почему так?
т.е. должно быть 0,00000025* 65535 = 0,01638375мс.
и тут тоже, 0,00000025* 64 = 0,000016мс.
Следовательно, 1000мс / 0,000016мс = 62 млн. 500 тысяч!
Вот, накидал код, где светодиод мерцает с частотой ~1сек.
prescale 256 / 9 600 000*255 (счетный регистр) = 0,0068сек. = 1 тик таймера.
за 1 секунду: 1000*0,0068сек. = 6,8 тиков.
Каждый тик таймера увеличивает переменную Count до 72, после чего загорается светодиод и тухнет.
И так каждую секунду.
Цифру 72 подбирал экспериментально. Точность +/- несколько единиц мс.
Затем проводил вычисления с этими цифрами, чтобы не гадать и сразу вписать необходимую частоту мерцания..
Пока ничего не получается
Голова опухла.
Если можно, объясните на примере моего кода, с таймером 8-бит, камнем 96 000 000 (тинька13) и прескейл 256
А ж голова опухла
edm2007 писал(а):Привет.
На деле все очень просто. Допустим, 16-ми битный таймер молотит на частоте 4 МГц без предделителя. Счетный регистр увеличивает свое значение с каждым тактом, а значит период таймера (величина, обратная частоте) составит 1 / 4 000 000 = 0,00025 мс. Это один тик таймера. Так как он у нас 16-ти битный, то переполнится при переходе через FFFF (65535).
1/4 000 000 = 0,000 000 25
разве нет?
Отсюда:
16-ти битный таймер при тактовой частоте 4 МГц с прескаллером 1 будет переполняться каждые 0,00025 мс * 65536 = 16,384 мс
16-битный таймер переполнится через 65535, а у вас 65536 - почему так?
т.е. должно быть 0,00000025* 65535 = 0,01638375мс.
Если тактовая частота таймера в 64 раза меньше частоты МК, то ее период в 64 раза больше: 0,00025 * 64 = 0,016 мс. Осталось только выяснить, сколько тиков таймера нужно для отсчета 1 секунды: 1000 мс / 0,016 мс = 62500.
и тут тоже, 0,00000025* 64 = 0,000016мс.
Осталось только выяснить, сколько тиков таймера нужно для отсчета 1 секунды: 1000 мс / 0,016 мс = 62500.
Следовательно, 1000мс / 0,000016мс = 62 млн. 500 тысяч!
Вот, накидал код, где светодиод мерцает с частотой ~1сек.
Код: Выделить всё
'----------
$regfile = "attiny13.dat" 'specify the used micro
$crystal = 9600000 'used crystal frequency
$hwstack = 32 'default use 32 for the hardware stack
$swstack = 8 'default use 8 for the SW stack
$framesize = 16 'default use 40 for the frame space
Config Debounce = 75 '
'== НАСТРОЙКА ПОРТОВ =======
Config Portb.0 = Output 'LED1
Config Pinb.1 = Input 'KEY1
Dim Count As Integer
Led1 Alias Portb.0 'LED1 -> PORTB.0
Key1 Alias Pinb.1 'KEY1 -> PINB.1
Led1 = 1 ' светодиод выключаем
Config Timer0 = Timer , Prescale = 256
On Timer0 Pulse:
Enable Interrupts
Enable Timer0
'======== ПРОГРАММА ==========
Do
If Count = 72 Then
Led1 = 0
Waitms 50
If Count < 72 Then 'Waitms 100
Led1 = 1
End If
End If
Loop
Pulse:
Waitms 10
Incr Count
If Count > 72 Then Count = 0 'Led1 = 1
Return
'----------
End 'end programprescale 256 / 9 600 000*255 (счетный регистр) = 0,0068сек. = 1 тик таймера.
за 1 секунду: 1000*0,0068сек. = 6,8 тиков.
Каждый тик таймера увеличивает переменную Count до 72, после чего загорается светодиод и тухнет.
И так каждую секунду.
Цифру 72 подбирал экспериментально. Точность +/- несколько единиц мс.
Затем проводил вычисления с этими цифрами, чтобы не гадать и сразу вписать необходимую частоту мерцания..
Пока ничего не получается
Если можно, объясните на примере моего кода, с таймером 8-бит, камнем 96 000 000 (тинька13) и прескейл 256