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

 
 
> Затраты на обработку прерывания по переполнению таймера.
zheka
сообщение Jan 21 2010, 18:11
Сообщение #1


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Господа, пишу программку для подсчета периода импульсов. Могу применять только 8-битный таймер, ибо 16-ти битный таймер занят.
Всвязи с тем что переполнение его наступает через каждые 256 тактов, их приходится точно просчитывать.
Вот такой вот код:
Код
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
//tacts++;
a=TCNT0;
TCCR0=0x00;
lcd_gotoxy(0,0);
lcd_putsf("       ");

lcd_gotoxy(0,0);
   sprintf(s," %i", a);
     lcd_puts(s);

TCCR0=0x01;


}


То есть сразу по прерывания по переполнения таймер по идее должен сбрасываться. В самом начале обработчика значение TCNT0 записывается в переменную a. И ее значение выводится на экран. Так вот в данном случае оно равно 32 или 33 (в зависимости от фазы луны и того, чем я похмелялся )))) ). Что контроллер делает эти 32 такта?
ПРичем 32 такта выдается хоть при 16 000 кГц, хоть при делении на 8 (2000 кГц).
Инициализирую таймер так:

Код
// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x01;
TCNT0=0x00;
OCR0=0x00;


Что делать и кто виноват?

У кого нибьудь есть опыт написания таких программ, когда приходилось несколько циклов переполнения таймера складывать. Как-нибудь компенсировали время, затрачиваемое на обработку прерывания?
Go to the top of the page
 
+Quote Post
3 страниц V   1 2 3 >  
Start new topic
Ответов (1 - 31)
Goodefine
сообщение Jan 21 2010, 18:34
Сообщение #2


Местный
***

Группа: Свой
Сообщений: 211
Регистрация: 6-08-07
Из: Приднестровье, Тирасполь
Пользователь №: 29 581



Цитата(zheka @ Jan 21 2010, 22:11) *
...Всвязи с тем что переполнение его наступает через каждые 256 тактов, их приходится точно просчитывать...

Просчитыванию очень способствуют функции типа:
Цитата(zheka @ Jan 21 2010, 22:11) *
Код
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
...
lcd_gotoxy(0,0);
lcd_putsf("       ");
lcd_gotoxy(0,0);
sprintf(s," %i", a);
lcd_puts(s);
...}

Как Вы думаете, за сколько тактов они выполнятся и сколько раз за это время переполнится таймер?..


--------------------
Любой, заслуживающий внимания, опыт приобретается себе в убыток...
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 21 2010, 18:37
Сообщение #3


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Господи, ну читайте же внимательно мой код. Или укажите где я не прав?
Прежде чем обращаться к LCD, я загнал в переменную а содержание TCNT0. А эта операция, как я выяснил для char занимает один такт, для int - 4 такта, для long int 20 тактов. А потом хоть заобращайся к LCD, он будет выводить правильное значение.

Еще версии будут?
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 21 2010, 18:37
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zheka @ Jan 21 2010, 23:11) *
Что контроллер делает эти 32 такта?
Скорее всего выполняет пролог обработчика прерывания - сохранение содержимого регистров на стеке. А листинг ассемблера посмотреть не догадались?
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 21 2010, 18:52
Сообщение #5


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Код
А листинг ассемблера посмотреть не догадались?

К сожалению, китайский не изучал)))

Никак нельзя этот период стабилизировать? У меня две цифры отображаются - 32 и 33.




Опять таки-чисто практический вопрос - имея таймер 8 бит, как посчитать период импульсов? Длительность от 500 мкс до 1 сек. Точность - 1 такт (клок 160 МГц).
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 21 2010, 19:07
Сообщение #6


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(zheka @ Jan 21 2010, 23:52) *
К сожалению, китайский не изучал)))
Ну сюда его (листинг) выложите, тут его поймут.
Цитата(zheka @ Jan 21 2010, 23:52) *
Никак нельзя этот период стабилизировать?
Попробуйте использовать для сохранения TCNT0 глобальную или статическую переменную и вынести из обработчика прерывания вызовы любых функций. Пока в обработчике прерывания есть вызовы других функций компилятор будет формировать пролог из блока сохранения всех регистров.
Go to the top of the page
 
