ishpanec 0 19 декабря, 2014 Опубликовано 19 декабря, 2014 · Жалоба Здравствуйте Проблема возникла такая, есть у меня 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 0 19 декабря, 2014 Опубликовано 19 декабря, 2014 · Жалоба результат один и тот же Не плохо было бы узнать полученный результат, способ наблюдения оного. И перепроверить cksel сравнив с DS. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dust112 0 19 декабря, 2014 Опубликовано 19 декабря, 2014 · Жалоба ishpanec, Вы раздел 8-bit Timer/Counter0 with PWM документации читали? В частности про делители ( prescaler ) частоты. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
stells 9 19 декабря, 2014 Опубликовано 19 декабря, 2014 (изменено) · Жалоба если там частота 16МГц а там точно 16МГЦ? не 8? пс: таблицу 9 смотрите Изменено 19 декабря, 2014 пользователем stells Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
demiurg1978 1 19 декабря, 2014 Опубликовано 19 декабря, 2014 (изменено) · Жалоба У меня такой способ получить 1 мс при 8 и 16 мгц: /======================================================================== #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 с. Изменено 19 декабря, 2014 пользователем demiurg1978 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
akl 0 20 декабря, 2014 Опубликовано 20 декабря, 2014 · Жалоба С точностью до такта можно временной интервал формировать так. Писано для tiny13, но и для mega32 будет примерно также. .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 0 21 декабря, 2014 Опубликовано 21 декабря, 2014 · Жалоба отвечу всем по порядку) Не плохо было бы узнать полученный результат значит при счете до 62 500 мигает он раз в 15 секунд %) наблюдал просто, ни каких особых измерений, это если бы там миллисекунды погрешности было, другое дело) вот биты из программки Вы раздел 8-bit Timer/Counter0 with PWM документации читали? я исключительно по книжкам. не думал что там особая разница есть. не 8? пробовал клепать расчеты под 8, все равно заметные глазу отличия есть) мигание ~ раз в 7 секунд что за таблица 9? У меня такой способ получить 1 мс при 8 и 16 мгц: с Си не дружу) после того как gcc танцы с бубном устраивать заставлял))))) С точностью до такта можно временной интервал формировать так. Писано для tiny13, но и для mega32 будет примерно также. вашу магию тоже не совсем понял... вот моя магия 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 0 21 декабря, 2014 Опубликовано 21 декабря, 2014 · Жалоба не та картинка... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zombi 0 21 декабря, 2014 Опубликовано 21 декабря, 2014 · Жалоба получается Internal Calibrated RC Oscillator 1 MHz. Если галочка соответствует биту равному нулю. Table 9-8. Internal Calibrated RC Oscillator Operating Modes DS Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
stells 9 21 декабря, 2014 Опубликовано 21 декабря, 2014 · Жалоба что за таблица 9? таблица 9 из даташита... или 9-8 из приведенного выше... в принципе все уже понятно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ishpanec 0 21 декабря, 2014 Опубликовано 21 декабря, 2014 · Жалоба да, уже разобрался, всем спасибо за помощь!) по умолчанию в мк и правда был 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 0 22 декабря, 2014 Опубликовано 22 декабря, 2014 · Жалоба Ваш код дает интервал 1 секунды, за счёт сравнений в обработчике, на 39мс больше. Если такая погрешность устраивает, нет проблем. Без ручного пересчёта чисел сравнения Вы не можете менять частоту. По мне, лучше поручить эту работу ассемблеру. 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 0 22 декабря, 2014 Опубликовано 22 декабря, 2014 · Жалоба Зачем для этой цели использовать 8-ми разрядный счетчик? Не проще использовать 16-ти разрядный в режиме CTC ? Один раз настроил - и будет Вам прерывание 1 раз в сек без всяких дополнительных счетчиков на Си/Асме Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
akl 0 22 декабря, 2014 Опубликовано 22 декабря, 2014 · Жалоба Не проще использовать 16-ти разрядный в режиме CTC ? Один раз настроил - и будет Вам прерывание 1 раз в сек без всяких дополнительных счетчиков на Си/АсмеПроще, конечно. Попробуйте настроить один раз без дополнительных счётчиков формирователь 1.000'000 секунды для частоты 7'890'123 Гц на 16-ти разрядном таймере в режиме CTC. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RabidRabbit 0 22 декабря, 2014 Опубликовано 22 декабря, 2014 · Жалоба Проще, конечно. Попробуйте настроить один раз без дополнительных счётчиков формирователь 1.000'000 секунды для частоты 7'890'123 Гц на 16-ти разрядном таймере в режиме CTC. Ну, в обычных мегах эти Ваши 7'890'123 Гц можно было поделить на 256 предделителем и для CTC поставить значение 30820. Будет частота 0,999993283, разве плохо? :) А для Ваших 1.000'000 секунды поди надо кварц специально отобранный да ещё и в термостат всю конструкцию засунуть... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться