Перейти к содержанию

Частотомер На Atmega16


angoli

Рекомендуемые сообщения

Делаю частотомер в Proteus. Прошивку писал в codevisionavr. Микроконтроллер выбран atmega16. Стоит кварцевый резонатор 16Мгц. Подсчет времени использую таймер T2. Сигнал поступает на прерывание INT0. Когда замеряю частоту до 10 кГц, то все нормально. Но когда частота измерения 15 кГц и выше, то цифры начирают мергать из-за прерывания. А хотелось бы замерять до 6-8МГц. Может знает как изменить прошивку что бы замеряла высокие частоты и не моргали цифры?

Kyrsach.rar

Изменено пользователем angoli
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

#include <mega16.h>
#include <delay.h>

unsigned long int i;
unsigned long int frequency;
unsigned long int temp_h;
unsigned long int temp_l;
unsigned long int x, y, z;


int num[10]={
        0b11000000,    //0
        0b11111001,    //1
        0b10100100,    //2
        0b10110000,    //3              
        0b10011001,    //4
        0b10010010,    //5
        0b10000010,    //6
        0b11111000,    //7
        0b10000000,    //8
        0b10010000};   //9
int str[8]={0};


void main( void )
{
 int j;
 DDRA = 0xff;
 PORTA = 0x00;
 DDRC = 0xff;
 PORTC = 0xff;

 /*DDRD &= ~(1<<PIN_INT0);
 PORTD |= (1<<PIN_INT0); 
 GICR |= (1<<INT0); 
 MCUCR |= (1<<ISC01)|(1<<ISC00);*/

 TCCR1B |= (1<<ICES1)|(1<<CS10);
 SREG |= (1<<7);
 TIMSK |= (1<<TICIE1);


 /*TCCR2 |=(1<<CS20)|(1<<CS21)|(1<<CS22);
 SREG |=(1<<7);
 TIMSK |= (1<<TOIE2);
 TCNT2 =0;*/

 #asm("sei");

 while(1)
 {        
    str[0]=frequency/10000000;
        i=frequency%10000000;

        str[1]=i/1000000;
        i=i%1000000;

        str[2]=i/100000;
        i=i%100000;

        str[3]=i/10000;
        i=i%10000;

        str[4]=i/1000;
        i=i%1000;

        str[5]=i/100;
        i=i%100;

        str[6]=i/10;

        str[7]=i%10;

    for(j=0; j<8; j++)
     {
        PORTA = num[str[j]];

        if(j==0)
           PORTC = 0b10000000;
        if(j==1)
           PORTC = 0b01000000;
        if(j==2)
           PORTC = 0b00100000;
        if(j==3)
           PORTC = 0b00010000;
        if(j==4)
           PORTC = 0b00001000;
        if(j==5)
           PORTC = 0b00000100;
        if(j==6)
           PORTC = 0b00000010;
        if(j==7)
           PORTC = 0b00000001;
        delay_us(1000);
        PORTA=0xff;
     }

 }
}

interrupt [TIM1_CAPT] void timer1_capt_isr(void)
{

temp_h = ICR1H;
temp_l = ICR1L;
if(x == 0)
{
   x = (temp_h*256+temp_l);
}
else
{
   y = (temp_h*256+temp_l);
   z = y - x;
   frequency = (unsigned long)16000000/z; 

}
}

Нашел в интернете такой код на таймер Т1 и вставил себе в проект, но он не работает. Может вместо ICR1L должно быть другое что-то? Или вообще все не правильно?

Кстати заметил что когда ставлю измеряемую частоту 1МГц и выше, то пишет что микроконтроллер перегружен и что он не будет так работать.

Изменено пользователем angoli
Ссылка на комментарий
Поделиться на другие сайты

Изменил свой проект кординально. Теоретически у меня должно выводится правильная частота, но в протеусе выводит что захочет. Вот мои рассчеты. Таймер T2 работает на частоте микроконтроллера (16 МГц). Значит t2 будет считатся 62500 раз в секунду. Когда на вход INT0 поступает сигнал, то происходит прерывание где сохраняются состояние TCNT2 и t2. Затем останавливается прерывание INT0 на секунду. Когда пройдет 1с запустится прерывание INT0. В чем мои просчеты, кто знает?

