| Ваш IP: 100.26.179.251 | Online(18) - гости: 7, боты: 11 | Загрузка сервера: 0.22 ::::::::::::

STM32 — осциллограф (Arduino IDE)

На рисунке показана схема простого осциллографа (пробник) основанного на микроконтроллере STM32F103C. Осциллограф имеет минимальный набор внешних компонентов, прост в сборке. Максимальное входное напряжение (только положительной полярности) 6,6 В и может быть увеличено применением внешнего делителя напряжения. Так АЦП STM32F103C 12 бит, это позволило сделать программный умножитель входного сигнала, без существенный потери качества осциллограммы.

При измерении напряжения более 3,3 В, включается делитель напряжения (вручную или автоматически). Управление осциллографом осуществляется при помощи 4-х кнопок. На экран выводятся показания амплитуды входного сигнала, множитель сигнала, длительность одного деления сетки и курсор синхронизации.

1 кГц

Кнопками UP и WOWN можно поменять длительность развертки, множитель входного сигнала и уровень синхронизации. Режимы настроек меняются кнопкой SET.

При нажатии на кнопку HOLD включается режим остановки осциллограммы, кнопками UP и WOWN можно перемещать по горизонтали осциллограмму. Нажимая на кнопку SET поочередно активируются курсоры измерения напряжения и длительности.

Тест полосы пропускания

Максимальная длительность развертки 100 Гц

Максимальная длительность развертки 100 Гц

1000 Гц

10.0 кГц

50,0 кГц

100,0 кГц

100,0 кГц (меандр)

200,0 кГц (меандр)

минимальная длительность развертки

400,0 кГц (меандр)

минимальная длительность развертки

500,0 кГц (меандр)

минимальная длительность развертки

100,0 кГц (синус)

минимальная длительность развертки

200,0 кГц (синус)

минимальная длительность развертки

#include "SPI.h"
#include <EEPROM.h>
#include <Adafruit_GFX_AS.h>   // https://rcl-radio.ru/wp-content/uploads/2020/06/Adafruit_GFX.zip
#include <Adafruit_ILI9341_STM.h>
#include <STM32ADC.h>
#include <HardwareTimer.h> 
 STM32ADC myADC(ADC1);
 uint8 pin = PA0;
 volatile static bool dma1_ch1_Active;
 #define maxSamples 1000
 uint16_t buffer[maxSamples]; 
 uint16 dataPoints[maxSamples]; 
 
#define TFT_CS         PB1                 
#define TFT_DC         PB10            
#define TFT_RST        PB11
  Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST); // Mosi - PA7, SCK - PA5
 
byte data[1000],data_old[1000];
int setting,hold_set,i,x,y,i2,u_max,u_min,minn,u_sinh,mn=2,raz,per,razv,sinhro;
int u1,u2,t1,t2,zap,ux=1,uxx=1,fun;
long h0,h1;
long times,times1,hhh,times2,times3,tim;
byte hold,www,w=1,w1=1,w2=1,w3=1,w4=1,link,w5=1,b1=1,b2=1;
String raz_x;
float k1,k2,del=1;
 
int data1[1000];
 
 
void setup() {
 Serial.begin(115200);
 EEPROM.init(0x801F000,0x801F800,0x400);// 1024 byte
 pinMode(PA0, INPUT_ANALOG);
 pinMode(PB12,INPUT_PULLUP);// HOLD
 pinMode(PB13,INPUT_PULLUP);//+
 pinMode(PB14,INPUT_PULLUP);//-
 pinMode(PB15,INPUT_PULLUP);// SET
 tft.begin();tft.setRotation(1);
 tft.fillScreen(ILI9341_BLACK); 
 razv=EEPROM.read(0);
 sinhro=EEPROM.read(1);
 
 
ADC1->regs->CR1 = 0; // Обнулить регистр управления
ADC1->regs->SQR1 = 0; // Обнулить регистр SQR1
ADC1->regs->CR2 |= ADC_CR2_CAL; // Пуск калибровки
while (!(ADC1->regs->CR2 & ADC_CR2_CAL)){}; 
 
}
 
