Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Таймеры atmega32a
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
ishpanec
Здравствуйте
Проблема возникла такая, есть у меня atmega32a китайский. постигаю таймеры. использую таймер0 (8 бит).
Логика моих мыслей такова:

если там частота 16МГц а таймер считает до 256 то каждое переполнение таймера будет происходить (1 / 16 000 000) * 256 = 16 микросекунд (0,000016).
Соответственно, что бы получить 1 секунду надо таких отрезков 62 500 (0,000016 * 62 500 = 1 сек.)
Что бы особо не мучиться с 16 битными числами я разбил на две 8 битные, т.е. 250 и 250.
Значит в прерывании по переполнению мы считаем первый счетчик, када он доходит до 250 мы увеличиваем второй и обнуляем первый.
Сразу что скажу что cksel биты не менял, они все отключены, значит частота должна быть нормальной. В коде не устанавливаю предделитель для таймера.
Внешнего кварца, как и осциллографа, не имею. замерить частоту не выходит. пробовал всю партию контроллеров (10 штук) результат один и тот же, либо у них у всех не 16 МГц, либо логика моих действий не верна.
zombi
Цитата(ishpanec @ Dec 19 2014, 13:57) *
результат один и тот же

Не плохо было бы узнать полученный результат, способ наблюдения оного.
И перепроверить cksel сравнив с DS.
Dust112
ishpanec, Вы раздел 8-bit Timer/Counter0 with PWM документации читали? В частности про делители ( prescaler ) частоты.
stells
Цитата(ishpanec @ Dec 19 2014, 12:57) *
если там частота 16МГц

а там точно 16МГЦ? не 8?

пс: таблицу 9 смотрите
demiurg1978
У меня такой способ получить 1 мс при 8 и 16 мгц:
CODE
/========================================================================
#define ST_TCNT TCNT0
#define ST_TIMSK TIMSK
#define ST_OCIE OCIE0
#define ST_OCR OCR0
#define ST_TCCR TCCR0
#define CS0 CS00
#define CS1 CS01
#define CS2 CS02
//========================================================================

//========================================================================
#define SYS_TICK_FLG 0
//------------------------------------------------------------------------

//========================================================================
#pragma vector = TIMER0_COMP_vect
__interrupt void Timer0Comp(void)
{
ST_OCR += 250;
sys_tick |= 1<<SYS_TICK_FLG;
}
//========================================================================

//========================================================================
void init_sys_timer (void)
{
sys_tick = 0;
ST_TCNT = 0;
ST_TIMSK |= 1<<ST_OCIE;
ST_OCR = 250;
ST_TCCR |= (1<<CS0) | (1<<CS1);
}
//------------------------------------------------------------------------


При 8 мгц 125, при 16 мгц 250.

Делаем счетчики и получаем любую времянку с дискретностью в 1 мс. 1000 мс = 1 с.
akl
С точностью до такта можно временной интервал формировать так. Писано для tiny13, но и для mega32 будет примерно также.
CODE
.INCLUDE "tn13def.inc"


.equ Fo=7890123
;.equ Fo=8000000


.org $0000
.CSEG
RJMP START
.org $0003
TIMER0_OVER:
SBIW YL,1
RET
.org $0006
TIMER0_COMPA:
RET
;*******************************
START:
SBI DDRB,0

LDI YH,BYTE3(Fo-1)
LDI YL,BYTE2(Fo-1)
LDI R22,BYTE1(Fo-1)
OUT OCR0A,R22

LDI R22,1<<SE
OUT MCUCR,R22 ; SLEEP IDLE

CLR R19
OUT TCCR0A,R19

LDI R21,1<<OCIE0A

LDI R20,1<<TOIE0
OUT TIMSK0,R20 ; разрешить прерывание переполнения
OUT TIFR0,R20

LDI R20,1
OUT TCCR0B,R20 ; старт Т0

SEI
WAIT:
SLEEP
BRNE PC-2

LDI R19,1<<WGM01
OUT TCCR0A,R19 ; режим сравнения с самоочисткой CTC

OUT TIMSK0,R21 ; разрешить прерывание сравнения
OUT TIFR0,R21
SEI
WAIT_COMP:
SLEEP
SBI PINB,0 ; инвертировать выход
RJMP START

.EXIT
ishpanec
отвечу всем по порядку)

Цитата(zombi @ Dec 19 2014, 15:11) *
Не плохо было бы узнать полученный результат



