8-и канальный логический анализатор STM32 (Arduino IDE)

Логический анализатор выполнен на основе микроконтроллера STM32F103C8T6 (отладочная плата), вся информация выводится на TFT-дисплей SPI 320×240 (ILI9341C). Максимальное напряжение подаваемое на входы порта PB8-PB15 STM32F103C8T6 не должно превышать 5 В.

Логический анализатор позволяет отслеживать логическое состояние по 8-и каналом одновременно, а так же измерять временные параметры импульсов. Частотный диапазон от единиц герц до 400 кГц. Память на 3200 точек измерения (10 разверток экрана).

Анализатор имеет три режима работы:

  • AUTO — автоматический режим синхронизации по кану № 0 (PB8)
  • START_1 — режим ожидания, при появлении на входе № 0 лог. 1, анализатор производит один цикл измерения.
  • START_0 — режим ожидания, при появлении на входе № 0 лог. 0, анализатор производит один цикл измерения.

Управление логическим анализатором осуществляется 5-ю кнопками:

  • HOLD — остановка измерения, вывод на экран текущей информации, перезапуск измерения в режиме START_1 и START_0.
  • SET — переключение режимов AUTO, START_1, START_0.
  • UP и DOWN :
    • выбор длительности развертки в режиме AUTO
    • перемещение изображения импульсов в режиме HOLD по горизонтали
  • SET_CURSOR — обнуление показаний измерителя временных интервалов.

Измерительный курсор (красная полоса) позволяющий оценивать логическое состояние одновременно по 8-и каналам (вывод на экран лог. состояния в двоичной и шестнадцатеричной системы счисления), курсор активен в режимах AUTO, START_1 и START_0, перемещение импульсов по горизонтали осуществляется кнопками UP и DOWN. Так при нажатии кнопки SET_CURSOR происходит обнуление показаний измерителя временных интервалов.

Сигналы шины I2C 100 кГц

Сигналы шины I2C 100 кГц при минимальной длительности развертки

Сигнал управления RGB (W2812) ленты 800 кГц

Сигналы шины I2C 400 кГц при минимальной длительности развертки

 

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

STM32 Arduino IDE

 

#include <SPI.h>
#include <Adafruit_GFX_AS.h>   // http://rcl-radio.ru/wp-content/uploads/2020/06/Adafruit_GFX.zip
#include <Adafruit_ILI9341_STM.h>
#include <EEPROM.h>
 
 
#define TFT_CS         PA0                 
#define TFT_DC         PA1            
#define TFT_RST        PA2
// MOSI                PA7
// SCK                 PA5
Adafruit_ILI9341_STM tft = Adafruit_ILI9341_STM(TFT_CS, TFT_DC, TFT_RST); 
 
byte data[3200],data_old[3200];
bool stopp=0;
unsigned long times;
int i,i2,i3,razv,delays,hh;
byte w=1,w1,st,x,z,mn=8,sett;
 
void setup() {
 Serial.begin(9600);
 EEPROM.init(0x801F000,0x801F800,0x400);// 1024 byte 
 pinMode(PA3,INPUT_PULLUP);// HOLD 
 pinMode(PB0,INPUT_PULLUP);// +++
 pinMode(PB1,INPUT_PULLUP);// --- 
 pinMode(PA4,INPUT_PULLUP);// SET 
 pinMode(PB4,INPUT_PULLUP);// SET_CURSOR 
 tft.begin();tft.setRotation(1);tft.fillScreen(ILI9341_BLACK);
 polos();
 tft.setCursor(180, 5);tft.print("LOGIC ANALYZER");
 tft.setCursor(180, 20);tft.print("RCL-RADIO.RU");
 GPIOB-> regs-> CRH = 0x88888888; // INPUT PB8...PB15
 razv = EEPROM.read(0);
 
}
 