+Quote Post
defunct
сообщение Jan 21 2010, 19:14
Сообщение #7


кекс
******

Группа: Свой
Сообщений: 3 825
Регистрация: 17-12-05
Из: Киев
Пользователь №: 12 326



Цитата(zheka @ Jan 21 2010, 20:52) *
Никак нельзя этот период стабилизировать?

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

Цитата
Опять таки-чисто практический вопрос - имея таймер 8 бит, как посчитать период импульсов? Длительность от 500 мкс до 1 сек. Точность - 1 такт (клок 160 МГц).

160Mhz это не опечатка? Вроде в ветке по AVR находимся... стало быть 16Mhz.

В свете того что 8-ми битный таймер как правило обделенный, то есть только один вариант - очень и очень долго мерять и с помощью мат статисткики отсеивать результаты с большой погрешностью.

А если хотите быстро, тогда обязательно нужен input capture и хотя бы поверхностное знание китайского.
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 22 2010, 03:54
Сообщение #8


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Господа, я в принципе только сейчас понял: вывод на экран - это временно, в процессе изучения работы таймера, в дальнейшем там будет только tacts++. Мне главное посчитать, сколько раз таймер переполнился. То есть компенсировать и прибавлять эти 32 такта мне не потребуется. ПРоблема в другом - на каждые 256 тактов будет приходиться 32 такта бесполезной работы, то есть 12,5% времени псу под хвост. Так что решение проблемы только одно, освободить 16-битный таймер (там й меня все равно PWM который можно на 0 или 2 таймер посадить) и с ним работать.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 22 2010, 04:54
Сообщение #9


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(zheka @ Jan 22 2010, 07:54) *
на каждые 256 тактов будет приходиться 32 такта бесполезной работы, то есть 12,5% времени псу под хвост.

1111493779.gif Вы чего там надумали?
Код
// Registers used
// SaveSREG - keep SREG during ISR execution
// TickL, TickH - store 16-bit overflow data
timer0_ovf_isr:
        in SaveSREG,SREG //1
        inc TickL//1
        brne label1//2
        inc TickH//1
label1:
        out SREG,SaveSREG //1
        reti //4
//Total: 4+1+1+2+1+1=10 clocks + interrupt response time

Комментировать очевидное не буду. в помощь
Go to the top of the page
 
+Quote Post
Александр Куличо...
сообщение Jan 22 2010, 06:15
Сообщение #10


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017



Цитата
Длительность от 500 мкс до 1 сек. Точность - 1 такт (клок 160 МГц).

Такую точность можно получить только используя регистр захвата + прерывание по захвату. И, само собой разумеется, считать прерывания по переполнению. А в прерывании по захвату (после второго перепада) анализировать значения TCNT и ICR. Если TCNT < ICR, то последнее переполнение не учитывать.
Go to the top of the page
 
+Quote Post
fantex
сообщение Jan 22 2010, 09:09
Сообщение #11


Участник
*

Группа: Свой
Сообщений: 54
Регистрация: 4-11-05
Пользователь №: 10 480



Цитата
Опять таки-чисто практический вопрос - имея таймер 8 бит, как посчитать период импульсов? Длительность от 500 мкс до 1 сек. Точность - 1 такт (клок 16 МГц).


При периоде импульсов 1 сек, получается точность измерения 0.00000625%. Что это за такие импульсы, которые требуют такую точность измерения?
Go to the top of the page
 
+Quote Post
rezident
сообщение Jan 22 2010, 09:59
Сообщение #12


Гуру
******

Группа: Свой
Сообщений: 10 920
Регистрация: 5-04-05
Пользователь №: 3 882



