реклама на сайте
подробности

 
 
 
Reply to this topicStart new topic
> Не получается записать в регистр TCNT0 таймера, Atmega8515
esr
сообщение May 24 2015, 07:59
Сообщение #1


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 13-03-09
Из: Москва
Пользователь №: 46 073



Приветствую! Хочу сформировать интервал времени по таймеру
В даташите Atmega8515 написано, что можно напрямую работать с регистром TCNT0 таймера

Делаю побитную инверсию этого регистра

com TCNT0

Получаю ошибку компиляции

test_1.asm(158): error: Invalid register

т.е. как я понимаю, мой проект в AVR не понимает имя этого регистра

При этом на определение PORTB компилятор не ругается
out PORTB,temp_inv
и на включение/ выключение таймера тоже не ругается
clr temp_timer
out TCCR0,temp_timer

Описание в начале программы есть:

.include "8515def.inc"


Что не так ? 05.gif

Сообщение отредактировал esr - May 24 2015, 08:00
Go to the top of the page
 
+Quote Post
mcheb
сообщение May 24 2015, 08:11
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 326
Регистрация: 30-05-06
Пользователь №: 17 602



Цитата(esr @ May 24 2015, 11:59) *
Приветствую! Хочу сформировать интервал времени по таймеру
В даташите Atmega8515 написано, что можно напрямую работать с регистром TCNT0 таймера

Делаю побитную инверсию этого регистра

com TCNT0




Что не так ? 05.gif

А с какими регистрами может работать команда com ? Может быть, в этом причина?
Go to the top of the page
 
+Quote Post
Xenia
сообщение May 24 2015, 08:41
Сообщение #3


Гуру
******

Группа: Модератор FTP
Сообщений: 4 479
Регистрация: 20-02-08
Из: Москва
Пользователь №: 35 237



Цитата(esr @ May 24 2015, 10:59) *
В даташите Atmega8515 написано, что можно напрямую работать с регистром TCNT0 таймера
Делаю побитную инверсию этого регистра
com TCNT0


А зачем вы это делаете? Если вы работаете с таймером 0 по прерыванию (переполнение), то в TCNT0 надо константу записывать, а не инверсию ему делать.
Go to the top of the page
 
+Quote Post
rx3apf
сообщение May 24 2015, 08:47
Сообщение #4


Гуру
******

Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047



Цитата(esr @ May 24 2015, 10:59) *
Что не так ?

Безотносительно сомнительности самого действия, встречный вопрос - а с чего Вы решили, что команда "com" может работать с регистрами _ввода/вывода_ ?
Go to the top of the page
 
+Quote Post
esr
сообщение May 24 2015, 16:38
Сообщение #5


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 13-03-09
Из: Москва
Пользователь №: 46 073



Цитата(mcheb @ May 24 2015, 12:11) *
А с какими регистрами может работать команда com ? Может быть, в этом причина?

Спасибо откликнувшимся, да действительно в этом причина была. Вот так получилось, через промежуточный регистр:

; Инвертируем регистр таймера TCNT0 через считывание - инверсию -обратную запись с помощью промежуточного регистра

clr temp_inv
in temp_inv,TCNT0 ; Переписываем из регистра (счётчика) таймера в промежуточный регист
com temp_inv ; Инвертируем побитно в промежуточном регистре
out TCNT0,temp_inv ; Записываем обратно в таймер инвертированное значения

Ну и потом запускаю заново таймер и дальше идёт программа.

Оказывается этот регистр (счётчик) TCNT0 не регистр вовсе, а порт получается ? Потому что с ним команда in прошла, которая для портов ввода-вывода действует ?
А это в документации и не отражено нигде вроде бы ....

Цитата(Xenia @ May 24 2015, 12:41) *
А зачем вы это делаете? Если вы работаете с таймером 0 по прерыванию (переполнение), то в TCNT0 надо константу записывать, а не инверсию ему делать.

Так задача поставлена. Надо сначала интервал в таймере накопить, потом его считать оттуда, а потом в течение этого интервала нечто выполнять. Поэтому эту константу для записи нужно из этого-же таймера и доставать.

Сообщение отредактировал esr - May 24 2015, 16:39
Go to the top of the page
 
+Quote Post
rx3apf
сообщение May 24 2015, 22:30
Сообщение #6


Гуру
******

Группа: Участник
Сообщений: 3 834
Регистрация: 14-06-06
Из: Moscow, Russia
Пользователь №: 18 047



Цитата(esr @ May 24 2015, 19:38) *
Оказывается этот регистр (счётчик) TCNT0 не регистр вовсе, а порт получается ? Потому что с ним команда in прошла, которая для портов ввода-вывода действует ?
А это в документации и не отражено нигде вроде бы ....

Это как бы самоочевидно из архитектуры AVR и вполне внятно описано в даташитах - регистры периферийных устройств, конфигурации, собственно портовые ноги это пространство ввода/вывода. Арифметические и логические команды работают только с регистрами общего назначения r0...r31 (с некоторыми ограничениями).
Go to the top of the page
 
+Quote Post
demiurg1978
сообщение May 25 2015, 02:33
Сообщение #7


Местный
***

Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709



Чуть позже вы столкнетесь с тем, что временных интервалов требуется несколько, а у ATMEGA8515 всего два аппаратных таймера. Если вам нужны времянки от мс и выше, и особая точность не нужна, то вам нужны "программные таймеры".
Go to the top of the page
 
+Quote Post
esr
сообщение May 25 2015, 07:23
Сообщение #8


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 13-03-09
Из: Москва
Пользователь №: 46 073



Цитата(rx3apf @ May 25 2015, 02:30) *
Это как бы самоочевидно из архитектуры AVR и вполне внятно описано в даташитах - регистры периферийных устройств, конфигурации, собственно портовые ноги это пространство ввода/вывода. Арифметические и логические команды работают только с регистрами общего назначения r0...r31 (с некоторыми ограничениями).

Да, конечно, теперь уже немного становится очевидно. После того как довольно много времени у меня ушло на разбор этой ошибки.

Цитата(demiurg1978 @ May 25 2015, 06:33) *
Чуть позже вы столкнетесь с тем, что временных интервалов требуется несколько, а у ATMEGA8515 всего два аппаратных таймера. Если вам нужны времянки от мс и выше, и особая точность не нужна, то вам нужны "программные таймеры".

А это как? По прерыванию от кнопки начать бесконечный программный цикл и выходить из него по следующему прерыванию от кнопки? Пример кода можете показать ?
Go to the top of the page
 
+Quote Post
demiurg1978
сообщение May 25 2015, 07:56
Сообщение #9


Местный
***

Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709



Кнопка - человеко-интерфейс. А значит очень медленный. Кнопки можно и нужно опрашивать в основном цикле. Для создания временных интервалов, задержек - программные таймеры. Примерное описание, что это такое. Есть аппаратный таймер, который отщелкивает каждое заранее определенное время. Скажем, 1 мс. В прерывании таймера устанавливаем флажок. В обычном цикле проверяем флажок. Если он сброшен, выходим. Если установлен, дальше уже зависит от реализации. У меня сделано так: очередь таймеров. Структура: статус таймера, счетчик. Когда флаг установлен, перебираем очередь таймеров. Если таймер активен, декремент счетчика. Если не ноль, следующий таймер. Если ноль, в статусе устанавливаем флаг, следующий таймер, пока не закончится очередь таймеров.
Go to the top of the page
 
+Quote Post
esr
сообщение May 25 2015, 16:13
Сообщение #10


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 13-03-09
Из: Москва
Пользователь №: 46 073



Цитата(demiurg1978 @ May 25 2015, 11:56) *
У меня сделано так: очередь таймеров. Структура: статус таймера, счетчик. Когда флаг установлен, перебираем очередь таймеров.

А что значит очередь таймеров? Их там всего два ?
Go to the top of the page
 
+Quote Post
demiurg1978
сообщение May 25 2015, 19:06
Сообщение #11


Местный
***

Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709



Аппаратных два. А программных можно наделать хоть несколько десятков.
CODE

//========================================================================
.equ ST_TCNT = TCNT0
.equ ST_TIMSK = TIMSK
.equ ST_OCIE = OCIE0
.equ ST_OCR = OCR0
.equ ST_TCCR = TCCR0
.equ CS0 = CS00
.equ CS1 = CS01
.equ CS2 = CS02
//========================================================================

//========================================================================
.equ SYS_TICK = 1 // Период системного таймера 1 мс
//========================================================================

//========================================================================
.equ ST_SIZE = 2
//========================================================================

