Измеритель скважности и длительности импульсов

Измеритель предназначен для измерения скважности и длительности импульсов уровня TTL с периодом следования от 1 мс до нескольких минут, при длительности импульса от 10 мкс.

В измерителе скважности и длительности импульсов используется плата LGT8F328P-LQFP32 MiniEVB и дисплей 0,96″ I2C 128×64 OLED.

LGT8F328P-LQFP32 MiniEVB — это плата разработки, основанная на микроконтроллере LGT8F328P с 32 выводами в корпусе LQFP32. Это мощный микроконтроллер, который обеспечивает высокую производительность и широкие возможности для разработки.

0,96″ I2C 128×64 OLED — это компактный дисплей, который использует технологию OLED (Organic Light Emitting Diode) для отображения изображений. Дисплей имеет интерфейс I2C, который обеспечивает простое подключение к микроконтроллерам и другим устройствам.

Схема измерителя скважности и длительности импульсов

Измеритель скважности и длительности импульсов имеет индикатор измерения и тестовый выход (меандр 1 Гц). Мигание индикатора измерения свидетельствует о наличии на входе импульсов, период мигания зависит от длительности поступающих на вход импульсов.

Дисплей измерителя выводит следующую информацию:

  • Длительность импульсов в мс (0,000 мс)
  • Скважность импульсов в мс (0,000 мс)
  • Период в мс (0,000 мс)
  • Частота сигнала в Гц (0,000 Гц)
  • Графическое изображение импульса

Дополнительно все измеренные параметры импульсов выводятся в монитор порта:

Измерение импульсов с периодом 120 секунд и длительностью импульса 800 мс

Как добавить поддержку LGT8F328P (плата) в Arduino IDE и прошить микроконтроллер написано в LGT8F328P-LQFP32 MiniEVB в Arduino IDE.

LGT8F328P-LQFP32 MiniEVB

Скетч:

#include <Wire.h>
#include <OLED_I2C.h>           // http://rcl-radio.ru/wp-content/uploads/2022/01/OLED_I2C.zip
 OLED  myOLED(SDA, SCL, 8);
 extern uint8_t SmallFont[];
 char i;
 unsigned long times0,times1,t0,t1;
 int w=1;

void setup(){
  Serial.begin(9600);
  Wire.begin();
  Wire.setClock(50000L);
  delay(300);
  myOLED.begin();
  myOLED.setBrightness(100);
  DDRB |= PB5; // D13 ARUINO > OUTPUT
  DDRD &= ~(1 << 2);  // D2 ARDUINO > INPUT (INT0)
  EICRA |= (1<<ISC00); // любое изменение на INT0
  EIMSK |= (1<<INT0); // разрешить внешние прерывания INT0
  noInterrupts();
  TCNT1 = 0;
  TCCR1A = 0;
  TCCR1C = 0;
  TCCR1A = 1 << COM1A0;
  TCCR1B = 1 << WGM12 | 1 << CS12 | 1 << CS10;
  DDRB =  1 << DDB1;
  OCR1A = 15624;
  interrupts();
  }

void loop(){
  if(w==1){
  EIMSK &=~ (1<<INT0);
  PORTB |=(1 << PB5);
  Serial.print("T1 ");Serial.print(t0/1000.0,3);Serial.println(" mS");
  Serial.print("T2 ");Serial.print(t1/1000.0,3);Serial.println(" mS");
  Serial.print("T  ");Serial.print((t1+t0)/1000.0,3);Serial.println(" mS");
  Serial.print("F  ");Serial.print(1000000.0/(t1+t0),3);Serial.println(" Hz");
  Serial.println();
  //////////////////////
  myOLED.clrScr();
  myOLED.setFont(SmallFont);
  myOLED.print(F("T1"),LEFT,0);myOLED.printNumF(t0/1000.000,3, 30, 0);myOLED.print(F("mS"), RIGHT, 0);
  myOLED.print(F("T2"),LEFT,10);myOLED.printNumF(t1/1000.000,3, 30, 10);myOLED.print(F("mS"), RIGHT, 10);
  myOLED.print(F("T "),LEFT,20);myOLED.printNumF((t1+t0)/1000.0,3, 30, 20);myOLED.print(F("mS"), RIGHT, 20);
  myOLED.print(F("F "),LEFT,30);myOLED.printNumF(1000000.0/(t1+t0),3, 30, 30);myOLED.print(F("Hz"), RIGHT, 30);
  ///////////
  myOLED.drawLine(0, 40, 128, 40);
  float t_dl = t0;
  float t_sk = t1;
  float t_pr = t0+t1;
  myOLED.drawLine(0, 60, 5, 60);
  myOLED.drawLine(5, 60, 5, 45);
  myOLED.drawLine(5, 45, 5+(t_dl/t_pr)*120, 45);
  myOLED.drawLine(5+(t_dl/t_pr)*120, 60, 5+(t_dl/t_pr)*120, 45);
  myOLED.drawLine(5+(t_dl/t_pr)*120, 60, 5+(t_dl/t_pr)*120+(t_sk/t_pr)*120, 60);
  ///////////
  myOLED.update();
  PORTB &=~(1 << PB5);
  delay(400);
  EICRA|=(1<<ISC00);w=0;i=0;times0=micros();times1=micros();
  EICRA|=(1<<ISC01);EIMSK |= (1<<INT0);}
  }