void loop() {
  ////////// SET 
 if(digitalRead(PA4)==LOW){sett++;w=1;w1=1;stopp=0;if(sett>2){sett=0;}delay(200);tft.fillRect(50,0,65,8,ILI9341_BLACK);polos();cif();tft.fillRect(50,10,80,25,ILI9341_BLACK);} 
 
   //////////////////// HOLD ON OFF ///////////////////////////////////////////
 if(digitalRead(PA3)==LOW&&stopp==0){stopp=1;w1=1;polos();cif();tft.fillRect(50,10,80,25,ILI9341_BLACK);delay(300);i2=0;}  
 if(digitalRead(PA3)==LOW&&stopp==1){stopp=0;w1=1;polos();cif();tft.fillRect(50,10,80,25,ILI9341_BLACK);delay(300);i2=0;}
 
 if(digitalRead(PB0)==LOW&&stopp==1){i2++;w1=1;if(i2>2880){i2=2880;}delay(1);}
 if(digitalRead(PB1)==LOW&&stopp==1){i2--;w1=1;if(i2<0){i2=0;}delay(1);}
 
 if(digitalRead(PB4)==LOW){i3=i2;w1=1;delay(200);}
  if(stopp==1&&w1==1){
  tft.fillRect(0,10,60,8,ILI9341_BLACK);tft.setCursor(0, 10);
  //if(digitalRead(PB4)==LOW){i3=i2;delay(200);}
  if(((float)times/10/mn/320*mn)*(i2-i3)>1000){tft.print(((float)times/10000/mn/320*mn)*(i2-i3),1);tft.print(" mS  ");}
  else{tft.print(((float)times/10/mn/320*mn)*(i2-i3),1);tft.print(" uS  ");}
  }
  if(stopp==0){tft.fillRect(0,10,65,8,ILI9341_BLACK);}
 
 
 if(stopp==1){tft.fillRect(i2/10,235,4,3,ILI9341_BLACK);tft.fillRect(i2/10+2,235,30,3,ILI9341_GREEN);tft.fillRect(i2/10+32,235,4,3,ILI9341_BLACK);}
 if(stopp==0&&w1==1){tft.fillRect(0,235,320,3,ILI9341_BLACK);}
 tft.setCursor(0, 25);
 if(stopp==0){tft.fillRect(295,0,25,8,ILI9341_BLACK);tft.fillRect(0,25,65,8,ILI9341_BLACK);}else{tft.print("HOLD");}
 
 ///// SET = 0 //////////////////////////////////////////////////////////////
 if(digitalRead(PB0)==LOW&&stopp==0){razv++;w=1;if(razv>12){razv=12;}EEPROM.update(0,razv);delay(300);}
 if(digitalRead(PB1)==LOW&&stopp==0){razv--;w=1;if(razv<0){razv=0;}EEPROM.update(0,razv);delay(300);}
 
 switch(razv){
   case 0: mn=1;delays=500;break;
   case 1: mn=1;delays=200;break;
   case 2: mn=1;delays=100;break;
   case 3: mn=1;delays=50;break;
   case 4: mn=1;delays=25;break;
   case 5: mn=1;delays=12;break;
   case 6: mn=1;delays=5;break;
   case 7: mn=1;delays=2;break;
   case 8: mn=1;delays=1;break;
   case 9: mn=1;delays=0;break;
  case 10: mn=2;delays=0;break;
  case 11: mn=4;delays=0;break;
  case 12: mn=8;delays=0;break;
  }
   sinhr();
 
 
///////////// измерение //////////////////////////
  if(stopp==0&&delays>0){
  times=micros();
  i=0;while(i<3200){i++;delay_us(delays);data[i] = (GPIOB-> regs-> IDR & 0b1111111100000000) >> 8;}
  times=micros()-times;}
 
  if(stopp==0&&delays==0){
  times=micros();
  i=0;while(i<3200){i++;data[i] = (GPIOB-> regs-> IDR & 0b1111111100000000) >> 8;}
  times=micros()-times;}
  if(sett>0){stopp=1;}
////////////// end ////////////////////////////////
 
 
  if(w==1){w=0;polos();
  tft.fillRect(0,0,65,8,ILI9341_BLACK);tft.setCursor(0, 0);
  if(times/10/mn>1000){tft.print((float)times/10/mn/1000,2);tft.print(" mS  ");}
  else{tft.print((float)times/10/mn,1);tft.print(" uS  ");}
 
  cif();
 
  tft.setCursor(65, 0);
  if(sett==0){tft.print("AUTO   ");}
  if(sett==1){tft.print("START_1");}
  if(sett==2){tft.print("START_0");}
  }
 
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 55-((data_old[i]>>0)&1)*15,i*mn-x, 55-((data_old[i+z]>>0)&1)*15, 0x000F);
 tft.drawLine(i*mn-x, 55-((data[i+i2]>>0)&1)*15,i*mn-x, 55-((data[i+z+i2]>>0)&1)*15,  ILI9341_WHITE);}}
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 80-((data_old[i]>>1)&1)*15,i*mn-x, 80-((data_old[i+z]>>1)&1)*15, 0x000A);
 tft.drawLine(i*mn-x, 80-((data[i+i2]>>1)&1)*15,i*mn-x, 80-((data[i+z+i2]>>1)&1)*15,  ILI9341_WHITE);}}
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 105-((data_old[i]>>2)&1)*15,i*mn-x, 105-((data_old[i+z]>>2)&1)*15, 0x000F);
 tft.drawLine(i*mn-x, 105-((data[i+i2]>>2)&1)*15,i*mn-x, 105-((data[i+z+i2]>>2)&1)*15,  ILI9341_WHITE);}} 
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 130-((data_old[i]>>3)&1)*15,i*mn-x, 130-((data_old[i+z]>>3)&1)*15, 0x000A);
 tft.drawLine(i*mn-x, 130-((data[i+i2]>>3)&1)*15,i*mn-x, 130-((data[i+z+i2]>>3)&1)*15,  ILI9341_WHITE);}} 
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 155-((data_old[i]>>4)&1)*15,i*mn-x, 155-((data_old[i+z]>>4)&1)*15, 0x000F);
 tft.drawLine(i*mn-x, 155-((data[i+i2]>>4)&1)*15,i*mn-x, 155-((data[i+z+i2]>>4)&1)*15,  ILI9341_WHITE);}}  
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 180-((data_old[i]>>5)&1)*15,i*mn-x, 180-((data_old[i+z]>>5)&1)*15, 0x000A);
 tft.drawLine(i*mn-x, 180-((data[i+i2]>>5)&1)*15,i*mn-x, 180-((data[i+z+i2]>>5)&1)*15,  ILI9341_WHITE);}} 
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 205-((data_old[i]>>6)&1)*15,i*mn-x, 205-((data_old[i+z]>>6)&1)*15, 0x000F);
 tft.drawLine(i*mn-x, 205-((data[i+i2]>>6)&1)*15,i*mn-x, 205-((data[i+z+i2]>>6)&1)*15,  ILI9341_WHITE);}} 
 
 i=10/mn;while(i<320){i++;
 for(x=0;x<mn;x++){if(x==0){z=1;}else{z=0;}
 tft.drawLine(i*mn-x, 230-((data_old[i]>>7)&1)*15,i*mn-x, 230-((data_old[i+z]>>7)&1)*15, 0x000A);
 tft.drawLine(i*mn-x, 230-((data[i+i2]>>7)&1)*15,i*mn-x, 230-((data[i+z+i2]>>7)&1)*15,  ILI9341_WHITE);}} 
 
