BASCOM AVR в вопросах и ответах
- Сообщения: 132
- Зарегистрирован: Пт окт 19, 2012 05:54:55
- Реклама
Угу, в прерывании по переполнению этого таймера начальное значение счета задавать можно, например. Либо настроить таймер в режиме CTC (Clear To Compare - Сброс При Совпадении). Тогда достаточно будет один раз в регистр сравнения число загрузить, и таймер будет считать от 0 и до этого значения. 
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Спасибо, я так и думал, что тут не все так просто. А может кто-нибудь поделится куском кода для примера
использования Timer1 в режиме CTC, а то в сети все попадаются обрывки информации с разными вариантами написания,
замучился уже искать. Можно ткнуть ссылкой на конкретное место. Буду очень благодарен.
использования Timer1 в режиме CTC, а то в сети все попадаются обрывки информации с разными вариантами написания,
замучился уже искать. Можно ткнуть ссылкой на конкретное место. Буду очень благодарен.
Все просто, на самом деле. В конфигурации таймера указываете
А в регистр сравнения заносите нужное значение. Например (от таймера зависит):
И всех делов, таймер считает от 0 до 12345, а при совпадении вызывается соответствующее прерывание.
Пример:
Только в даташите смотрите, какие таймеры поддерживают этот режим.
Код: Выделить всё
Clear Timer = 1Код: Выделить всё
Compare1a = 12345Пример:
Код: Выделить всё
Config Timer1 = Timer , Prescale = 256 , Clear Timer = 1 ' 1/8000000 = 0,125мкс * 256 * 31250 = 1 cек
Compare1a = &H7A12 ' в регистре совпадения число, для отсчета 1 секунды
On Oc1a 1_sec ' вектор прерывания совпадения Т1
..
1_sec: ' обработка прерывания отсчета 1 секунды
..
Return
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Спасибо. Если я правильно понял, то выходит, что отсчитать нужный интервал времени можно двумя способами:
1. Задать Timer1 начальное значение, и он будет считать от этого значения и до 65535. Но в этом случае нужно
указывать начальное значение при каждом обращении к таймеру.
2. При конфигурировании Timer1 заносим конечное значение в регистр сравнения, и таймер каждый раз считает от 0
до этого значения. Второй способ мне кажется более удобным.
1. Задать Timer1 начальное значение, и он будет считать от этого значения и до 65535. Но в этом случае нужно
указывать начальное значение при каждом обращении к таймеру.
2. При конфигурировании Timer1 заносим конечное значение в регистр сравнения, и таймер каждый раз считает от 0
до этого значения. Второй способ мне кажется более удобным.
- Реклама
Совершенно верно. Удобство зависит от того, как используется таймер. Второй вариант больше подходит под задачу "запустили и забыли". Отсчет времени тот же, например. Первый же вариант тоже жизнеспособен, когда нужно изредка запускать отсчет какой-либо выдержки. Тут можно даже написать функцию, в которую передается значение для начального отсчета, а в прерывании по переполнению выставляется флаг окончания отсчета. Все это удобно и гибко.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Все таки, учитывая что прерывание по сравнению вызывается в следующем, после сравнения, такте, логичнее записатьКод: Выделить всё
Config Timer1 = Timer , Prescale = 256 , Clear Timer = 1 ' 1/8000000 = 0,125мкс * 256 * 31250 = 1 cек Compare1a = &H7A12 ' в регистре совпадения число, для отсчета 1 секунды On Oc1a 1_sec ' вектор прерывания совпадения Т1 .. 1_sec: ' обработка прерывания отсчета 1 секунды .. Return
Код: Выделить всё
Fcpu=8000000
Config Timer1 = Timer , Prescale = 256 , Clear Timer = 1 ' 1/8000000 = 0,125мкс * 256 * 31250 = 1 cек
Compare1a = Fcpu/256-1 ; в регистре совпадения число, для отсчета 1 секунды
;Compare1a = &H7A12 ' в регистре совпадения число, для отсчета 1 секунды
On Oc1a 1_sec ' вектор прерывания совпадения Т1
..
1_sec: ' обработка прерывания отсчета 1 секунды
..
Return
akl, так и есть, один такт отнимать нужно.
Код старый, первые шаги еще. Для примера приведен был. 
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Приветствую неспящих!
Наконец у меня дошли руки, чтобы живьём проверить, как обращаться с Timer1. Взяв за основу образец, который мне
подкинул многоуважаемый edm2007 (в свое время учился по его статьям), написал небольшую учебную програмку,
которая, по идее, должна отсчитывать секунды и при этом моргать светодиодом каждую секунду. Собрал все это на
макетке, о оно не хочет работать. На индикаторе - нули, на кнопки не реагирует. Бейсик не ругается. Не могу
понять, чего ему не хватает. Может, кто подскажет, что я не так делаю. Хочется подружиться с Timer1.
Наконец у меня дошли руки, чтобы живьём проверить, как обращаться с Timer1. Взяв за основу образец, который мне
подкинул многоуважаемый edm2007 (в свое время учился по его статьям), написал небольшую учебную програмку,
которая, по идее, должна отсчитывать секунды и при этом моргать светодиодом каждую секунду. Собрал все это на
макетке, о оно не хочет работать. На индикаторе - нули, на кнопки не реагирует. Бейсик не ругается. Не могу
понять, чего ему не хватает. Может, кто подскажет, что я не так делаю. Хочется подружиться с Timer1.
Код: Выделить всё
$regfile = "2313def.dat"
$crystal = 4000000
$hwstack = 32
$swstack = 8
$framesize = 16
Dim Seco As Byte
Dim Number(2) As Byte
Dim Count As Byte
Dim A As Byte
Dim F As Bit
Config Portb = Output
Config Portd.3 = Output '1 разряд
Config Portd.4 = Output '2 разряд
Config Portd.5 = Output 'светодиод
Config Pind.1 = Input
Config Debounce = 50
Config Timer0 = Timer , Prescale = 256
On Ovf0 Indic
Config Timer1 = Timer , Prescale = 64 , Clear Timer = 1
'Compare1a = 62500
Ocr1a = 62500
On Oc1a Timecount ' рассчет времени
Config Int0 = Falling
On Int0 Breaktime
Dig1 Alias Portd.3
Dig2 Alias Portd.4
Diod Alias Portd.5
Pusk Alias Pind.1 'кнопка пуск
Enable Interrupts
Enable Int0
Enable Timer0
Enable Timer1
Start Timer0
Seco = 0 : F = 0
Do
If Pusk = 0 Then 'нажата кнопка Пуск
Start Timer1
End If
If F = 1 Then ' секунда отсчитана
Set Diod 'моргание светодиодом
Waitms 200
Reset Diod
F = 0 'сброс флага
End If
Loop
Breaktime: 'нажата кнопка Стоп
Stop Timer1
Timer1 = 0 : Seco = 0 ' остановка таймера, обнуление
Return
Indic: 'индикация
A = Seco
Number(1) = A / 10
Number(2) = A Mod 10
Reset Dig1 : Reset Dig2
Incr Count : If Count > 2 Then Count = 1
Portb = Lookup(number(count) , Digits)
Select Case Count
Case 1 : Set Dig1
Case 2 : Set Dig2
End Select
Return
Timecount: 'рассчет времени
Incr Seco : If Seco > 59 Then Seco = 0
F = 1 'установка флага
Return
End
Digits:
Data &B00111111 , &B00000110 , &B01011011 , &B01001111 , &B01100110
Data &B01101101 , &B01111101 , &B00000111 , &B01111111 , &B01101111
Здравствуйте.
Enable Timer1 - это разрешение прерывания по переполнению. У Вас же прерывание по совпадению. А следовательно, Enable Oc1a.
Enable Timer1 - это разрешение прерывания по переполнению. У Вас же прерывание по совпадению. А следовательно, Enable Oc1a.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Привет! Исправил код по вашему совету. Все работает супер. Спасибо за помощь. Заодно узнал, что Timer1 начинает работать после команды Enable Timer1, поэтому приходится его сначала тушить, а в нужном месте запускать командой Start Timer1.
Вообще таймер начинает тикать как только будет сконфигурированы биты прескаллера. Вот как только задали Prescale, таймер пошагал считать. Команда Stop Timer останавливает таймер именно обнуляя прескалллер, а запускает восстанавливая его значение.
Команда же Enable / Disable Timer разрешает / запрещает именно прерывание этого таймера в регистре TIMSK. Что все это значит?
После того как таймер был сконфигурирован, он начинает считать. Если прерывание было запрещено, то он просто крутит счетный регистр по кругу, без всяких внешних реакций. С одной-то стороны и ладно. Если речь идет о таймере индикации, например. А с другой это чревато тем, что мы не знаем что там в счетном регистре в момент разрешения прерывания. И если важно именно прошедшее время, то нужно однозначно таймер перезапускать, обнуляя счетный регистр. Такие дела.
Команда же Enable / Disable Timer разрешает / запрещает именно прерывание этого таймера в регистре TIMSK. Что все это значит?
После того как таймер был сконфигурирован, он начинает считать. Если прерывание было запрещено, то он просто крутит счетный регистр по кругу, без всяких внешних реакций. С одной-то стороны и ладно. Если речь идет о таймере индикации, например. А с другой это чревато тем, что мы не знаем что там в счетном регистре в момент разрешения прерывания. И если важно именно прошедшее время, то нужно однозначно таймер перезапускать, обнуляя счетный регистр. Такие дела.
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Если BASCOM при старте чистит регистр TIFR, то ладно. Но, я бы почистил флаги, записью 1, устраняя, таким образом, всю предисторию.
Да, еще к этой теме, раз речь зашла. Даже не смотря на запрет прерывания, его флаг все равно выставится в соответствующем регистре при соблюдении условий. И как только оно будет разрешено, программа уйдет в его обработчик.
Этот флаг сбрасывается при переходе по соответствующему вектору прерывания, либо как заметил akl, самостоятельной записью 1 в соответствующий бит регистра флагов (например, у таймеров TIFR - Timer/Counter Interrupt Flag Register).
Этот флаг сбрасывается при переходе по соответствующему вектору прерывания, либо как заметил akl, самостоятельной записью 1 в соответствующий бит регистра флагов (например, у таймеров TIFR - Timer/Counter Interrupt Flag Register).
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
- Сообщения: 132
- Зарегистрирован: Пт окт 19, 2012 05:54:55
Спасибо edm2007. Всё получилось.
Enable Oc1a.
On Oc1a
Откуда? Вхелпе их нет. Поясните где их раскопать, чтобы дале не домогаться?
Enable Oc1a.
On Oc1a
Откуда? Вхелпе их нет. Поясните где их раскопать, чтобы дале не домогаться?
Можно открыть файл .DAT соответствующего контроллера, в папке с установленной программой. Обычным блокнотом. Там много всего интересного, на самом деле. Например, прерывания Attiny2313:
Далее в именах и видно, что Timer0 это Ovf0 (переполнение), например:
А вместо Enable Oc1a можно написать Enable Compare1a, это уже будет в стиле баскома:
Код: Выделить всё
[INTS]
INT0=$001 ;External Interrupt0 Vector Address
INT1=$002 ;External Interrupt1 Vector Address
ICP1=$003 ;Input Capture1 Interrupt Vector Address
OC1A=$004 ;Output Compare1 Interrupt Vector Address
OVF1=$005 ;Overflow1 Interrupt Vector Address
OVF0=$006 ;Overflow0 Interrupt Vector Address
URXC=$007 ;UART Receive Complete Interrupt Vector Address
UDRE=$008 ;UART Data Register Empty Interrupt Vector Address
UTXC=$009 ;UART Transmit Complete Interrupt Vector Address
ACI=$00a ;Analog Comparator Interrupt Vector Address
PCINT=$00B
OC1B=$00C
OC0A=$00D
OC0B=$00E ; timer 0 compare match B
UCI_START=$00F ; USI start
UCI_OVFLW=$010 ; USI overflow
EERDY=$011 ; eeprom ready
WDT=$012 ; watch dog timer overflow
Код: Выделить всё
INTname6=OVF0@TIMER0,$006,TIMSK.TOIE0,TIFR.TOV0
Код: Выделить всё
INTname4=OC1A@COMPARE1A,$004,TIMSK.OCIE1A,TIFR.OCF1A
"Слишком много людей ломаются, даже не подозревая о том, насколько близки к успеху они были в тот момент, когда упали духом". Томас Алва Эдисон
Здравия.
Тут уже мелькало, но предложенные варианты не прокатили.
Проблема: Unknown interrupt [PCINT3]
Код:
Даташит на тиньку13 на всякий случай прилагаю.
Что делать? Гугел не помогает
Тут уже мелькало, но предложенные варианты не прокатили.
Проблема: Unknown interrupt [PCINT3]
Код:
Код: Выделить всё
$regfile = "attiny13.dat"
$crystal = 4800000
$hwstack = 8
$swstack = 16
$framesize = 16
Config POTRB.3 = Input
On PCINT3 Button:
Gimsk = &B00100000
'5bit - pcint enable. Stranica 46, punkt 9.3.2
Pcmsk = &B00001000
'3bit - pcint3 enable. Stranica 47, punkt 9.3.4
Do
Loop
Button:
Wait 1
Return
Что делать? Гугел не помогает
Демократии нет и не будет!
Государство - это я!
Государство - это я!
Unknown interrupt [INT3]
Он же именно PC, потому что INT у тиньки13 только 0
Он же именно PC, потому что INT у тиньки13 только 0
Демократии нет и не будет!
Государство - это я!
Государство - это я!