значит при счете до 62 500 мигает он раз в 15 секунд %) наблюдал просто, ни каких особых измерений, это если бы там миллисекунды погрешности было, другое дело) вот биты из программки

Цитата(Dust112 @ Dec 19 2014, 15:16) *
Вы раздел 8-bit Timer/Counter0 with PWM документации читали?


я исключительно по книжкам. не думал что там особая разница есть.

Цитата(stells @ Dec 19 2014, 15:26) *
не 8?


пробовал клепать расчеты под 8, все равно заметные глазу отличия есть) мигание ~ раз в 7 секунд
что за таблица 9?

Цитата(demiurg1978 @ Dec 19 2014, 16:10) *
У меня такой способ получить 1 мс при 8 и 16 мгц:


с Си не дружу) после того как gcc танцы с бубном устраивать заставлял)))))

Цитата(akl @ Dec 20 2014, 10:56) *
С точностью до такта можно временной интервал формировать так. Писано для tiny13, но и для mega32 будет примерно также.


вашу магию тоже не совсем понял...

вот моя магия

CODE

device atmega32a
.include "D:\asm\include\m32def.inc"
.def temp = r16 ; темповая переменная
.def countTimer = r17 ; счетчик задержки
.def countTimer2 = r27
.def posR = r25

.equ timerSleep = 250
.equ timerSleep2 = 125

; начало программы
.org 0
rjmp RESET

.org $16 ; перывание таймера 0
rjmp TIMER0

TIMER0: ;начало таймер0

inc countTimer
cpi countTimer, timerSleep
ldi temp, 0
out TCNT0, temp
breq showsInt
reti

showsInt:

clr countTimer
inc countTimer2
cpi countTimer2, timerSleep2
breq IncsSeconds
reti

IncsSeconds:
clr countTimer2
inc posR
cpi posR,1
breq showReg1
cpi posR,2
breq showReg2

showReg1:
ldi temp, 0b11111111
rjmp continueTimers

showReg2:
ldi temp, 0b00000000
ldi posR,0


continueTimers:
out PORTA, temp
reti ;конец таймер 0


RESET:

ldi temp,low(RAMEND) ;загружаем указатель на стек
out SPL,temp

ldi temp,high(RAMEND) ; указатель стека, старший байт
out SPH,temp

ldi temp,0b11111111 ; контакт 0-7 порта A на выход
out DDRA,temp ;

ldi temp, 0b00000001 ; контакт 0-1 порта В на выход
out DDRB, temp
out PORTB,temp

clr countTimer
clr countTimer2

ldi temp,0b00000001
out TIMSK,temp

ldi temp,0b00000001
out TCCR0,temp

clr posR

sei ;разрешить прерывания

END:
rjmp END ;бесконечный цикл

там у меня просто циферблат стоит, пока им моргаю...)
ishpanec
Цитата(ishpanec @ Dec 21 2014, 14:54) *
не та картинка...

zombi
получается Internal Calibrated RC Oscillator 1 MHz.
Если галочка соответствует биту равному нулю.
Table 9-8. Internal Calibrated RC Oscillator Operating Modes
DS
stells
Цитата(ishpanec @ Dec 21 2014, 16:54) *
что за таблица 9?

таблица 9 из даташита... или 9-8 из приведенного выше... в принципе все уже понятно
ishpanec
да, уже разобрался, всем спасибо за помощь!)
по умолчанию в мк и правда был 1МГц, поменял биты, рпсчитал на 8 и все заработало как надо)
Код
Table 9. Internal Calibrated RC Oscillator Operating Modes
CKSEL3..0    Nominal Frequency (MHz)
0001        1.0
0010        2.0
0011        4.0
0100        8.0
akl
Ваш код дает интервал 1 секунды, за счёт сравнений в обработчике, на 39мс больше. Если такая погрешность устраивает, нет проблем. Без ручного пересчёта чисел сравнения Вы не можете менять частоту. По мне, лучше поручить эту работу ассемблеру.
CODE
ldi temp, 0b00000001 ; контакт 0-1 порта В на выход
out DDRB, temp
out PORTB,temp

;*******************************
;.equ Fo=8000000
.equ Fo=7890123

MOV R0,TEMP
SET_SEC:

IN TEMP,PINB
EOR TEMP,R0

LDI R20,BYTE3(Fo-8); загрузка 1 секунды в тиках Fo за вычетом установок
LDI R21,BYTE2(Fo-8);
LDI R22,BYTE1(Fo-8);

