BASCOM AVR в вопросах и ответах

Обсуждаем контроллеры компании Atmel.
Ответить
Встал на лапы
Аватара пользователя
Сообщения: 139
Зарегистрирован: Вт май 03, 2011 10:13:12
Откуда: Россия, Татарстан

Сообщение Tankor »

Необходимо прерывание по внешним импульсам. На вход T0 идут (проверено на осциле) 32768Гц.
Отрывок:
..
Config Timer0 = Counter , Edge = Rising , Prescale = 64
On Counter0 Refreshscreen
Enable Interrupts
Enable Counter0
do
..
loop

Refreshscreen:
..
Return

Компилятор не пропускает строку Enable counter0
Сообщение Unknown interrupt source [COUNTER0]
Голову сломал уже. Во всех учебниках указывается, что данная конструкция работает.
Реклама
ROC
Родился
Аватара пользователя
Сообщения: 4
Зарегистрирован: Пн янв 29, 2007 00:46:53
Откуда: СПБ

Сообщение ROC »

Может
Enable Timer0
?
Реклама
Встал на лапы
Аватара пользователя
Сообщения: 139
Зарегистрирован: Вт май 03, 2011 10:13:12
Откуда: Россия, Татарстан

Сообщение Tankor »

ROC писал(а):Может
Enable Timer0
?
Мне нужен именно счётчик T0 а не Timer0, внешние импульсы нужны.
ROC
Родился
Аватара пользователя
Сообщения: 4
Зарегистрирован: Пн янв 29, 2007 00:46:53
Откуда: СПБ

Сообщение ROC »

Тогда найдите, где вы определяете Counter0
Config Timer0 = Counter , Edge = Rising , Prescale = 64
On Counter0 Refreshscreen
Enable Interrupts
Enable Counter0

Или Counter0 - это встроенное по переполнению?
Реклама
Эиком - электронные компоненты и радиодетали
Встал на лапы
Аватара пользователя
Сообщения: 139
Зарегистрирован: Вт май 03, 2011 10:13:12
Откуда: Россия, Татарстан

Сообщение Tankor »

ROC писал(а):Тогда найдите, где вы определяете Counter0
Config Timer0 = Counter , Edge = Rising , Prescale = 64
On Counter0 Refreshscreen
Enable Interrupts
Enable Counter0

Или Counter0 - это встроенное по переполнению?
Переполнение от внешних импульсов.
Реклама
ROC
Родился
Аватара пользователя
Сообщения: 4
Зарегистрирован: Пн янв 29, 2007 00:46:53
Откуда: СПБ

Сообщение ROC »

Такая же ерунда в примере от декады - http://www.decada.org.ru/project/lesson ... unter2.bas
Не компилируется с таким же сообщением.
Реклама
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2255
Зарегистрирован: Вт апр 21, 2009 22:24:10
Откуда: Иркутск

Сообщение edm2007 »

Tankor, Для Вас самым главным учебником должен быть даташит! Ну компилятор же явно говорит, что такое прерывание ему не известно. И если взять и всем на зло открыть даташит, то можно убедиться, что такого прерывания нет. Есть таймер/счетчик, у которого есть прерывания по переполнению, по совпадению, по захвату счетного регистра... И эти прерывания останутся таковыми, независимо от того, откуда таймер/счетчик будет брать тактовые импульсы, от внутреннего генератора или с внешнего вывода.

Вам нужно прерывание по переполнению импульсами с вывода Т0? Так конфигурируйте таймер на тактирование от внешних импульсов и обзывайте прерывание по переполнению как Вам угодно, и все будет работать:

Код: Выделить всё

Config Timer0 = Counter , Edge = Falling       ' подсчет внешних импульсов по спаду (или rising - по фронту)

On Timer0 Name_int                                    ' имя прерывания по переполнению
Enable Interrupts                                         ' глобальное разрешение прерываний
Enable Timer0                                             ' разрешение прерывания по переполнению Т0
//----------------------------------------------------------

Если интересно: тип тактирования таймера настраивается в регистре TCCRx битами CSxx. Именно эти биты указывают, что и как будет считать таймер. Для подсчета внешних импульсов есть два режима: счет по спаду и счет по фронту (в баскоме настраивается при конфигурации таймера в поле Edge). Прерывания таймера остаются прежними, и своих имен не меняют, продолжая работать в том же духе. Если честно, то им абсолютно все равно, кто заставляет тикать таймер...

