

На начальном этапе стоит задача измерения частоты импульсов с датчика скорости (таз 21099i). Датчик выдаёт 6004 импульса на 1 км пути, т.е. 6 импульсов на 1 м. Частота импульсов прямопропорциональна скорости авто.
Начал делать на Кодевижене. Алгоритм такой: в main стартует таймер0, контроллер постоянно обновляет lcd дисплей из переменной. По прерыванию с ноги: останавливаю таймер0, ссчитываю его значение в переменную, обнуляю его, стартую таймер.
ATmega8515, 4МГц, в качестве ДС At90S2313, который формирует прямоугольные импульсы длиной 10мс, время между импульсами 10мс.
По началу использовал 8-битный таймер, при делителе частоты таймера 1024, в счётчике было значение 0-1, при делителе 1 в счётчике 69-70, хотя должно быть несколько тысяч. Я так понимаю он несколько раз успевает переполниться?
Нашёл в нете исходник на C маршрутного компьютера, который умеет мерять скорость с ДС. В нём используется 16-битный таймер1:
Код
void IRQ_Speedometer_Lable(void) interrupt 0
{
// Считываем значение интервала между метками скорости в числе 0.5 мксек.
union LONG_INT
{
unsigned long int Long;
unsigned char Byte[4];
};
union LONG_INT Interval;
unsigned int Tmp;
TR1=0;
Interval.Byte[3]=TL1; Interval.Byte[2]=TH1;
Interval.Byte[1]=Speed_Interval; Interval.Byte[0]=0;
TH1=TL1=0;
Speed_Interval=0;
TR1=1;
// Вычисляем текущую скорость движения.
Tmp=((16666666/Interval.Long)*72)/100;
Speed=Tmp/10;
if((Tmp%10) >= 5) Speed++;
// Смотрим, разрешен ли подсчет параметров маршрута.
if((Trip_Params.State&0x01) != 0)
{
// Инкрементируем счетчик пройденного расстояния.
Trip_Params.Passed_Distance++;
}
return;
}
{
// Считываем значение интервала между метками скорости в числе 0.5 мксек.
union LONG_INT
{
unsigned long int Long;
unsigned char Byte[4];
};
union LONG_INT Interval;
unsigned int Tmp;
TR1=0;
Interval.Byte[3]=TL1; Interval.Byte[2]=TH1;
Interval.Byte[1]=Speed_Interval; Interval.Byte[0]=0;
TH1=TL1=0;
Speed_Interval=0;
TR1=1;
// Вычисляем текущую скорость движения.
Tmp=((16666666/Interval.Long)*72)/100;
Speed=Tmp/10;
if((Tmp%10) >= 5) Speed++;
// Смотрим, разрешен ли подсчет параметров маршрута.
if((Trip_Params.State&0x01) != 0)
{
// Инкрементируем счетчик пройденного расстояния.
Trip_Params.Passed_Distance++;
}
return;
}
Так и не понял что за переменная speed_interval, ну это не столь важно.
Попробовал переделать свою прогу под таймер1, но никогда им не пользовался, напортачил, в таймере всегда 0. Посмотрите плиз:
Код
#include <mega8515.h>
#include <stdio.h>
#include <delay.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x15;PORTC
#endasm
#include <lcd.h>
char lcd_buffer[33];
// Процедуры
void init(void);
void imp(void);
unsigned char k;
union LONG_INT
{
unsigned long int Long;
unsigned char Byte[4];
}Interval;
unsigned int Tmp;
interrupt [2] comp(void){imp();}
//---------------------------------------- Инициализация -----------------------------------------------
void init(void)
{lcd_init(16);
TCCR1B=0x81;
GICR|=0x40;
MCUCR=0x00;
EMCUCR=0x00;
GIFR=0x40;
DDRD=0x00;
PORTD=0xff;
lcd_init(16);
#asm("sei")
k=0;
}
//------------------------------------- Процедура вызываемая по Int0 ------------------------------------------
void imp(void)
{ unsigned char Speed_Interval;
Speed_Interval=0; // ???
TCCR1B=0x00;
Interval.Byte[3]=TCNT1L; Interval.Byte[2]=TCNT1H;
Interval.Byte[1]=Speed_Interval; Interval.Byte[0]=0;
TCNT1H=TCNT1L=0;
Speed_Interval=0;
TCCR1B=0x81;
// Вычисляем текущую скорость движения.
Tmp=((16666666/Interval.Long)*72)/100;
k=Tmp/10;
if((Tmp%10) >= 5) k++;
sprintf(lcd_buffer,"Скорость: %d",k);
return;
}
//----------------------------------- Главная процедура -----------------------------------------------
void main(void)
{
init();
#pragma ruslcd+
while (1)
{
lcd_clear();
lcd_puts(lcd_buffer);
delay_ms(100);
}
#pragma ruslcd-
}
#include <stdio.h>
#include <delay.h>
// Alphanumeric LCD Module functions
#asm
.equ __lcd_port=0x15;PORTC
#endasm
#include <lcd.h>
char lcd_buffer[33];
// Процедуры
void init(void);
void imp(void);
unsigned char k;
union LONG_INT
{
unsigned long int Long;
unsigned char Byte[4];
}Interval;
unsigned int Tmp;
interrupt [2] comp(void){imp();}
//---------------------------------------- Инициализация -----------------------------------------------
void init(void)
{lcd_init(16);
TCCR1B=0x81;
GICR|=0x40;
MCUCR=0x00;
EMCUCR=0x00;
GIFR=0x40;
DDRD=0x00;
PORTD=0xff;
lcd_init(16);
#asm("sei")
k=0;
}
//------------------------------------- Процедура вызываемая по Int0 ------------------------------------------
void imp(void)
{ unsigned char Speed_Interval;
Speed_Interval=0; // ???
TCCR1B=0x00;
Interval.Byte[3]=TCNT1L; Interval.Byte[2]=TCNT1H;
Interval.Byte[1]=Speed_Interval; Interval.Byte[0]=0;
TCNT1H=TCNT1L=0;
Speed_Interval=0;
TCCR1B=0x81;
// Вычисляем текущую скорость движения.
Tmp=((16666666/Interval.Long)*72)/100;
k=Tmp/10;
if((Tmp%10) >= 5) k++;
sprintf(lcd_buffer,"Скорость: %d",k);
return;
}
//----------------------------------- Главная процедура -----------------------------------------------
void main(void)
{
init();
#pragma ruslcd+
while (1)
{
lcd_clear();
lcd_puts(lcd_buffer);
delay_ms(100);
}
#pragma ruslcd-
}
Буду благодарен любой помощи