Цитата(fantex @ Jan 22 2010, 14:09) *
При периоде импульсов 1 сек, получается точность измерения 0.00000625%. Что это за такие импульсы, которые требуют такую точность измерения?
Очередное заблуждение. Это не точность, а разрешение. Реальная точность порядка на три меньше будет. Точность зависит от стабильности частоты кварцевого генератора и стабильности логических уровней входной логики порта МК на который подается входной сигнал. В общем случае (если не принимать спец. приемов и методов) точность ну никак не лучше 50ppm (0,005%) будет.
Go to the top of the page
 
+Quote Post
fantex
сообщение Jan 22 2010, 10:41
Сообщение #13


Участник
*

Группа: Свой
Сообщений: 54
Регистрация: 4-11-05
Пользователь №: 10 480



Тогда какой смысл измерять с таким разрешением (0.0625 мкс), когда достаточно для точности 0.005% разрешения 25мкс?
Или может у автора стоит прецизионный кварцевый генератор с точностью 1ppm и он делает прецизионный частотомер?

Сообщение отредактировал fantex - Jan 22 2010, 10:43
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 22 2010, 11:37
Сообщение #14


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
При периоде импульсов 1 сек, получается точность измерения 0.00000625%. Что это за такие импульсы, которые требуют такую точность измерения?

Это скорее юношеский максимализм))) Хочется написать рациональную программу. И если она позволяет измерять с точностью до такта то почему-бы нет? ПО сути - это тахометр для модельного двигателя, который раскручивается до 100 тыс об/мин. ПРи рассчитанной предыдущим оратором точности разрешающая способность будет равна 15 об/мин.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 22 2010, 12:40
Сообщение #15


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Если точность 1 клок, то Вам без input capture не обойтись. В противном случае Вам надо формировать точные задержки, при этом проц будет занят только этой задачей - тоже не годится.
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 22 2010, 14:39
Сообщение #16


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Все господа.... мысли кончились. Не гонясь за точностью, пытаюсь сделать хоть что-то.
Завел Timer0 на 16 МГц. ПО переполнению инкрементирую OVF_count - счетчик переполнений. Timer1 в режиме PWM настроен на период 20 мс, выход поступает на вход INT0, фронту импульса запускается обработчик, который умножает OVF_count на 256 , прибавляет текущее значение TCNT0, после чего делит на 16 - получаем период в микросекундах. У меня же проказывает не 20 000 мкс, а 1610 либо 1594. Вот код, где я не прав?
CODE
#include <mega32.h>
#include <delay.h>
#include <stdio.h>

#asm
.equ __lcd_port=0x15;PORTC
#endasm
#include <lcd.h>


#define FAN PORTB.4

#define FINEUP PIND.7
#define FINEDOWN PIND.4

#define SPEED_MINUS PIND.6
#define SPEED_PLUS PIND.1


#define SPEED_MIN 0x0490
#define SPEED_MAX 0x07D0

#define SPEED OCR1A





char lcd_buffer[33];
unsigned char s[8];

unsigned int a,b;

unsigned int OVF_count;


unsigned long int time;




// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{
a=TCNT0;
time=(OVF_count*256+a)/16;
OVF_count=0;
lcd_clear();
lcd_gotoxy(0,0);
sprintf(s,"%u", time);
lcd_puts(s);

}

interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
OVF_count++;
}




main()
{

unsigned char i,j, devices;
int temp;

OVF_count=0;


// Timer/Counter 0 initialization
// Clock source: System Clock
// Clock value: 16000,000 kHz
// Mode: Normal top=FFh
// OC0 output: Disconnected
TCCR0=0x01;
TCNT0=0x00;
OCR0=0x00;


// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 2000,000 kHz
// Mode: Ph. & fr. cor. PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x80;
TCCR1B=0x12;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x4E;
ICR1L=0x00;
OCR1BH=0x00;
OCR1BL=0x00;


// Timer(s)/Counter(s) Interrupt(s) initialization

TIMSK=0b00000001;

// External Interrupt(s) initialization
// INT0: On
// INT0 Mode: Rising Edge
// INT1: Off
// INT2: Off
GICR|=0x40;
MCUCR=0x03;
MCUCSR=0x00;
GIFR=0x40;


SPEED=SPEED_MIN;

DDRA=0xFF;
DDRD=0x00;
PORTD=0xFF;

DDRD.5=1;

DDRB.4=1;
FAN=1;
delay_ms(500);
FAN=0;

DDRD.2=0;
PORTD.2=0;

DDRD.0=0;
PORTD.0=1;


lcd_init(8);
lcd_clear();


#asm
sei
#endasm



while (1)
{

if (!SPEED_PLUS)
{
if (SPEED<SPEED_MAX) SPEED++;
delay_ms(2);
}

if (!SPEED_MINUS)
{

if (SPEED>SPEED_MIN) SPEED--;
delay_ms(2);
}





}








}