//========================================================================
//--------------------- Флаги системных таймеров -------------------------
Def_Flag SYS_TICK_FLG
//------------------------------------------------------------------------

//------------------------------------------------------------------------
.equ ST_UNLOCK_FLG = 0 // Флаг активности таймера.
.equ ST_TIME_OUT_FLG = 1 // Время вышло.
//========================================================================

.dseg

//========================================================================
//-------------------- Очередь системных таймеров ------------------------
.set NUM_ST = -1
.set ST_QUANTITY = 0

.macro Def_Sys_Timer
.set NUM_ST = (NUM_ST+1)
.set ST_QUANTITY = (ST_QUANTITY+1)
.set @0 = NUM_ST
.message "System Timer Defined!"
.endmacro

Def_Sys_Timer ST_DRV_LCD
Def_Sys_Timer ST_KBD
Def_Sys_Timer ST_PROC_GAME_1
Def_Sys_Timer ST_PROC_GAME_2

ST_CNT_QUEUE:
.byte ST_QUANTITY*(ST_SIZE+1)
//========================================================================

.cseg

//========================================================================
.macro Init_System_Timer
clr r16
out ST_TCNT, r16
in r16, ST_TIMSK
sbr r16, 1<<ST_OCIE
out ST_TIMSK, r16
outi ST_OCR, (XTAL/64/1000)
in r16, ST_TCCR
sbr r16, 1<<CS0 | 1<<CS1
out ST_TCCR, r16
.endmacro

.macro ReRun_Sys_Timer
in r16,ST_OCR
subi r16,-(XTAL/64/1000)
out ST_OCR,r16
.endmacro
//========================================================================

//========================================================================
Sys_Timer_Comp:
push r16
in r16,SREG
push r16

ReRun_Sys_Timer

sbr FLAGS,1<<SYS_TICK_FLG

pop r16
out SREG,r16
pop r16
reti
//========================================================================

//========================================================================
//-------------------------- Установка таймера ---------------------------
.macro par_timer
.db @0, @1, tab_l(@2)
.endmacro

.macro Set_Timer
ldi r17,HIGH(@0*2)
ldi r16,LOW(@0*2)
rcall _Set_Timer
.endmacro

_Set_Timer:
push XL
push XH
push ZL
push ZH
movw ZH:ZL, r17:r16
lpm XL,Z+
mov r16,XL
lsl XL
add XL,r16
clr XH
subi XL,LOW(-ST_CNT_QUEUE)
sbci XH,HIGH(-ST_CNT_QUEUE)
ldi r17, 3
_Set_Timer_Cycle:
lpm r16, Z+
st X+, r16
dec r17
brne _Set_Timer_Cycle
pop ZH
pop ZL
pop XH
pop XL
ret
//------------------------------------------------------------------------

//-------------------------- Проверка таймера ----------------------------
.macro Proc_Timer
ldi r17,HIGH(@0*2)
ldi r16,LOW(@0*2)
rcall _Proc_Timer
.endmacro

_Proc_Timer:
push XL
push XH
push ZL
push ZH
movw ZH:ZL, r17:r16
lpm XL, Z+
mov r16, XL
lsl XL
add XL, r16
clr XH
subi XL,LOW(-ST_CNT_QUEUE)
sbci XH,HIGH(-ST_CNT_QUEUE)
clt
ld r16, X
ldi r17, 1<<ST_TIME_OUT_FLG
and r17, r16
breq Proc_Timer_End
st X, r16
set
Proc_Timer_End:
pop ZH
pop ZL
pop XH
pop XL
ret
//========================================================================

