Измеритель предназначен для измерения скважности и длительности импульсов уровня 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 МГц
Как и в первом варианте измерителя, в мониторе порта можно видеть результаты измерения:
В качестве внешнего генератора я использовал тактовый генератор IQX0—100C 12,000MHz. Генератор должен выдавать импульсы уровня TTL с частотой от 8 до 20 МГц.