Сообщение отредактировал rezident - Jan 22 2010, 15:07
Причина редактирования: Нарушение п.3.4 Правил форума.
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 22 2010, 15:36
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(zheka @ Jan 22 2010, 17:39) *
Вот код, где я не прав?
Прикиньте: какое значение переменной OVF_count ? А, если умножить это значение на 256 ? А, поместиться ли полученное значение в int ?
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 22 2010, 19:14
Сообщение #18


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Хм.. а вот тут уже незнание мной матчасти, вопрос вообще можно было бы выделить в отдельную тему.
Формула у меня такая: time=(OVF_count*256+a)/16; time имеет тип long int. Я думал этого достаточно. Разве умножаемая величина должна быть подходящего типа? Я думал, что только произведение...

Да, кстати, отключил таймер1, заменил сигнал с него на цикл PORTD.5=1;PORTD.5=0; с задержкой в 1 мс (период 2 мс). На осциллографе длительность периода составила 2,1 мс. Запретил обработку прерываний (внешнего и переполнения T0) - стало ровно 2 мс. Кроме того с вычислениями все в порядке стало, в пределах 2 мс показывает отлично, остальные диапазоны не проверял. Может быть таймер1 вносит в работу программы какую-то разножопицу? Хотя прерывания с него запрещены и работает он в режиме phase & frequency correction PWM.

Сообщение отредактировал zheka - Jan 22 2010, 19:17
Go to the top of the page
 
+Quote Post
Александр Куличо...
сообщение Jan 22 2010, 21:10
Сообщение #19


Местный
***

Группа: Свой
Сообщений: 256
Регистрация: 6-03-06
Из: Украина, г. Винница
Пользователь №: 15 017



Цитата
Timer1 в режиме PWM настроен на период 20 мс, выход поступает на вход INT0

А почему не используете одно из прерываний таймера? зачем такой обходной путь?
Цитата
time=(OVF_count*256+a)/16;

Установите предделитель таймера на 8 и Вам для 20 мс хватит разрядности unsigned int.
Тогда time=(OVF_count*256+a)/2;
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 23 2010, 07:38
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(Александр Куличок @ Jan 23 2010, 00:10) *
Установите предделитель таймера на 8 и Вам для 20 мс хватит разрядности unsigned int.
Разрядности и так хватит. Можно записать выражение, например, так : time=OVF_count*16+a/16;
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 24 2010, 11:05
Сообщение #21


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Цитата
А почему не используете одно из прерываний таймера? зачем такой обходной путь?


Александр, если вы мне подскажете способ, как сделать на 8-битном таймере PWM периодом 20 мс, чтобы освободить Timer1, или как на одном Timer1 сделать одновременно и PWM и измерение периода импульсов, то я откажусь от INT0
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jan 24 2010, 13:11
Сообщение #22


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(zheka @ Jan 24 2010, 15:05) *
PWM периодом 20 мс

Какая дискретность нужна?
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 24 2010, 14:56
Сообщение #23


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Дискретность? думаю, что той что обеспечит 8-битный таймер хватит. ДЛина импульса от 0.8 до 2 мс.
Насколько я понял, на 8-битном таймере максимальный период при наибольшем коэффициенте деления будет 16 мс. БОльше не сделаешь? МОжет добавить в обработчик переполнения задержку в 4 мс?