ISR(INT0_vect){
  if(i>1){i=0;w=1;}
  if(i==0){EICRA&=~(1<<ISC01);EICRA|=(1<<ISC00);
  times0=micros();t1=micros()-times1;}
  if(i==1){
  times1=micros();t0=micros()-times0;}
  i++;}


ДОРАБОТКА

Для увеличения точности и стабильности показаний измерителя скважности и длительности импульсов можно подавать тактовые импульсы с внешнего кварцевого генератора.

В скетч внесен необходимы код для работы с внешнем кварцевым генератором:

#define HZ 12 

#include <Wire.h>
#include <OLED_I2C.h>           // http://rcl-radio.ru/wp-content/uploads/2022/01/OLED_I2C.zip
 OLED  myOLED(SDA, SCL, 8);
 extern uint8_t SmallFont[];
 char i;
 unsigned long times0,times1,t0,t1,tic,f;
 int w=1;

void setup(){
  Serial.begin(9600);
  Wire.begin();
  Wire.setClock(50000L);
  delay(300);
  myOLED.begin();
  myOLED.setBrightness(100);
  DDRB |= PB5; // D13 ARUINO > OUTPUT
  DDRD &= ~(1 << 2);  // D2 ARDUINO > INPUT (INT0)
  EICRA |= (1<<ISC00); // любое изменение на INT0
  PORTD |= (1 << PD5); // подтягивающий резистор на PD5 (вход T1)
  EIMSK |= (1<<INT0); // разрешить внешние прерывания INT0
  noInterrupts();
// TIMER_1 INPUT T1
  TCCR1A = 0;TCCR1B = 0;TCNT1=0;
  TCCR1B = (1 << CS12) | (1 << CS11) | (1 << CS10);
  TIMSK1 = (1 << TOIE1);
  TCKCSR = (1 << F2XEN) | (1 << TC2XS1);
  interrupts();
  }

void loop(){
  if(w==1){
  EIMSK &=~ (1<<INT0);
  PORTB |=(1 << PB5);
  Serial.print("T1 ");Serial.print(t0/(1000.0*HZ),3);Serial.println(" mS");
  Serial.print("T2 ");Serial.print(t1/(1000.0*HZ),3);Serial.println(" mS");
  Serial.print("T  ");Serial.print((t1+t0)/(1000.0*HZ),3);Serial.println(" mS");
  Serial.print("F  ");Serial.print((1000000.0*HZ)/(t1+t0),3);Serial.println(" Hz");
  Serial.println();
  //////////////////////
  myOLED.clrScr();
  myOLED.setFont(SmallFont);
  myOLED.print(F("T1"),LEFT,0);myOLED.printNumF(t0/(1000.0*HZ),3, 30, 0);myOLED.print(F("mS"), RIGHT, 0);
  myOLED.print(F("T2"),LEFT,10);myOLED.printNumF(t1/(1000.0*HZ),3, 30, 10);myOLED.print(F("mS"), RIGHT, 10);
  myOLED.print(F("T "),LEFT,20);myOLED.printNumF((t1+t0)/(1000.0*HZ),3, 30, 20);myOLED.print(F("mS"), RIGHT, 20);
  myOLED.print(F("F "),LEFT,30);myOLED.printNumF((1000000.0*HZ)/(t1+t0),3, 30, 30);myOLED.print(F("Hz"), RIGHT, 30);
  ///////////
  myOLED.drawLine(0, 40, 128, 40);
  float t_dl = t0;
  float t_sk = t1;
  float t_pr = t0+t1;
  myOLED.drawLine(0, 60, 5, 60);
  myOLED.drawLine(5, 60, 5, 45);
  myOLED.drawLine(5, 45, 5+(t_dl/t_pr)*120, 45);
  myOLED.drawLine(5+(t_dl/t_pr)*120, 60, 5+(t_dl/t_pr)*120, 45);
  myOLED.drawLine(5+(t_dl/t_pr)*120, 60, 5+(t_dl/t_pr)*120+(t_sk/t_pr)*120, 60);
  ///////////
  myOLED.update();
  PORTB &=~(1 << PB5);
  delay(400);
  w=0;i=0;f=tic*0xFFFF+TCNT1;times0=f;times1=f;
  EICRA|=(1<<ISC01);EICRA|=(1<<ISC00);EIMSK |= (1<<INT0);}
  }

ISR(INT0_vect){
  if(i>1){i=0;w=1;}
  if(i==0){EICRA&=~(1<<ISC01);EICRA|=(1<<ISC00);
  f=tic*0xFFFF+TCNT1;
  times0=f;t1=f-times1;}
  if(i==1){
  f=(tic*0xFFFF+TCNT1);
  times1=f;t0=f-times0;}
  i++;}

ISR(TIMER1_OVF_vect) {tic++;}  

В скетче необходимо указать частоту внешнего кварцевого генератора:

#define HZ 12 // 12 МГц

Как и в первом варианте измерителя, в мониторе порта можно видеть результаты измерения:

В качестве внешнего генератора я использовал тактовый генератор IQX0100C 12,000MHz. Генератор должен выдавать импульсы уровня TTL с частотой от 8 до 20 МГц.

Форум — http://forum.rcl-radio.ru/viewtopic.php?id=574

Добавить комментарий

Войти с помощью: