Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.



Timer1

Сообщений 1 страница 18 из 18

1

Помогите разобраться с таймером, второй раз с ним мучаюсь. Не могу загрузить в него начальное значение т.к. по ощущениям считает всегда с 0 до переполнения.

конструкция типа, вообще не работает

Код:
Const Load_timer1 = 7813
Load Timer1 , Load_timer1

реализовал так:
какое то время работало, хз после какой сборки вдруг перестало

Код:
Config Timer1 = Timer , Prescale = 1024
Const Load_timer1 = 57723                                    ' (1024/16000000)*7813 = 0,5 сек
Enable Timer1
Timer1 = Load_timer1
On Timer1 TimeTic

Do
...
Loop

TimeTic:
print "bla-bla-bla"
Timer1 = Load_timer1
return

уже всю голову изломал

Отредактировано maul52 (2020-01-25 21:45:39)

0

2

Попробуйте добавить Enable Interrupts. Глобально разрешить все прерывания.

0

3

Забыл написать: Atmega328p, кварц 16мгц
Все прерывания разрешены дальше в коде. Я привел только кусочек кода касаемо timer1 более того у меня используется и timer0 и с ним проблем нет. Проблема таймера1 в том что в TimeTic я попадаю всегда примерно раз в 4 секунды в независимости от значения Load_timer1. Т.е. получается что он игнорит строчку:

Код:
Timer1 = Load_timer1

И считает всегда с 0 до 65535, а до 65535 при кварце 16Мгц это примерно 4,19 секунды

0

4

Нужно записать в первый канал сравнения на нужное значение (в данном случае 7813), включить сброс таймера при сравнении и использовать прерывание первого канала сравнения.

+1

5

Если я правильно понял, то вы предлагаете использовать Timer1 в режиме компаратора, а не таймера как у меня в коде. Можете привести пример кода?

Отредактировано maul52 (2020-01-25 23:50:18)

0

6

Я вас правильно понял?

Код:
Config Timer1 = Timer , Prescale = 1024 , Clear_Timer = 1
Enable Timer1
Compare1a = 7813
On Compare1A TimeTic
Enable Compare1a

Отредактировано maul52 (2020-01-26 00:23:50)

0

7

Да.

0

8

Проверил опечатка была в Clear_Timer = 1 (с подчеркиванием надо)
Сейчас все работает. Уточнение небольшое, хочу узнать мнение профессионалов есть смысл делать дополнительный сброс? В TimeTic у меня кода достаточно много, нужно ли дополнительно сбрасывать таймер?
например:

Код:

TimeTic:
Stop Timer1
' здесь куча кода
...
Timer1=0
Start Timer1  

Или как лучше сделать сброс?

Отредактировано maul52 (2020-01-26 00:31:57)

0

9

Таймер аппаратно сбрасывается при достижении значения в Compare1a.

0

10

maul52 написал(а):

Я вас правильно понял?

В самом низу экрана есть раздел "Похожие темы"...
Не листали ? ;)

0

11

Пётр написал(а):

Таймер аппаратно сбрасывается при достижении значения в Compare1a.

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

0

12

Nord написал(а):

В самом низу экрана есть раздел "Похожие темы"...
Не листали ?

Там одна очень схожая тема, где предлагается куча вариантов решения и потом типа: ОК чет заработало. Каким способом не уточняется. Вот и уточняю.
Пока склоняюсь к Stop Timer1 при входе в прерывание Start Timer1 при выходе. У меня там просто есть "медленная" перефирия вот и боюсь из-за нее.

Отредактировано maul52 (2020-01-26 05:15:27)

0

13

maul52 написал(а):

не зайти второй раз в прерывание пока первый раз не вышел

А никто и не зайдёт. В момент выполнения прерывания все остальные отключены.
Вам нужно капитально пересмотреть архитектуры системы. Ну не должно быть в прерывании много кода. Иначе по мере разрастания системы можно напороться на очень острые грабли.
Классический пример построения программы с прерываниями такой:

Main:

If Timer_Int=1 Then
   Timer_Int=0
   Здесь код обработки таймера
   GoTo Main
End If

If GPIO_Int=1 Then
   GPIO_Int=0
   Здесь код обработки GPIO
   GoTo Main
End If

и т.д.

Config PowerMode=IDLE
   GoTo Main
End

Обработка прерываний. Показан пример и его лучше написать на ASM. В данном случае никакие регистры не обрабатываются.

Timer_ISR:
  Timer_Int=1
Return

GPIO_ISR:
  GPIO_Int=1
Return

Всё будет обрабатываться быстро и вы не пропустите ничего.

Отредактировано sva-don (2020-01-26 11:04:46)

+1

14

Вот небольшой пример. У меня на плате стоят часы и по расписанию от них приходит сигнал. Нужно его поймать и обработать. Сигнал поступает на ножку PE3. Флагом наступления прерывания является переменная Alarm_Int.

Код:
'Прерывание от сигнала тревоги
ALRM:
   $asm
      push R24
      in R24,SREG
      push R24
      IN R24,PINE                                           'Прочтем пины порта Е
      ANDI R24,4                                            'Выделим ножку PE3
      CPI R24,4                                             'Проверяем не стоит ли там 1
      BREQ OutIn                                            'Если стоит 1, то выходим
      LDI R24,1                                             'Если 0, то установим флаг прерывания
      STS {Alarm_Int},R24
OutIn:
      pop R24
      out SREG, R24
      pop R24
   $end asm
Return

Отредактировано sva-don (2020-01-26 11:12:23)

+2

15

Если в теле программы сравнивать Alarm_Int как равно/не равно 0, то можно упростить подпрограмму:

sva-don написал(а):

Флагом наступления прерывания является переменная Alarm_Int.
'Прерывание от сигнала тревоги
ALRM:
   $asm
      push R24
      in R24,SREG
      push R24
      IN R24,PINE                                           'Прочтем пины порта Е
      ANDI R24,4                                            'Выделим ножку PE3
      STS {Alarm_Int},R24
      pop R24
      out SREG, R24
      pop R24
   $end asm
Return

0

16

sva-don написал(а):

Вот небольшой пример.

Извиняюсь. Тут ошибочка вышла. НАдо не 4 а 8, т.к. ножка PE3. Будет так:

Код:
'Прерывание от сигнала тревоги
ALRM:
   $asm
      push R24
      in R24,SREG
      push R24
      IN R24,PINE                                           'Прочтем пины порта Е
      ANDI R24,8                                            'Выделим ножку PE3
      CPI R24,8                                             'Проверяем не стоит ли там 1
      BREQ OutIn                                            'Если стоит 1, то выходим
      LDI R24,1                                             'Если 0, то установим флаг прерывания
      STS {Alarm_Int},R24
OutIn:
      pop R24
      out SREG, R24
      pop R24
   $end asm
Return

0

17

pchela5 написал(а):

Если в теле программы сравнивать Alarm_Int как равно/не равно 0, то можно упростить подпрограмму:

Можно и так, но тогда после ANDI R24,8  Alarm_Int = 8 и в основной программе проверяем:
If Alarm_Int=8 Then
   Alarm_Int=0
   Здесь код обработки Alarm
   GoTo Main
End If

0

18

Я, конечно, не знаю полный алгоритм, но если опрос порта идет один раз при возникновении прерывания, то переменная автоматически сбросится в 0 при следующем опросе, если будет 0 на данной ножке.

0