Сообщение отредактировал zheka - Jan 24 2010, 14:57
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 24 2010, 18:50
Сообщение #24


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



В общем, конфликтуют у меня два таймера. Переделал на TImer1 - все нормально, генерирую в цикле импульс периодом 500 мкс (через delay_ms) показывает 504 мкс, и даже не знаю, может быть именно delay_us вносит эту погрешность.
Но, как только разрешаю прерывание по переполнению Timer0 - сразу скачет на 553 мкс, причем показания нестабильны. Даже запрет прерываний на время обработки и вывода на экран не помогают...

Сообщение отредактировал zheka - Jan 24 2010, 18:56
Go to the top of the page
 
+Quote Post
fantex
сообщение Jan 25 2010, 11:38
Сообщение #25


Участник
*

Группа: Свой
Сообщений: 54
Регистрация: 4-11-05
Пользователь №: 10 480



Вот пример реализации измерения частоты импульсов на CPU188-MX5.
Основная идея способа - считать количество импульсов и время между передними фронтами импульсов.
Если время между фронтами превышает заданное (в данном случае 3 секунды), то полученые значения кол-ва импульсов
и время между фронтами копируется в соответствующие переменные, из которых внешняя функция вычисляет уже частоту импульсов.

CODE

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

namespace FI
{
word timeMS = -1;
word freqCount = 0;

void __declspec(naked) interrupt IntHandler();
};

//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

void __declspec(naked) interrupt FI::IntHandler()
{
static word sMS = 0;
static word count = 0;

__asm
{
push ax // 14
push dx // 14
push ds // 13

mov ax, seg millisecondsCount // 4
mov ds, ax // 2

inc [count] // 19
mov ax, [word ptr millisecondsCount] // 2
mov dx, [sMS] // 2
sub ax, dx // 3
cmp ax, 3000 // 3

jnc loc2 // 4, 13

locret:

pop ds
pop dx
pop ax
iret

loc2:

add dx, ax

mov [byte ptr sMS], dl // 2
mov [byte ptr sMS+1], dh // 2
mov [byte ptr timeMS], al // 2
mov [byte ptr timeMS+1], ah // 2

mov al, [byte ptr count] // 2
mov ah, [byte ptr count+1] // 2

mov [byte ptr freqCount], al // 2
mov [byte ptr freqCount+1], ah // 2

xor al, al // 3
mov [byte ptr count], al // 2
mov [byte ptr count+1], al // 2


pop ds // 12
pop dx // 14
pop ax // 14
iret // 28

}
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

float FI::GetFreq()
{
TRACE

float f1;
float f2;

_cli();

f1 = FI::freqCount;
f2 = FI::timeMS;
FI::freqCount = 0; FI::timeMS = -1;

_sti();

return 1000.0 * f1 / f2;
}

//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


Сообщение отредактировал fantex - Jan 25 2010, 11:39
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 25 2010, 12:44
Сообщение #26


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Fantex, спасибо, но, с алгоритмом я разобрался, у меня не получаются детали и конкретная реализация на конкретном камне. КРоме того, я пишу на С.
Метод подсчета импульсов мне ну никак не подходит.
Go to the top of the page
 
+Quote Post
ILYAUL
сообщение Jan 25 2010, 13:26
Сообщение #27


Профессионал
*****

Группа: Свой
Сообщений: 1 940
Регистрация: 16-12-07
Из: Москва
Пользователь №: 33 339



Цитата(zheka @ Jan 25 2010, 15:44) *
... реализация на конкретном камне.......
.

Вот кстати , а камень то какой


--------------------
Закон Мерфи:

Чем тщательнее составлен проект, тем больше неразбериха, если что-то пошло не так
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 25 2010, 13:59
Сообщение #28


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Камень ATMega32.

Вот, господа, упростил до безобразия:
По прерыванию INT0 сразу запоминаю значение TCNT0 и количество переполнений таймера0 (всего-то 256 тиков, вдруг чего...) Затем обнуляю таймер: если импульс первый, то начинаем жихнь с чистого листа, если второй, то пофиг, мы то уже запомнили его значение. Далее, чтобы свести к минмимуму влияние вывода на LCD на время, проверяю, первый ли импусьс? Если первый, то обнуляю счетчик переполнений и сбрасываю флаг "первого импульса", дабы при следующем срабатывании он считался вторым.

Код
// External Interrupt 0 service routine
interrupt [EXT_INT0] void ext_int0_isr(void)
{

a=TCNT0;  
b=OVF_count;
TCNT0=0x00;


if (!first_pulse)
{

// time=((OVF_count*256+a)/16);
lcd_clear();
lcd_gotoxy(1,0);
sprintf(s,"%u", b);
lcd_puts(s);        
lcd_gotoxy(1,1);
sprintf(s,"%u", a);
lcd_puts(s);        
OVF_count=0;
first_pulse=1;
TCNT0=0x00;
}
else
{
   first_pulse=0;
   OVF_count=0;
}


}


interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
OVF_count++;
}