void loop() {
 
if(digitalRead(PB15)==LOW&&hold==0){w=1;w1=1;b1=1;b2=0;setting++;if(setting>2){setting=0;}delay(300);}
if(digitalRead(PB15)==LOW&&hold==1){w=1;w2=1;w4=1;hold_set++;if(hold_set>4){hold_set=0;}delay(300); }
 
//////  TFT  //////////////////////////////////////////
  tft.setCursor(295, 0);
  tft.setTextColor(ILI9341_WHITE);  tft.setTextSize(1);
  //////////////////// HOLD ON OFF ///////////////////////////////////////////
 if(digitalRead(PB12)==LOW&&hold==0){hold=1;w2=1;w4=1;link=1;setting=0;delay(300);}  
 if(digitalRead(PB12)==LOW&&hold==1){hold=0;www=1;b2=0;hold_set=0;delay(300);}
 
 if(link==1){link=0;tft.fillRect(170,0,100,30,ILI9341_BLACK);}
 if(hold==0){tft.setCursor(170, 0);tft.print("OSCILLOSCOPE");tft.setCursor(170, 10);tft.print("VERSION 0.1");tft.setCursor(170, 20);tft.print("RCL-RADIO.RU");}
 
razmer();
 if(hold==0){
 if(setting==0){
  if(digitalRead(PB14)==LOW&&hold==0){razv++;if(razv>12){razv=12;}EEPROM.update(0,razv);delay(300);b2=1;w3=1;w=1;w1=1;u1=0;u2=0;t1=0;t2=0;}
  if(digitalRead(PB13)==LOW&&hold==0){razv--;if(razv<0){razv=0;}EEPROM.update(0,razv);delay(300);b2=1;w3=1;w=1;w1=1;w5=1;}
  razmer();
  if(b2<5){b2++;tft.fillRect(80,0,65,8,ILI9341_RED);tft.setCursor(90, 0);tft.print((float)times3/10/mn,1);tft.print(" uS");}
  }
 
 if(setting==1){
  if(digitalRead(PB14)==LOW&&hold==0){uxx++;if(uxx>5){uxx=5;}del=1;ux=uxx;delay(300);w=1;w1=1;u1=0;u2=0;t1=0;t2=0;}
  if(digitalRead(PB13)==LOW&&hold==0){uxx--;ux=uxx;if(uxx<=0){del=2;uxx=0;ux=1;}delay(300);w=1;w1=1;}
  if(w1==1){w1=0; tft.fillRect(85,10,50,8,ILI9341_RED);tft.setCursor(90, 10);tft.print("U x ");if(uxx==0){tft.print(0.5,1);}else{tft.print(uxx);}}
  }
 
 if(setting==2){
  if(digitalRead(PB13)==LOW&&hold==0){sinhro++;if(sinhro>200){sinhro=200;}EEPROM.update(1,sinhro);delay(10);w=1;w1=1;}
  if(digitalRead(PB14)==LOW&&hold==0){sinhro--;if(sinhro<0){sinhro=0;}EEPROM.update(1,sinhro);delay(10);w=1;w1=1;}
    tft.fillRect(0, 230-sinhro+3, 3, 3, ILI9341_BLACK);tft.fillRect(0, 230-sinhro, 3, 3, 0xFFFFDD);tft.fillRect(0, 230-sinhro-3, 3, 3, ILI9341_BLACK);
 if(w1==1){w1=0;tft.fillRect(85,20,50,8,ILI9341_RED);tft.setCursor(90, 20);tft.print("SINH");}
 }
 }
 
  if(hold==0&&w==1){w=0;
  if(setting!=0){tft.fillRect(80,0,65,8,ILI9341_BLACK);tft.setCursor(90, 0);tft.print((float)times3/10/mn,1);tft.print(" uS");}
  if(setting!=1){tft.fillRect(70,10,65,8,ILI9341_BLACK);tft.setCursor(90, 10);tft.print("U x ");if(uxx==0){tft.print(0.5,1);}else{tft.print(uxx);}}
  if(setting!=2){tft.fillRect(70,20,65,8,ILI9341_BLACK);tft.setCursor(90, 20);tft.print("SINH");
  tft.fillRect(0, 230-sinhro+3, 3, 3, ILI9341_BLACK);tft.fillRect(0, 230-sinhro, 3, 3, 0x333333);tft.fillRect(0, 230-sinhro-3, 3, 3, ILI9341_BLACK);
  }}
 
 
if(uxx==0){pinMode(PA2,OUTPUT);digitalWrite(PA2,LOW);}
if(uxx>0){pinMode(PA2,INPUT);analogRead(PA2);}
 
 
//////////////// HOLD SET ////////////////////////////////////////////////////////////////////////////////
 if(hold==1){
  if(w4==1){w4=0;
  tft.fillRect(80,0,65,8,ILI9341_BLUE);tft.setCursor(90, 0);tft.print((float)times3/10/mn,1);;tft.print(" uS");tft.fillRect(70,10,65,8,ILI9341_BLACK);
  tft.fillRect(0, 230-sinhro, 3, 3, 0x000000);tft.setCursor(90, 10);tft.print("U x ");tft.fillRect(70,20,65,8,ILI9341_BLACK);if(uxx==0){tft.print(0.5,1);}else{tft.print(uxx);}}
 
  tft.setCursor(295, 0);
  if(digitalRead(PB14)==LOW&&hold_set==0){i2+=2;if(i2>290){i2=290;}delay(50);
  tft.drawLine(0, u1+30,320, u1+30,  0x000000);
  tft.drawLine(0, 230-u2,320, 230-u2,  0x000000);
  tft.drawLine(t1,   230, t1, 30,  0x000000);
  tft.drawLine(318-t2,   230, 318-t2, 30,  0x000000);
 
  u1=0;u2=0;t1=0;t2=0;}
  if(digitalRead(PB13)==LOW&&hold_set==0){i2-=2;if(i2<0){i2=0;}delay(50);
  tft.drawLine(0, u1+30,320, u1+30, 0x000000);
  tft.drawLine(0, 230-u2,320, 230-u2,  0x000000);
  tft.drawLine(t1,   230, t1, 30,  0x000000);
  tft.drawLine(318-t2,   230, 318-t2, 30,  0x000000);
 
  u1=0;u2=0;t1=0;t2=0;}
  if(hold==1){tft.fillRect(i2,235,4,3,ILI9341_BLACK);tft.fillRect(i2+2,235,30,3,ILI9341_GREEN);tft.fillRect(i2+32,235,4,3,ILI9341_BLACK);}
  if(hold==0){tft.fillRect(295,0,25,8,ILI9341_RED);tft.fillRect(0,235,240,3,ILI9341_BLACK);}else{tft.print("HOLD");}
 
  if(digitalRead(PB14)==LOW&&hold==1&&hold_set==1){if(u1<199-u2){u1++;}w2=1;if(u1>200){u1=200;}delay(30);w=1;w1=1;}
  if(digitalRead(PB13)==LOW&&hold==1&&hold_set==1){if(u1<201-u2){u1--;}w2=1;if(u1<0){u1=0;}delay(30);w=1;w1=1;}
  if(digitalRead(PB13)==LOW&&hold==1&&hold_set==2){if(u2<199-u1){u2++;}w2=1;if(u2>200){u2=200;}delay(30);w=1;w1=1;}
  if(digitalRead(PB14)==LOW&&hold==1&&hold_set==2){if(u2<201-u1){u2--;}w2=1;if(u2<0){u2=0;}delay(30);w=1;w1=1;}
 
  if(digitalRead(PB14)==LOW&&hold==1&&hold_set==3){if(t1<319-t2){t1++;};w2=1;if(t1>320){t1=320;}delay(30);w=1;w1=1;}
  if(digitalRead(PB13)==LOW&&hold==1&&hold_set==3){if(t1<321-t2){t1--;}w2=1;if(t1<0){t1=0;}delay(30);w=1;w1=1;}
  if(digitalRead(PB13)==LOW&&hold==1&&hold_set==4){if(t2<319-t1){t2++;}w2=1;if(t2>320){t2=320;}delay(30);w=1;w1=1;}
  if(digitalRead(PB14)==LOW&&hold==1&&hold_set==4){if(t2<321-t1){t2--;}w2=1;if(t2<0){t2=0;}delay(30);w=1;w1=1;}
 
 if(w2==1){w2=0;
   tft.drawLine(0, u1-1+30,320, u1-1+30,  ILI9341_BLACK);if(hold_set==1){tft.drawLine(0, u1+30,320, u1+30,  0xFFDAB9);}else{tft.drawLine(0, u1+30,320, u1+30,  0x222222);} tft.drawLine(0, u1+1+30,320, u1+1+30,  ILI9341_BLACK);
   tft.drawLine(0, 230-u2-1,320, 230-u2-1,  ILI9341_BLACK);if(hold_set==2){tft.drawLine(0, 230-u2,320, 230-u2,  0xFFDAB9);}else{tft.drawLine(0, 230-u2,320, 230-u2,  0x222222);} tft.drawLine(0, 230-u2+1,320, 230-u2+1,  ILI9341_BLACK);
   tft.drawLine(t1-1, 230, t1-1, 30,  ILI9341_BLACK);if(hold_set==3){tft.drawLine(t1,   230, t1, 30,  0xFFDAB9);}else{tft.drawLine(t1,   230, t1, 30,  0x222222);}tft.drawLine(t1+1, 230, t1+1, 30,  ILI9341_BLACK);
   tft.drawLine(318-t2-1, 230, 318-t2-1, 30,  ILI9341_BLACK);if(hold_set==4){tft.drawLine(318-t2,   230, 318-t2, 30,  0xFFDAB9);}else{{tft.drawLine(318-t2,   230, 318-t2, 30,  0x222222);}}tft.drawLine(318-t2+1, 230, 318-t2+1, 30,  ILI9341_BLACK);
 
   if(hold_set==1){tft.fillRect(150,0,55,8,ILI9341_RED);}else{tft.fillRect(150,0,55,8,ILI9341_BLACK);}
   if(hold_set==2){tft.fillRect(150,10,55,8,ILI9341_RED);}else{tft.fillRect(150,10,55,8,ILI9341_BLACK);}
   if(hold_set==3){tft.fillRect(220,0,60,8,ILI9341_RED);}else{tft.fillRect(220,0,60,8,ILI9341_BLACK);}
   if(hold_set==4){tft.fillRect(220,10,60,8,ILI9341_RED);}else{tft.fillRect(220,10,60,8,ILI9341_BLACK);}
 
 
    tft.fillRect(150,20,55,8,ILI9341_BLACK);
    tft.setCursor(150, 0);tft.print("U1 = ");tft.print((3.3-u1*0.0165)/ux*del,2);
    tft.setCursor(150, 10);tft.print("U2 = ");tft.print((abs(u2*0.0165))/ux*del,2);
    tft.setCursor(150, 20);tft.print("U  = ");tft.print(((3.3-u1*0.0165)-abs(u2*0.0165))/ux*del,2);
 
    tft.fillRect(220,20,65,8,ILI9341_BLACK);
    if(razv<6){zap=1;}else{zap=0;}
    tft.setCursor(220, 0);tft.print("T1 = ");tft.print(t1*(float)times3/1000/mn,zap);
    tft.setCursor(220, 10);tft.print("T2 = ");tft.print(((float)times3/3.125-t2*(float)times3/1000)/mn,zap);
    tft.setCursor(220, 20);tft.print("T  = ");tft.print(((((float)times3/3.125-t2*(float)times3/1000))/mn-((t1*(float)times3/1000))/mn),zap);
    tft.fillRect(280,20,30,8,ILI9341_BLACK);tft.print(" uS");
 }} 
////////// END HOLD SET ///////////////////////////////////////////////////////////////////////////////////
  setka();
 
  if(hold==0){DMA();if(dma1_ch1_Active == 0){for(int x=0; x<maxSamples; x++){data[x]=map(buffer[x],0,4095/ux,0,200);}}u1=0;u2=0;t1=0;t2=0;}
  arr();
 
 if(hold==0){i2=0;for(i=1;i<1000;i++){if(data[i+5]>sinhro&&data[i+3]<sinhro){fun=i;if(fun>680){fun=0;}i=2000;}}
  for(i=0;i<1000-fun;i++){data1[i]=data[fun+i];}i=0;}
 
 while(i<320){ 
 tft.drawLine(i*mn, 230-data_old[i],i*mn+mn-1, 230-data_old[i+1], ILI9341_BLACK);
 tft.drawLine(i*mn, 230-data1[i+i2],i*mn+mn-1, 230-data1[i+1+i2],  ILI9341_RED);i++;}i=0;
 while(i<639){data_old[i]=data1[i+i2];i++;}i=0; 
 if((mn>1&&w1==1&&hold==0&&setting==0)||www==1){www=0;w=1;w1=0;tft.fillScreen(ILI9341_BLACK);}
 if(razv==2&&w5==1){w5=0;w=1;w1=0;tft.fillScreen(ILI9341_BLACK);}
}
 
void DMA(){
 
     switch(per){
       case 0: rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_2); break;
       case 1: rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_4); break;
       case 2: rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_6); break;
       case 3: rcc_set_prescaler(RCC_PRESCALER_ADC, RCC_ADCPRE_PCLK_DIV_8); break;
      }
     switch (raz) {
      case 0: adc_set_sample_rate(ADC1, ADC_SMPR_1_5); break;
      case 1: adc_set_sample_rate(ADC1, ADC_SMPR_7_5); break;
      case 2: adc_set_sample_rate(ADC1, ADC_SMPR_13_5); break;
      case 3: adc_set_sample_rate(ADC1, ADC_SMPR_28_5); break;
      case 4: adc_set_sample_rate(ADC1, ADC_SMPR_41_5); break;
      case 5: adc_set_sample_rate(ADC1, ADC_SMPR_55_5); break;
      case 6: adc_set_sample_rate(ADC1, ADC_SMPR_71_5); break;
      case 7: adc_set_sample_rate(ADC1, ADC_SMPR_239_5); break;
       } 
 
  adc_set_reg_seqlen(ADC1, 1);
  ADC1->regs->SQR3 = PIN_MAP[pin].adc_channel;      
  ADC1->regs->CR2 |= ADC_CR2_CONT;
  ADC1->regs->CR2 |= ADC_CR2_EXTSEL;   
  ADC1->regs->CR2 |= ADC_CR2_SWSTART; 
 
  dma_init(DMA1);  
  dma_attach_interrupt(DMA1, DMA_CH1, DMA1_CH1_Event);
  myADC.setDMA(buffer, maxSamples, (DMA_MINC_MODE | DMA_TRNS_CMPLT), DMA1_CH1_Event);
  dma1_ch1_Active = 1;
 
 
  times3 = micros();
  dma_enable(DMA1, DMA_CH1); 
  while (dma1_ch1_Active == 1);
  dma_disable(DMA1, DMA_CH1); 
  times3 = micros() - times3;
}
 
 
void setka(){ 
 for(y=30;y<240;y=y+50){for(x=10;x<320;x=x+5){tft.drawPixel(x, y, ILI9341_DARKGREY);}}  
 for(x=0;x<320;x=x+64){for(y=40;y<240;y=y+10){tft.drawPixel(x, y, ILI9341_DARKGREY);}}}
 