i=0;while(i<3199){i++;data_old[i]=data[i+i2];}
 
 
  if(stopp==1&&w1==1){w1=0;
  tft.fillRect(50,10,75,25,ILI9341_BLACK);
  if(mn<=2){tft.setCursor(65, 10);tft.print("0B");tft.print(data[i2+60/mn],BIN);}
  if(mn>2){tft.setCursor(65, 10);tft.print("0B");tft.print(data[i2+60/mn+1],BIN);}
  if(mn<=2){tft.setCursor(65, 25);tft.print("0X");tft.print(data[i2+60/mn],HEX);}
  if(mn>2){tft.setCursor(65, 25);tft.print("0X");tft.print(data[i2+60/mn+1],HEX);}
  tft.drawLine(60, 10,60, 230,  ILI9341_RED);
  tft.drawLine(60, 20,125, 20,  ILI9341_RED);
  }
  }
 
void polos(){
 tft.fillRect(0,210,320,25,0x000A);
 tft.fillRect(0,185,320,25,0x000F);
 tft.fillRect(0,160,320,25,0x000A);
 tft.fillRect(0,135,320,25,0x000F);
 tft.fillRect(0,110,320,25,0x000A);
 tft.fillRect(0,85,320,25,0x000F);
 tft.fillRect(0,60,320,25,0x000A);
 tft.fillRect(0,35,320,25,0x000F);
  }  
 
void sinhr(){
  if(sett==0){
  while(((GPIOB-> regs-> IDR & 0b0000000100000000) >> 8)==1){hh++;delay_us(1);if(hh>1000){hh=0;break;}}
  while(((GPIOB-> regs-> IDR & 0b0000000100000000) >> 8)==0){hh++;delay_us(1);if(hh>1000){hh=0;break;}}
  while(((GPIOB-> regs-> IDR & 0b0000000100000000) >> 8)==1){hh++;delay_us(1);if(hh>1000){hh=0;break;}}
  }
  if(sett==1){
  while(((GPIOB-> regs-> IDR & 0b0000000100000000) >> 8)==0){zap();}}
  if(sett==2){
  while(((GPIOB-> regs-> IDR & 0b0000000100000000) >> 8)==1){zap();}}
  }
 
void cif(){ for(byte cc=0;cc<8;cc++){tft.setCursor(0, 45+cc*25);tft.print(cc);}}
 
void zap(){
if(digitalRead(PA4)==LOW){sett++;w=1;w1=1;stopp=0;if(sett>2){sett=0;}delay(200);tft.fillRect(50,0,65,8,ILI9341_BLACK);polos();cif();tft.fillRect(50,10,80,25,ILI9341_BLACK);}  
if(digitalRead(PA3)==LOW&&stopp==1){stopp=0;w1=1;polos();cif();tft.fillRect(50,10,80,25,ILI9341_BLACK);delay(300);i2=0;}
  tft.setCursor(65, 0);
  if(sett==0){tft.print("AUTO   ");}
  if(sett==1){tft.print("START_1");}
  if(sett==2){tft.print("START_0");}
  }

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

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