Изображение

P.S. Обратите внимание, предделителя у этого режима нет.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Контактная информация:
Встал на лапы
Аватара пользователя
Сообщения: 139
Зарегистрирован: Вт май 03, 2011 10:13:12
Откуда: Россия, Татарстан

Сообщение Tankor »

edm2007 писал(а):Tankor, Для Вас самым главным учебником должен быть даташит! Ну компилятор же явно говорит, что такое прерывание ему не известно. И если взять и всем на зло открыть даташит, то можно убедиться, что такого прерывания нет. Есть таймер/счетчик, у которого есть прерывания по переполнению, по совпадению, по захвату счетного регистра... И эти прерывания останутся таковыми, независимо от того, откуда таймер/счетчик будет брать тактовые импульсы, от внутреннего генератора или с внешнего вывода.

Вам нужно прерывание по переполнению импульсами с вывода Т0? Так конфигурируйте таймер на тактирование от внешних импульсов и обзывайте прерывание по переполнению как Вам угодно, и все будет работать:

Код: Выделить всё

Config Timer0 = Counter , Edge = Falling       ' подсчет внешних импульсов по спаду (или rising - по фронту)

On Timer0 Name_int                                    ' имя прерывания по переполнению
Enable Interrupts                                         ' глобальное разрешение прерываний
Enable Timer0                                             ' разрешение прерывания по переполнению Т0
//----------------------------------------------------------

Если интересно: тип тактирования таймера настраивается в регистре TCCRx битами CSxx. Именно эти биты указывают, что и как будет считать таймер. Для подсчета внешних импульсов есть два режима: счет по спаду и счет по фронту (в баскоме настраивается при конфигурации таймера в поле Edge). Прерывания таймера остаются прежними, и своих имен не меняют, продолжая работать в том же духе. Если честно, то им абсолютно все равно, кто заставляет тикать таймер...

Изображение

P.S. Обратите внимание, предделителя у этого режима нет.
Всё заработало с Enable Timer0. Благодарю всех откликнувшихся.
Встал на лапы
Аватара пользователя
Сообщения: 148
Зарегистрирован: Пн июн 07, 2010 16:16:57

Сообщение KOTик »

Мррр все котам и котикам.
Пришел вас помучить :)))
Столкнулся с проблемой.
Делаю замер через ADC1 и сравниваю его с тем, что имею в ЕЕПРОМ

Код: Выделить всё

...
Dim Eep_value As Word                      'здесь хранится значение АЦП в ЕЕП
Dim Adc_value As Word                      'сюда кладем значение АЦП
...
If Adc_value >= Eep_value  Then          'если значение АЦП больше или равно тому, что имеется в ЕЕП 
Led1 = 1                                             'включаем светик
End If   
Попытался добавить гистерезис. Не пашет :kill:

Код: Выделить всё

...
Dim Eep_value As Word                      'здесь хранится значение АЦП в ЕЕП
Dim Adc_value As Word                      'сюда кладем значение АЦП
Dim H As Word                                   'это типа HYSTERESIS
H = 30                                               ' ~ 0.5Вольт
...
If Adc_value = Eep_value + H Then      'все  то же самое, но с гистерезисом Н = 30 
Led1 = 1                                             'включаем светик
End If   
Басик ругается. В чем подвох? :roll:
Т.е. задумка такая: упало напряжение - фонарь выключился. Если напряжение поднялось на 0,5вольт выше значение Eep_value , включаем фонарь.

Всю ночью просидел и ничего не получилось :(
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4744
Зарегистрирован: Вс янв 24, 2010 13:14:02
Откуда: Омск

Сообщение vem566 »

If Adc_value = Eep_value + H Then
Такой оператор недопустим. Сравнение одновременно со сложением баском не понимает.
Встал на лапы
Аватара пользователя
Сообщения: 148
Зарегистрирован: Пн июн 07, 2010 16:16:57

Сообщение KOTик »

vem566 писал(а):If Adc_value = Eep_value + H Then
Такой оператор недопустим. Сравнение одновременно со сложением баском не понимает.
А какой допустим? :lol:
Можно примерчик?
Контактная информация:
Друг Кота
Аватара пользователя
Сообщения: 4744
Зарегистрирован: Вс янв 24, 2010 13:14:02
Откуда: Омск

Сообщение vem566 »

Сначала сложить в какую-нибудь переменную, а потом сравнивать.
A = Eep_value + H
If Adc_value = A Then
Встал на лапы
Аватара пользователя
Сообщения: 148
Зарегистрирован: Пн июн 07, 2010 16:16:57

Сообщение KOTик »

vem566 писал(а):Сначала сложить в какую-нибудь переменную, а потом сравнивать.
A = Eep_value + H
If Adc_value = A Then
Вот и этому научился. Мррр :)
Спасибо за пример. Работает! :beer:


И еще вопросик.
Задействовал режим Idle.
Завел Timer0 и по прерыванию он замеряет вольтаж. Там же происходит сравнение Eep_value и Adc_value. И если Adc_value ниже, то переходит в Idle.
В основном цикле только светодиод - его мигание индицирует уровень ШИМ фонарика.
Проверил в железе и при падении напряжения МК уходит в спячку: ШИМ-выход выключен, светодиод не мигает и потребление мизерное - полдела уже сделано!
А вот когда напряжение выше установленного порога, МК не хочет просыпаться :(

код чуток урезанный:

Код: Выделить всё

Config Timer0 = Timer , Prescale = 1024
On Timer0 Adc_timer
Enable Interrupts
Enable Timer0
Start Timer0
...
Do
...
мигание
и больше
ничего
...
Loop

Adc_timer:
Start Adc				    	        'запуск ADC
Adc_value = Getadc(1)			'кладем значение в Adc_value
Print #1 , "ADC1 = " ; Adc_value		'выводим в терминал

A = Eep_value + H				'значение Eep_value =  Eep_value + 0,5вольт и результат кладем в А
If Adc_value => A Then			'если значение АЦП => значения A
Led1 = 1					        'включение LED1
End If					        'конец условия

If Adc_value < Eep_value Then		'если значени АЦП < значения Eep_value
Led1 = 0					         'выключение LED1
Idle				                  	'идем баиньки
End If				         	'конец условия

Gifr = 64
Return
Ведь по-сути все верно. Таймер переполнится и перейдет по метке Adc_timer, где вновь пойдет замер ADC. Но работать не хочет :kill:
Где мой косяк?
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2168
Зарегистрирован: Ср май 01, 2013 13:53:56
Откуда: с пальмы в Рио-Инженейро

Сообщение fedyasolder »

сконфигурировать бы адц

Код: Выделить всё

CONFIG ADC = single, PRESCALER = AUTO, REFERENCE = opt
электропримат паяю даже лёжа...
Встал на лапы
Аватара пользователя
Сообщения: 148
Зарегистрирован: Пн июн 07, 2010 16:16:57

Сообщение KOTик »

fedyasolder писал(а):сконфигурировать бы адц

Код: Выделить всё

CONFIG ADC = single, PRESCALER = AUTO, REFERENCE = opt
Если это сообщение адресовано мне, то ADC, порты и прочие настройки произведены.
Я же написал, что код урезанный разместил.
Таймер ссылается на замер ADC и, если он ниже эталонного, то переходит в Idle.
А вот просыпаться не хочет. :kill:
Можно как-то разбудить МК по ADC?
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2168
Зарегистрирован: Ср май 01, 2013 13:53:56
Откуда: с пальмы в Рио-Инженейро

Сообщение fedyasolder »

Спойлер

Код: Выделить всё

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32

Config Portd.0 = Output
Led1 Alias Portd.0

Config Adc = Single , Prescaler = 128 , Reference = Avcc
Start Adc
Enable Adc
'Config Portc.1 = Input
'выбор 0-го канала (адц0) = 192 + 0
Admux = 192

Dim Adc_value As Integer
Dim A As Integer
Dim Eep_value As Integer
Dim H As Byte
Dim Hb As Byte
Dim Lb As Byte
H = 2
Eep_value = 512

'по окончании преобразования адц перейти по прерыванию адц на...
On Adc Adc_timer
Enable Interrupts

Power Adcnoise
Do
   nop
   nop
   nop
Loop

Adc_timer:

Adc_value = Getadc(0)

A = Eep_value + H
If Adc_value < A Then
   Led1 = 0
Else
   Led1 = 1
End If


'Бит 6 – ADSC. Запуск преобразования (в режиме однократного
'преобразования)
'0 – преобразование завершено
'1 – начать преобразование
Adcsra.6 = 1

Return
СпойлерИзображение
Таким образом таймер 0 можно не использовать совсем. Прерывание будет происходить по окончании преобразования адц. Если есть ошибки или неточности васикогуру поправят. Запустите протеус и нажимайте кнопочку (симулякр смены уровня сигнала), светик будет загораться и гаснуть в соотв с условием проверки уровня сигнала на входе адц.
Вложения
в картинках.PNG
(30.98 КБ) 1199 скачиваний
протеус.rar
(21.22 КБ) 184 скачивания
электропримат паяю даже лёжа...
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2168
Зарегистрирован: Ср май 01, 2013 13:53:56
Откуда: с пальмы в Рио-Инженейро

Сообщение fedyasolder »

Убрал мусор из кода.
Спойлер

Код: Выделить всё

$regfile = "m8def.dat"
$crystal = 8000000
$hwstack = 40
$swstack = 16
$framesize = 32

Config Portd.0 = Output
Led1 Alias Portd.0

Config Adc = Single , Prescaler = 128 , Reference = Avcc
Start Adc
Enable Adc

Dim Adc_value As Integer
Dim A As Integer
Dim Eep_value As Integer
Dim H As Byte
H = 2
Eep_value = 512

'ïî îêîí÷àíèè ïðåîáðàçîâàíèÿ àäö ïåðåéòè ïî ïðåðûâàíèþ àäö íà...
On Adc Adc_timer
Enable Interrupts

Power Adcnoise
Do
   nop
   nop
   nop
Loop

Adc_timer:

Adc_value = Getadc(0)

A = Eep_value + H
If Adc_value < A Then
   Led1 = 0
Else
   Led1 = 1
End If

'Áèò 6 – ADSC. Çàïóñê ïðåîáðàçîâàíèÿ (â ðåæèìå îäíîêðàòíîãî
'ïðåîáðàçîâàíèÿ)
'0 – ïðåîáðàçîâàíèå çàâåðøåíî
'1 – íà÷àòü ïðåîáðàçîâàíèå
Adcsra.6 = 1

Return
У-У-У. Таким образом мы получаем ещё однин недо-, но таймер. :)))
электропримат паяю даже лёжа...
Встал на лапы
Аватара пользователя
Сообщения: 148
Зарегистрирован: Пн июн 07, 2010 16:16:57