#define SPI_MISO 4
#define SPI_MOSI 3
#define SPI_SCK 5
#define SPI_SS 2
#define PIN_INT0 PIND2
unsigned long int t2, saveregt2, savet2;
unsigned long int i;
unsigned long int frequency;
char num[10]={
	 0x00, //0
	 0x01, //1
	 0x02, //2
	 0x03, //3			
	 0x04, //4
	 0x05, //5
	 0x06, //6
	 0x07, //7
	 0x08, //8
	 0x09}; //9
int str[8]={0};
void SPI_Init(void) //инициализация выводов для порта вывода на экран
{
SPI_DDRX |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(0<<SPI_MISO);
SPI_PORTX |= (1<<SPI_MOSI)|(1<<SPI_SCK)|(1<<SPI_SS)|(1<<SPI_MISO);
SPI_PORTX |= (1<<SPI_SS);
SPI_PORTX &= ~(1<<SPI_SCK);
SPI_PORTX &= ~(1<<SPI_MOSI);
}
void SPI_WriteData(char adres, char data) //вывод на экран
{
char i=16;
int tmp=adres;
tmp = (tmp<<8)|data;
SPI_PORTX &= ~(1<<SPI_SS);
{while(i>0)
 {
 SPI_PORTX &= ~(1<<SPI_SCK);
 SPI_PORTX.SPI_MOSI=((tmp & (1<<(i-1))) != 0 );
 SPI_PORTX |= (1<<SPI_SCK);
 i--;
 }

}	
SPI_PORTX &= ~(1<<SPI_SCK);
SPI_PORTX |= (1<<SPI_SS);
SPI_PORTX &= ~(1<<SPI_MOSI);
}
char count1=8;
void main(void)
{
int j;
DDRD &= ~(1<<PIN_INT0);			 //инициализация порта на прием сигнала
PORTD |= (1<<PIN_INT0);
GICR |= (1<<INT0);
MCUCR |= (1<<ISC01)|(0<<ISC00);

TCCR2 |= (1<<CS20);					 //инициализация счетчика Т2
TIMSK |= (1<<TOIE2);

SPI_Init();
SPI_WriteData(0x09,0xFF);				 //запускаем драйвер MAX7219
SPI_WriteData(0x0A,0x0F);
SPI_WriteData(0x0B,0x07);
SPI_WriteData(0x0C,0x01);
SPI_WriteData(0x0F,0x00);
{while(count1>0)
 {
 SPI_WriteData(count1,0x00);
 count1--;
 }
}
while (1)
 {
 #asm("sei");
 frequency = 16000000/(savet2*256 + saveregt2);	 //получаем частоту
 str[0]=frequency/10000000;		 //получаем числа из частоты по одельности.
	 i=frequency%10000000;
	 str[1]=i/1000000;
	 i=i%1000000;
	 str[2]=i/100000;
	 i=i%100000;

	 str[3]=i/10000;
	 i=i%10000;

	 str[4]=i/1000;
	 i=i%1000;

	 str[5]=i/100;
	 i=i%100;

	 str[6]=i/10;

	 str[7]=i%10;

 for(j=0; j<8; j++)		 //вывод на экран
 {
	 if(j==0)
	 SPI_WriteData(0x01,num[str[j]]);
	 if(j==1)
	 SPI_WriteData(0x02,num[str[j]]);
	 if(j==2)
	 SPI_WriteData(0x03,num[str[j]]);
	 if(j==3)
	 SPI_WriteData(0x04,num[str[j]]);
	 if(j==4)
	 SPI_WriteData(0x05,num[str[j]]);
	 if(j==5)
	 SPI_WriteData(0x06,num[str[j]]);
	 if(j==6)
	 SPI_WriteData(0x07,num[str[j]]);
	 if(j==7)
	 SPI_WriteData(0x08,num[str[j]]);
	 delay_us(1000);
 }
 TCNT2 = 0;
 t2 = 0;
 }

}
interrupt [EXT_INT0] void ExtInt0(void)
{
saveregt2 = TCNT2;					 //сохраняем состояние счетчика
savet2 = t2;
GICR |= (0<<INT0);					 //останавливаем прерывание на 1с.
}
interrupt [TIM2_OVF] void timer2_ovf_isr(void)
{
if(t2 == 62500)						 //прошло 1с
{
 GICR |= (1<<INT0);					 //запускаем прерывание
}
t2++;								 //счетчик переполнений
}

111.rar

Изменено пользователем angoli
Ссылка на комментарий
Поделиться на другие сайты

Причём тут INT0 (внешнее прерывание), если Вам нужно считать количество импульсов входной частоты за промежуток времени ? И для чего какие-то остановы на 1 секунду ? Ещё бы у Вас не выводилась каша. Что-то останавливаете, запускаете когда захотите, ....

У Вас в голове всё перемешалось.

Для низкой частоты нужно измерять период (время между двумя фронтами), для более высокой - кол-во импульсов за промежуток времени.

Ссылка на комментарий
Поделиться на другие сайты

Мысль была подсчитывать не количество пришедших тактов, а подсчитывание количество тактов микроконтроллера в промежутке старта прерывания и до появления входного сигнала. Паузу (1с) делал что бы не нагружать микроконтроллер, иначе ничего показывать не будет. В прервывании T2 я было добавил сброс t2 на 0. Самое удивительное потом после первого подсчета и сброса t2 почуму-то t2 не инкрементировался хотя пауза делалась. Очень странно.

Но да ладно. Я в очередной раз переделал проект, теперь он работает до 12кГц, с погрешностью 10Гц. А если дальше гнать то погрешнать будет больше. Жалко что нельзя измерять до пару МГц. Ну да ладно.

Ссылка на комментарий
Поделиться на другие сайты

Мысль была подсчитывать не количество пришедших тактов, а подсчитывание количество тактов микроконтроллера в промежутке старта прерывания и до появления входного сигнала. Паузу (1с) делал что бы не нагружать микроконтроллер, иначе ничего показывать не будет. В прервывании T2 я было добавил сброс t2 на 0. Самое удивительное потом после первого подсчета и сброса t2 почуму-то t2 не инкрементировался хотя пауза делалась. Очень странно.

Но да ладно. Я в очередной раз переделал проект, теперь он работает до 12кГц, с погрешностью 10Гц. А если дальше гнать то погрешнать будет больше. Жалко что нельзя измерять до пару МГц. Ну да ладно.

Да ладно, нельзя. Для начала сделай простой вариант. 8-ми битным таймером отмеряешь секунду с помощью предделителя и подсчёта кол-ва переполнений в прерывании , 16-ти битный таймер настраиваешь на счёт по внешнему входу и прерывание по переполнению, считаешь в обработчике прерываний их количество, предделитель у него ставишь 1. Как только у тебя наберётся количество прерываний 8-битного таймера равные 1 секунде, запрещаешь все прерывания и выключаешь 16 битный таймер, далее количество прерываний этого таймера будет старшим байтом, старший регистр таймера, средним, младший регистр таймера, младшим затем объединяешь эти байты так, чтобы они расположились в той последовательности как написал выше и получаешь число измеренной частоты в герцах, дальше для отображения можешь преобразовывать его в килогерцы, мегагерцы. Разрешающая способность такого частотомера будет 1 герц как минимум и частоту ты мерять сможешь как минимум до 16 мегагерц. Как реализуешь этот вариан, делай для низкой частоты блок где будешь мерять период тогда можно будет переключаться между ними.

Будьте проще и люди к вам потянутся.

Ссылка на комментарий
Поделиться на другие сайты

Мысль была подсчитывание количество тактов микроконтроллера в промежутке старта прерывания и до появления входного сигнала
Мысль верная. Это - измерение периода.

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

Разрешающая способность такого частотомера будет 1 герц как минимум и частоту ты мерять сможешь как минимум до 16 мегагерц.
Я с АВРами не совсем дружу, по этому буду по наслышке. Где то на форуме слышал, что у них таймеры синхронные, т.е. каждый его инкремент (имеется в виду с внешним тактированием) происходит по тактовой частоте МК, независимо от внешнего сигнала.

Если это так, то разрешающая способность будет уменьшаться, при приближении входной частоты к частоте МК. Например, частоту 10.5 Мгц уже не померишь, т.к. период её не кратен 1/16 us.

Но, чтобы меня тут не закидывали тухлыми помидорами, скажу сразу - эта инфа недостоверная :) Возможно у АВР таймеры асинхронные.

Ссылка на комментарий
Поделиться на другие сайты

Я с АВРами не совсем дружу, по этому буду по наслышке.
Там есть асинхронный таймер (в основном для реализации RTC), к выводам OSC1/OSC2, не путать c XTAL1, XTAL2, можно подключить часовой кварц.

И есть синхронные таймеры с внешним тактированием. Согласно документации, рекомендуется, чтобы частота этого внешнего сигнала не превышала тактовой частоты, деленной на 2,5.

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Там есть асинхронный таймер .......

Ну значит реализуем точный секундный интервал и считаем таймером импульсы на тактовом входе. Сколько насчитали - такая и частота в герцах.
Ссылка на комментарий
Поделиться на другие сайты

Вопрос конечно не по теме. Но все таки. А Proteus может работать в многопоточном режиме? А то я пытаюсь в signal generator выставить частоту в 8MHz и программа ложится. Потому что ядро процессора загружается на 100%.

Ссылка на комментарий
Поделиться на другие сайты

Так ложится (вылетает) или всего лишь не тянет в реальном времени (тормозит)?

Ругался на отсутствие форматирования исходного кода (включая отсутствие осмысленных комментариев и наличие неубранного после конфигуратора мусора) не менее 15 раз.

Часть моих наработок.

Ссылка на комментарий
Поделиться на другие сайты

Вопрос конечно не по теме. Но все таки. А Proteus может работать в многопоточном режиме? А то я пытаюсь в signal generator выставить частоту в 8MHz и программа ложится. Потому что ядро процессора загружается на 100%.

Тоже пытался такое проделать в протеусе, но также, загрузка процессора на 100%, причём так было 5 лет назад и так же сейчас.

Будьте проще и люди к вам потянутся.

Ссылка на комментарий
Поделиться на другие сайты

Так ложится (вылетает) или всего лишь не тянет в реальном времени (тормозит)?

Он не то что не тянет он улаживает ядро процессора за считанные секунды.

причём так было 5 лет назад и так же сейчас.
А Вы считаете, что железо в Вашем компе "поумнеет" за 5 лет ? :) Не пыталсь его апгрейдить ? :)

А причем тут апгрейдить? Частота на ядро 5 лет назад было такое же как и сейчас.

Я так понял что не только у меня программа однопоточное. Жаль... жаль...

Ссылка на комментарий
Поделиться на другие сайты

А причем тут апгрейдить? Частота на ядро 5 лет назад было такое же как и сейчас.

А при том. Почитайте, чем отличаются старые процы от современных, и теже Атлоны от Интелов. Частота ядра это не совсем показатель производительности.

Или Вы считаете, что какой-нибудь старый одноядерный пенёк, с частотой, например, в 2.5-3.0 Ггц будет работать так же, как и современный (например i-5 или i-7) с той же частотой на одном ядре ? :)

Или, если для Вас частота ядра - показатель производительности, то может посчитаете, что Атлон и Интел с одинаковой частотой ядра и одинаковым количеством ядер тоже будут работать одинаково ? :)

Ссылка на комментарий
Поделиться на другие сайты

Я не спорю что архитектура процессара играет важную роль. Просто 5 лет назад были не слабые процессоры. И я думаю что сильно они не изменились в производительности (одного ядра). Сейчас больше уделяют вниманию увеличению многопоточности, энергосбережение и уменьшение тепловыделение. Только в этом вроде направлении изменяется архитектура процессоров. Но это лично мое точка зрения.

Вот у меня одно ядро ложится от протеуса когда я выставляю большую частоту генерации сигнала. А ведь процессор не слабый i7-47770K. Так что если смотреть со стороны одного ядра(потока), то они не сильно долеко ушли.

Изменено пользователем angoli
Ссылка на комментарий
Поделиться на другие сайты

причём так было 5 лет назад и так же сейчас.
А Вы считаете, что железо в Вашем компе "поумнеет" за 5 лет ? :) Не пыталсь его апгрейдить ? :)