static void DMA1_CH1_Event(){dma1_ch1_Active = 0;}
 
void arr(){
   ///// U max max
 if(millis()-times>500){u_max=0;u_min=4100;w3=1;
 tft.fillRect(40,0,30,28,ILI9341_BLACK);
  for(int mmm=0;mmm<640;mmm++){u_min=min(u_min,buffer[mmm]);u_max=max(u_max,buffer[mmm]);}
 tft.setCursor(0, 0);tft.print("Vmax = ");tft.print(u_max*3.3/4095*del,2);
 tft.setCursor(0, 10);tft.print("Vmin = ");tft.print(u_min*3.3/4095*del,2);
 u_sinh = u_max-u_min;
 tft.setCursor(0, 20);tft.print("Vpp  = ");tft.print(u_sinh*3.3/4095*del,2);
 times=millis();
 if(u_max*3.3/4095>=3.3){uxx=0;ux=1;del=2;w3=1;tft.fillRect(70,10,65,8,ILI9341_BLACK);tft.setCursor(90, 10);tft.print("U x ");tft.print(0.5,1);}}
  }
 
void razmer(){
     switch(razv){
    case 0: mn=4;      per=0;raz=0;;break;  
    case 1: mn=2;      per=0;raz=0;;break; 
    case 2: mn=1;      per=0;raz=0;break; 
    case 3: mn=1;      per=0;raz=1;break;
    case 4: mn=1;      per=1;raz=1;break; 
    case 5: mn=1;      per=2;raz=1;break; 
    case 6: mn=1;      per=3;raz=1;break; 
    case 7: mn=1;      per=3;raz=2;break; 
    case 8: mn=1;      per=3;raz=3;break; 
    case 9: mn=1;      per=3;raz=4;break; 
    case 10: mn=1;     per=3;raz=5;break;
    case 11: mn=1;     per=3;raz=6;break;
    case 12: mn=1;     per=3;raz=7;break;
    }
  }