//========================================================================
Service_Timers: // Служба таймеров.
sbrs FLAGS,SYS_TICK_FLG // Флаг очередного отсчета системного таймера установлен?
ret // Нет, выход.
cbr FLAGS,1<<SYS_TICK_FLG // Установлен, сброс флага.
ldy ST_CNT_QUEUE // Указатель на начало очереди системных таймеров.
clr CNT
Service_Timers_ST_Cycle:
ld r16,Y // Считывание байта-статуса системного таймера.
sbrs r16,ST_UNLOCK_FLG // Таймер заблокирован?
rjmp Process_Next_System_Timer // Да, переход к обработке следующего таймера.
ldd r24,Y+1 // Считывание младшего байта таймера.
ldd r25,Y+2 // Считывание старшего байта таймера.
sbiw r24,1 // Уменьшаем значение таймера на единицу.
std Y+1,r24 // Сохранение значения таймера.
std Y+2,r25 // Сохранение значения таймера.
brne Process_Next_System_Timer // Если время не вышло, то переход к обработке следующего таймера.
sbr r16,1<<ST_TIME_OUT_FLG // Установка флага завершения работы таймера.
Save_ST_Flags:
st Y,r16 // Запись статуса таймера.
Process_Next_System_Timer:
adiw YL,3 // Смещение указателя на следущий таймер.
inc CNT
cpi CNT,ST_QUANTITY // Значение счетчика таймеров равно количеству таймеров?
brlo Service_Timers_ST_Cycle // Меньше, обрабатываем следующие таймеры.
Service_Timers_End:
ret
//========================================================================


Пример применения:
CODE

//========================================================================
Main:
wdr
rcall Service_Timers
rcall Drv_Lcd
rcall KBD_DRV
rcall Proc_Game
rjmp Main
//========================================================================

//========================================================================
Keys_None:
sbrs FSM_FLAGS, KEYS_PRESSED_FLG // Если что-то нажато, то пропуск команды.
ret
Read_Keys_Current
Save_Keys_Prev // Сохранение текущего состояния клавиатуры.
Set_Timer Par_Tim_Debounce // Установка задержки устранения дребезга.
Set_State _KEYS_DOWN
ret

Keys_Down:
Proc_Timer Par_Tim_Debounce
brtc Keys_Down_End
sbrs FSM_FLAGS, KEYS_PRESSED_FLG
rjmp Keys_Set_None
Comp_Last_Curr_Keys
breq Keys_Down_A
rjmp Keys_Set_None
Keys_Down_A:
setb FSM_FLAGS, DEFINE_KEYS_FLG
#if (HOLD==NO)
rjmp Keys_Set_Wait_Up
#elif (HOLD==YES)
Set_Timer Par_Tim_Hold
Set_State _KEYS_HOLD
#endif
Keys_Down_End:
ret

Par_Tim_Debounce:
par_timer ST_KBD, 1<<ST_UNLOCK_FLG, DEBOUNCE_DELAY
Go to the top of the page
 
+Quote Post
Onkel
сообщение May 26 2015, 05:41
Сообщение #12


Знающий
****

Группа: Свой
Сообщений: 708
Регистрация: 8-05-11
Из: Чг
Пользователь №: 64 861



Цитата(esr @ May 25 2015, 19:13) *
А что значит очередь таймеров? Их там всего два ?

кстати очень полезно будет для начинающих про софтовые таймеры и прочие основные идеи работы с мелкими мк:

"Осевые технологии. Пишем свою микрооперационную систему " в хакере (журнал такой, официально издающийся) 123, 2009
или (возможно, автор тот же, не знаю точно) тут http://easyelectronics.ru/avr-uchebnyj-kur...a-vvedenie.html

Go to the top of the page
 
+Quote Post
esr
сообщение May 26 2015, 17:41
Сообщение #13


Частый гость
**

Группа: Участник
Сообщений: 91
Регистрация: 13-03-09
Из: Москва
Пользователь №: 46 073



Цитата(demiurg1978 @ May 25 2015, 23:06) *
Аппаратных два. А программных можно наделать хоть несколько десятков.
...

Спасибо! То что надо для моего проектика.

Цитата(Onkel @ May 26 2015, 09:41) *
"Осевые технологии. Пишем свою микрооперационную систему " ...

Это для меня ещё рановато смотреть.
Go to the top of the page
 
+Quote Post
Onkel
сообщение May 27 2015, 04:33
Сообщение #14


Знающий
****

Группа: Свой
Сообщений: 708
Регистрация: 8-05-11
Из: Чг
Пользователь №: 64 861



Цитата(esr @ May 26 2015, 20:41) *
Спасибо! То что надо для моего проектика.


Это для меня ещё рановато смотреть.

не пугайтесь названия, материал хавабелен даже для чайников. Мне в свое время очень помогло - я все свои проекты попеределывал и не то чтобы много проблем исчезло, а они не появлялись.
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 20th June 2025 - 15:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.01481 секунд с 7
ELECTRONIX ©2004-2016