SEC_WAIT:
SUBI R22,BYTE1(5);
SBCI R21,BYTE2(5)
SBCI R20,BYTE3(5)

BRCC SEC_WAIT
OUT PORTB,TEMP
RJMP SET_SEC
;*******************************
.EXIT
alexeyv
Зачем для этой цели использовать 8-ми разрядный счетчик? Не проще использовать 16-ти разрядный в режиме CTC ? Один раз настроил - и будет Вам прерывание 1 раз в сек без всяких дополнительных счетчиков на Си/Асме
akl
Цитата(alexeyv @ Dec 22 2014, 09:39) *
Не проще использовать 16-ти разрядный в режиме CTC ? Один раз настроил - и будет Вам прерывание 1 раз в сек без всяких дополнительных счетчиков на Си/Асме
Проще, конечно. Попробуйте настроить один раз без дополнительных счётчиков формирователь 1.000'000 секунды для частоты 7'890'123 Гц на 16-ти разрядном таймере в режиме CTC.
RabidRabbit
Цитата(akl @ Dec 22 2014, 08:57) *
Проще, конечно. Попробуйте настроить один раз без дополнительных счётчиков формирователь 1.000'000 секунды для частоты 7'890'123 Гц на 16-ти разрядном таймере в режиме CTC.

Ну, в обычных мегах эти Ваши 7'890'123 Гц можно было поделить на 256 предделителем и для CTC поставить значение 30820. Будет частота 0,999993283, разве плохо? sm.gif А для Ваших 1.000'000 секунды поди надо кварц специально отобранный да ещё и в термостат всю конструкцию засунуть...
akl
Цитата(RabidRabbit @ Dec 22 2014, 12:35) *
Будет частота 0,999993283, разве плохо?
По мне, Плохо. И не частота, а период.
Цитата(RabidRabbit @ Dec 22 2014, 12:35) *
...поди надо кварц специально отобранный...
Частота взята для примера. Вот так студия отрабатывает такую частоту. Ничего не мешает в строке задания частоты установить требуемую и получить такой же результат.
Нажмите для просмотра прикрепленного файла
ishpanec
Цитата(alexeyv @ Dec 22 2014, 05:39) *
Не проще использовать 16-ти разрядный в режиме CTC ?


в моем не проще, все равно счет нужен. мне нужно не только считать по 1с. но минимум 25 раз в секунду изменять состояние каждого табло, проще сделать два счетчика, в первом меняем инфу на табло, во втором считаем

Цитата(akl @ Dec 22 2014, 05:18) *
Ваш код дает интервал 1 секунды, за счёт сравнений в обработчике, на 39мс больше.


чем обусловлена эта задержка?
akl
Каждое прерывание Т0, в котором дополнительно чистится TCNT0, наращиваются и сравниваются с уставками счетчики приводит к тому, что обработка идёт не через 256 тактов, а через 266. Вот отсюда и погрешность формирования интервала.
ishpanec
Цитата(akl @ Dec 22 2014, 15:03) *
в котором дополнительно чистится TCNT0


я выкинул это из кода, оно мне не нужно было, это я ставил по типу вдруг что изменится...))

без этого какова погрешность будет?
demiurg1978
Цитата(ishpanec @ Dec 21 2014, 19:54) *
с Си не дружу) после того как gcc танцы с бубном устраивать заставлял)))))

Значит попробуйте поработать в IAR. Я с ним сразу подружился.
Пример на асме:
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
//========================================================================

.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
//========================================================================
RabidRabbit
Цитата(akl @ Dec 22 2014, 12:43) *
По мне, Плохо. И не частота, а период.

А по-моему, очень даже неплохо. Чай не для сервера ntp sm.gif И кстати, батенька, вовсе не период, а именно частота: 7890123 / 256 / 30821
Вы то вообще нерабочий код выложили в посте от Dec 20 2014, 09:56 sm.gif А человек Вам поверит и будет удивляться, почему не фурычит...
akl
Да, действительно, период будет 256*30821=7890176/7890123=1,000006717259 секунды. Виноват, извините.
Ниже показана работа кода из указанного поста.
Нажмите для просмотра прикрепленного файла
RabidRabbit
Я одного не понимаю, после первого переполнения в обработчике Ваш ret не поставит на место флаг I в регистре SREG, следовательно, все последующие переполнения не будут вызывать выполнение обработчика... Ааааа, теперь я прошу прощения, хитровыраженная запись brne pc-2 несколько сбивает с толку, особенно глядя на расставленные метки...
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.