Поддержка платы STM32 в Arduino IDE — https://rcl-radio.ru/?p=68376

STM32 + TFT-дисплей SPI 320×240 (ILI9341C)

STM32 Arduino IDE

Комментарии

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

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

Случайные статьи

  • Узел настройки УКВ-ЧМ приемника

    Узел настройки УКВ_ЧМ приемника представляет собой синтезатор напряжения для электронной настройки УКВ_ЧМ приемника и как дополнительное уст-во — электронную линейную шкалу напряжения для контроля напряжения подаваемого на варикапы приемника. Напряжение настройки приемника устанавливается при помощи полевого транзистора VT1, в его затворной цепи включен С1, при нажатии S1 или S2 С1 …Подробнее...
  • Стерео усилитель класса D 2*25Вт на базе TDA7490

    Стерео усилитель класса D 2*25Вт на базе TDA7490

    Микросхема TDA7490 имеет защиту от перенапряжения, тепловую и защиту от КЗ, так же микросхема имеет встроенные функции MUTE и STAND-BY. Усилитель на TDA7490 имеет следующие технические характеристики: Напряжение питания от +/-10В до +/-25В (номинальное напряжение +/-21В) Ток покоя от 70 до 120мА в зависимости от  напряжения питания Выходная мощность 25Вт …Подробнее...
  • Усилитель мощности звуковой частоты класса D на ИМС MAX9709

    Усилитель мощности звуковой частоты класса D на ИМС MAX9709

    Усилитель мощности звуковой частоты класса D на ИМС MAX9709 обеспечивает выходную мощность до 25Вт на канал (стерео) при нагрузке 8 Ом и 50Вт в режиме моно при нагрузке 4 Ом. ИМС MAX9709 обеспечивает высокую производительность (КПД 87%), при этом используется небольшой радиатор охлаждения. Напряжение питания усилителя от 10 до 22В. MAX9709  имеет …Подробнее...
  • Простой испытатель тиристоров

    Простой испытатель тиристоров

    Из подручных радиоэлементов можно собрать простой испытатель тиристоров, который состоит из трансформатора со вторичной обмоткой на 6,3В (0,5А), диода, конденсатора, лампы и трех переключателей. Выбор постоянного или переменного тока осуществляется переключателем SA2. Электроды тиристора подключаются при помощи зажимов, индикатор служит лампа накаливания 6,3Вх0,28А. Для проверки тиристора постоянным током переведите переключатель …Подробнее...
  • УМЗЧ на 50Вт на полевых MOSFET транзисторах

    УМЗЧ на 50Вт на полевых MOSFET транзисторах

    На рисунке показана схема 50 Вт усилителя с выходными полевыми MOSFET транзисторами. Первый каскад усилителя представляет собой дифференциальный усилитель на транзисторах VT1 VT2. Второй каскад усилителя состоит из транзисторов VT3 VT4. Оконечный каскад усилителя состоит из МОП-транзисторов IRF530 и IRF9530. Выход усилителя через катушку L1 соединен с нагрузкой 8 Ом. Цепь состоящий …Подробнее...