Так и имелось в виду, что это с апгрейдом, что 5-ти летней давности железо ложилось, что современное, ложится также даже не пикнув. i-5 3570К 3.5 Ггц и 8 гиг оперативки.

Изменено пользователем a_sergeevich

Будьте проще и люди к вам потянутся.

Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
  • Сообщения

    • Я вскрываю металлической линейкой. Очень часто у таких блоков есть паз вдоль шва, туда вставляю линейку по всей длине шва и как рычагом вскрываю корпус. Если вначале немного промять корпус вдоль шва (бывает достаточно пальцами), то шансы легко вскрыть значительно увеличиваются.
    • При включении в ранее опубликованном виде устройство стало генератором. Частота до 140кГц, на индуктивности размах (от мин. до макс.) до 20В при напряжении на испытуемом БП ~3В. Добавил несколько конденсаторов, в том числе как рекомендовали Z_VIP и Starichok. Немного изменил номиналы резистора в компараторе. Удалил шунтирующее сопротивление на резисторе регулятора тока. Компаратор буду еще отлаживать - в приведённой ниже схеме срабатывает при 4В, но не не отпускает при отсутствии напряжения.  Ограничение тока выставил на 4А. Регулировка тока плавная от 0 до  4А. Выставленный ток стабильный при изменении напряжения от 1В до 10В. Напряжение выше 10В пока не поднимал. Ниже 0,95В ток снижается пропорционально напряжению. Схема в приложении. Все изменения-дополнения делал на существующей плате навесным монтажом. Позже выложу актуальную разводку. Отлаживал с транзисторами AP60T30 (ранее выкладывал фото транзисторов на радиаторе) - без обдува при комнатной температуре длительно держат 20Вт (10В, 2А) при температуре радиатора ~40гр.C. Приобрёл транзисторы IRFP460. С радиатором пока не определился. Схема и фото отладки на текущий момент времени. На фото стрелочный прибор - амперметр с током полного отклонения 6А. и в DipTrace:  
    • Ведь этож надо... такое совпадение. И я тоже делаю без сверлений. Более того, прилагаю фото имеющихся у меня  "хоть чуток острых предметов", несмотря на наличие которых, столь несложный и общедоступный  способ зачистки, к.м.к.  имеет право на демонстрацию в данной теме. Вдруг кому-то пригодится... Тем более, что тема простаивает аж с марта, будто на белом свете нет ничего, что можно было бы сюда  разместить,  хотя бы для сведения. 
    • В описании сказано, что МК включится после размыкания кнопки включения.
    • Мои слова ни как не относятся к тому куску кода Знаете что такое функция, аргумент, результат?
    • Устройство сделано на базе МК ATtiny44A. Так как девайс нужен был мобильный, то в качестве индикатора был выбран модуль ЖКИ на НТ1621. Схема устройства: Так как питание девайса 3 В, то пришлось на плате дисплея заменить резистор контрастности и резистор подсветки ЖКИ. R1 установил 4,7 кОм в место 20 кОм, а R2 в место 100 Ом поставил 300 Ом. Прошивка для МК: test_LCD.hex МК тактируется на заводских установках (от внутреннего генератора 1 МГц.)   Аккумулятор Li-ion 1100 мАч. В качестве зарядного устройства, используется модуль ТР4056.   При полной зарядке аккумулятора, устройство работает без подзаряда около 27 дней. Индикатор на дисплее, помогает визуально контролировать уровень заряда для последующей подзарядки аккумулятора. При напряжении на аккумуляторе ниже 3,4 В подсветка индикатора гаснет для снижении потребляемого тока. Подсветка гаснет и в ночное время (при недостаточном освещении), чтобы свет дисплея не мешал во время сна.
    • @korsaj Ну согласно твоих слов и этот код примерно тоже самое и получается. Я и не вижу особых отличий. Но нужно только как то доработать чтоб оно работало. В том то всё и дело что оно не работает. А учитывая как раз таки что мне нужны будут определённые фрагменты где хранятся данные, то это очень хорошее решение, но нужно его доработать до рабочего состояния.
  • Похожий контент

×
×
  • Создать...