Сообщение KOTик »

Спасибо, но это немного не то.
В коде я не увидел строку Idle, Powerdown и т.д.
Как же МК будет засыпать?
Контактная информация:
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2168
Зарегистрирован: Ср май 01, 2013 13:53:56
Откуда: с пальмы в Рио-Инженейро

Сообщение fedyasolder »

смотрите строку Power Adcnoise.
Это сон который промеж Low Power Idle и Power-down. Можете смело заменить на Low Power Idle. Но с Power-down ацп не разбудит, он выключается. Тут в табличке это описано.
электропримат паяю даже лёжа...
Поставщик валерьянки для Кота
Аватара пользователя
Сообщения: 2255
Зарегистрирован: Вт апр 21, 2009 22:24:10
Откуда: Иркутск

Сообщение edm2007 »

Здравствуйте, KOTик.

Вы упускаете один момент: при переходе в обработчик прерывания (любого), все прерывания глобально запрещаются до выхода из обработчика. Это вполне логично, не трудно догадаться что будет, если начнется вызов прерывания в прерывании. Представьте, было вызвано прерывание таймера, мы начали его обрабатывать, тут сработало прерывание INT0 (кнопку нажали), мы дернулись туда, тут буфер USART переполнился, бежим забирать данные... Да мы же потом дорогу обратно никогда не найдем. А если еще и учесть что баском при вызове прерывания сохраняет все РОН в стек, то понятно что этот стек снесет наглухо очень быстро. Вот от греха и запрещаются все прерывания, пока не обработается текущее. Но остальные пропущены не будут. Если кто-то срабатывал еще, пока мы находились в обработчике, выставится соответствующий флаг. И после выхода из обработчика, мы перейдем к остальным, в порядке очереди векторов.

Что же по факту происходит у Вас: вызывается обработчик прерывания таймера -> все прерывания запрещаются -> МК засыпает. Таймер-то досчитает, и даже флаг прерывания таймера выставится, но прерывание уже не сработает никогда. Ибо глобально запрещено...
Последний раз редактировалось edm2007 Пт май 15, 2015 13:33:01, всего редактировалось 1 раз.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Контактная информация:
Ответить

Вернуться в «AVR»