|
Таймеры atmega32a |
|
|
|
Dec 19 2014, 09:57
|
Группа: Новичок
Сообщений: 6
Регистрация: 19-12-14
Пользователь №: 84 192

|
Здравствуйте Проблема возникла такая, есть у меня 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 МГц, либо логика моих действий не верна.
|
|
|
|
|
Dec 19 2014, 14:16
|
Участник

Группа: Участник
Сообщений: 18
Регистрация: 6-04-06
Пользователь №: 15 890

|
ishpanec, Вы раздел 8-bit Timer/Counter0 with PWM документации читали? В частности про делители ( prescaler ) частоты.
|
|
|
|
|
Dec 19 2014, 15:10
|
Местный
  
Группа: Участник
Сообщений: 333
Регистрация: 19-12-13
Из: Новосибирск
Пользователь №: 79 709

|
У меня такой способ получить 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 с.
Сообщение отредактировал demiurg1978 - Dec 19 2014, 15:11
|
|
|
|
|
Dec 20 2014, 09:56
|
Частый гость
 
Группа: Свой
Сообщений: 127
Регистрация: 4-04-07
Из: Ижевск
Пользователь №: 26 773

|
С точностью до такта можно временной интервал формировать так. Писано для 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
|
|
|
|
|
Dec 21 2014, 13:54
|
Группа: Новичок
Сообщений: 6
Регистрация: 19-12-14
Пользователь №: 84 192

|
отвечу всем по порядку) Цитата(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 ;бесконечный цикл
там у меня просто циферблат стоит, пока им моргаю...)
|
|
|
|
|
Dec 21 2014, 15:17
|
Группа: Новичок
Сообщений: 6
Регистрация: 19-12-14
Пользователь №: 84 192

|
Цитата(ishpanec @ Dec 21 2014, 14:54)  не та картинка... 
|
|
|
|
|
Dec 21 2014, 18:19
|
Группа: Новичок
Сообщений: 6
Регистрация: 19-12-14
Пользователь №: 84 192

|
да, уже разобрался, всем спасибо за помощь!) по умолчанию в мк и правда был 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
|
|
|
|
|
Dec 22 2014, 04:18
|
Частый гость
 
Группа: Свой
Сообщений: 127
Регистрация: 4-04-07
Из: Ижевск
Пользователь №: 26 773

|
Ваш код дает интервал 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
|
|
|
|
|
Dec 22 2014, 05:57
|
Частый гость
 
Группа: Свой
Сообщений: 127
Регистрация: 4-04-07
Из: Ижевск
Пользователь №: 26 773

|
Цитата(alexeyv @ Dec 22 2014, 09:39)  Не проще использовать 16-ти разрядный в режиме CTC ? Один раз настроил - и будет Вам прерывание 1 раз в сек без всяких дополнительных счетчиков на Си/Асме Проще, конечно. Попробуйте настроить один раз без дополнительных счётчиков формирователь 1.000'000 секунды для частоты 7'890'123 Гц на 16-ти разрядном таймере в режиме CTC.
|
|
|
|
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|