Генерирую импульсы с периодом 1024 мкс. По идее таймер должен переполниться 64 раза на частоте 16 МГц. Показывает 80. Ну да ладно. Далее - запускаю таймер1. События на нем не обрабатываются, да и вообще, прерывания с него запрещены: TIMSK=0b00000001; Тем не менее, когда я его запускаю:
Код
/ Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 2000,000 kHz
// Mode: Ph. & fr. cor. PWM top=ICR1
// OC1A output: Non-Inv.
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x80;
TCCR1B=0x12;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x4E;
ICR1L=0x00;
OCR1BH=0x00;
OCR1BL=0x00;


на экран выводится число переполнений 1248. Если упрощаю поведение таймера : TCCR1A=0x00;TCCR1B=0x01;, то ничего такого нет, показывает 80.
Господа, мысли кончились. Почему таймеры не уживаются?

кстати, чем больше делитель TIMER1, тем больше улетает величина OVF_count. Если ее не делить, то показывает 96.



А уж если включаю TOIE1, то контроллер начинает ресетиться.

В TIFR при проверке все время висит 0x3F.

Сообщение отредактировал zheka - Jan 25 2010, 13:39
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 25 2010, 15:49
Сообщение #29


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(zheka @ Jan 25 2010, 16:59) *
Почему таймеры не уживаются?
Вы предлагаете погадать? Ну, например, разрешены прерывания от таймера 1, а процедура обработки прерывания не написана. При прерываниях от таймера 1 МК попадает на вектора 7-10, но там не команды перехода. МК добирается до векторов таймера 0 (на вектор 12, например), и благополучно попадает на функцию обработки его (таймера 0) прерывания по переполнению...

Совет: выбросить вывод на LCD из обработчика прерывания таймера: поставьте взведение флага вывода в прерывании - перенесите сам вывод в main во внутрь бесконечного цикла с проверкой флага.
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 25 2010, 16:00
Сообщение #30


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Палыч, вообще-то прерывания тапймера1 запрещены. ПОпробую ваш совет про вывод в main
Go to the top of the page
 
+Quote Post
Палыч
сообщение Jan 25 2010, 16:19
Сообщение #31


Гуру
******

Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954



Цитата(zheka @ Jan 25 2010, 19:00) *
вообще-то прерывания тапймера1 запрещены.
Уж - не знаю: что Вы занесли в TIMSK - всю программу Вы не привели - приходиться гадать...
Go to the top of the page
 
+Quote Post
zheka
сообщение Jan 25 2010, 17:32
Сообщение #32


Гуру
******

Группа: Участник
Сообщений: 2 072
Регистрация: 14-01-06
Пользователь №: 13 164



Палыч, однако спасибо Вам. Вынес все наружу. Все заработало!!! Ошибка в 1 мкс (16 тактов), причем ошибка ненакапливающаяся.
Осталось приладить и проверить не генератором импульсов, а двигателем.
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 23:17
Рейтинг@Mail.ru


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