单片机教程网

电脑版
提示:原网页已由神马搜索转码, 内容由www.51hei.com提供.
查看:12786|回复:39
打印上一主题下一主题

arduino TFT彩屏示波器v2.0正式版源程序+电路图

 [复制链接]
跳转到指定楼层
楼主
ID:349565发表于 2019-3-31 15:22|显示全部楼层|只看大图回帖奖励
更新内容
1,增加触屏操作功能,所有操作直接通过触屏操作
2,硬件部分增加负电压采集功能。
3,探头提供x1,x10,x100三档衰减功能.
4,支持DC,AC藕合方式。
5,支持时基调。
6,增加HOLD功能。
演示:下图采集的正玄波为市电通过9V变压器降压后直接采样的波形。
有能力的朋友可以改进一下,最好能发份改进的源码给我。

电路原理图如下:


制作出来的实物图如下:


单片机源程序如下:

  1. #include< Adafruit_GFX.h>
  2. #include< MCUFRIEND_kbv.h>
  3. #include< TouchScreen.h>
  4. MCUFRIEND_kbv tft;

  5. const int XP=7,XM=A1,YP=A2,YM=6; //ID=0x5408
  6. const int TS_LEFT=772,TS_RT=151,TS_TOP=953,TS_BOT=156;
  7. TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);
  8. TSPoint tp;

  9. #define MINPRESSURE 200
  10. #define MAXPRESSURE 1000

  11. // 颜色值:
  12. #define BLACK   0x0000
  13. #define BLUE   0x001F
  14. #define RED     0xF800
  15. #define GREEN   0x07E0
  16. #define CYAN   0x07FF
  17. #define MAGENTA 0xF81F
  18. #define YELLOW  0xFFE0
  19. #define WHITE   0xFFFF
  20. //RGB颜色
  21. #define RGB(r,g,b) (((r&0xF8)<<8)|((g&0xFC)<<3)|(b>>3))
  22. #define GREY     RGB(127, 127, 127)
  23. #define DARKGREY  RGB(64, 64, 64)
  24. #define TURQUOISE RGB(0, 128, 128)
  25. #define PINK     RGB(255, 128, 192)
  26. #define OLIVE     RGB(128, 128, 0)
  27. #define PURPLE   RGB(128, 0, 128)
  28. #define AZURE     RGB(0, 128, 255)
  29. #define ORANGE   RGB(255,128,64)

  30. #define ch1     A5
  31. #define max_buf 321
  32. #define max     320
  33. #define _ms     150
  34. #define vatel   5

  35. int xpos, ypos;
  36. uint8_t PENRADIUS = 1;
  37. uint8_t Orientation = 1;   //屏幕旋转
  38. int i,value;
  39. int time[]={0,7,20,46,102,224,460};
  40. int _adc,_us;
  41. int _id; //点击的按钮id
  42. int buf[max_buf];
  43. int buf_old[max];
  44. bool hold=false;
  45. long t;
  46. int delay_us=0;
  47. int Freq,Cycl,Duty,Pw,V_max,V_min,V_mid,Vpp;
  48. int i1,i2,i3;
  49. int Tv=209;  //触发电压
  50. String sj[]={" x1:1 "," x10:1 ","x100:1"};
  51. int mode=0;
  52. float _Vmax,_Vmin,_Vmid,_Vrms;
  53. int old_Freq,old_Duty;
  54. bool parameter=false;
  55. int adc_i=8;
  56. /*
  57. //主菜单
  58. void man_menu(void){
  59.   tft.fillScreen(BLACK);
  60.   tft.setTextSize(1);
  61.   tft.setTextColor(WHITE, BLACK);
  62.   tft.setCursor(60, 20);
  63.   tft.print("plase select menu");
  64.   
  65.   btn_osc.initButton(&tft,100,60,120,40,WHITE,CYAN,BLACK, "OSC",2);
  66.   btn_pwm.initButton(&tft,100,110,120,40,WHITE,CYAN,BLACK, "PWM",2);
  67.   btn_osc.drawButton(false);
  68.   btn_pwm.drawButton(false);
  69.   while (1) {
  70.    update_button_list(buttons);
  71.    if (btn_osc.justPressed()) {
  72.      btn_osc.drawButton(true);
  73.      osc();
  74.    }

  75.   }
  76. }*/

  77. void setup(void){
  78.   tft.reset();
  79.   tft.begin(0x5408);
  80.   tft.setRotation(Orientation);
  81.   osc();
  82. }

  83. void draw_btn(int x,int y,int w,int h,String lable){
  84.   tft.setTextColor(WHITE, BLUE);
  85.   tft.drawRoundRect(x, y, w, h, 3, RED);
  86.   tft.setCursor(x+3, y+9);
  87.   tft.print(lable);
  88. }

  89. //示波器
  90. void osc(void){
  91.   tft.fillScreen(BLACK);
  92.   tft.fillRect(0, 0, tft.width(), 30, BLUE);
  93.   tft.fillRect(0, 210, tft.width(), 30, BLUE);
  94.   tft.setTextSize(0);
  95.   
  96.   draw_btn(2,212,48,25," Auto");
  97.   draw_btn(55,212,48,25," x1:1 ");
  98.   draw_btn(108,212,48,25,"  D+");
  99.   draw_btn(162,212,48,25,"  D-");
  100.   draw_btn(217,212,48,25,"measure");
  101.   draw_btn(271,212,48,25," Hold");

  102.   while(1){
  103.    bool down =Touch_getXY();
  104.    if(down&&ypos<230&&ypos>200){
  105.      if(xpos>2&&xpos<48){       //Auto
  106.        _id=0;
  107.       
  108.        delay(100);
  109.      }else if(xpos>55&&xpos<103){   //衰减
  110.        _id=1;
  111.        mode++;
  112.        if(mode>2){mode=0;}
  113.        draw_btn(55,212,48,25,sj[mode]);
  114.      }else if(xpos>108&&xpos<157){  //D+
  115.        _id=2;
  116.        _us+=1;
  117.        if(_us>=6){_us=6;}
  118.      }else if(xpos>162&&xpos<210){  //D-
  119.        _id=3;
  120.        _us-=1;
  121.        if(_us<=0){_us=0;}
  122.      }else if(xpos>217&&xpos<266){  //测量
  123.        _id=4;
  124.        tft.fillRect(0, 0, tft.width(), 30, BLUE);
  125.        if(parameter){
  126.        parameter=false;
  127.        }else{
  128.        parameter=true;
  129.        }
  130.        //delay(100);
  131.      }else if(xpos>271&&xpos<320){  //hold
  132.        _id=5;
  133.        tft.setTextColor(WHITE, BLACK);
  134.        tft.setCursor(5, 40);
  135.        if(hold){
  136.        hold=false;
  137.        tft.print("   ");
  138.        }else{
  139.        hold=true;
  140.        tft.print("HOLD");
  141.        }
  142.        delay(100);
  143.      }
  144.    }else if(down&&ypos<200&&ypos>20){  //触发电压
  145.      tft.drawLine(0, Tv, 5, Tv, BLACK);
  146.      Tv=ypos+10;
  147.    }
  148.   
  149.    if(hold==false){
  150.        sampling();
  151.        measure();
  152.        display_cls();
  153.        display();
  154.    }
  155.   }
  156. }

  157. //获取触屏位置
  158. bool Touch_getXY(void){
  159.   tp = ts.getPoint();   //tp.x, tp.y的值从ADC读取
  160.   pinMode(XM, OUTPUT);  //恢复共享引脚
  161.   pinMode(YP, OUTPUT);
  162.   bool pressed = (tp.z>MINPRESSURE&& tp.z<MAXPRESSURE);
  163.   //模屏竖屏坐标计算
  164.   if (pressed) {
  165.    switch (Orientation) {
  166.      case 0:
  167.        xpos = map(tp.x, TS_LEFT, TS_RT, 0, tft.width());
  168.        ypos = map(tp.y, TS_TOP, TS_BOT, 0, tft.height());
  169.        break;
  170.      case 1:
  171.        xpos = map(tp.y, TS_TOP, TS_BOT, 0, tft.width());
  172.        ypos = map(tp.x, TS_RT, TS_LEFT, 0, tft.height());
  173.        break;
  174.      case 2:
  175.        xpos = map(tp.x, TS_RT, TS_LEFT, 0, tft.width());
  176.        ypos = map(tp.y, TS_BOT, TS_TOP, 0, tft.height());
  177.        break;
  178.      case 3:
  179.        xpos = map(tp.y, TS_BOT, TS_TOP, 0, tft.width());
  180.        ypos = map(tp.y, TS_LEFT, TS_RT, 0, tft.height());
  181.        break;
  182.    }
  183.    /*
  184.    tft.setTextColor(WHITE,BLUE);
  185.    tft.setCursor(250, 10);
  186.    tft.print("x=" + String(xpos) + " y=" + String(ypos) + "   ");*/
  187.   }
  188.   return pressed;
  189. }

  190. void loop(){
  191.   
  192.   
  193. }


  194. //ADC采样通道
  195. void ADC_pin(uint16_t pin){
  196.   switch(pin){
  197.    case A0: //A0
  198.      ADMUX =_BV(REFS0);break;
  199.    case A1: //A1
  200.      ADMUX =_BV(REFS0)|_BV(MUX0);break;
  201.    case A2: //A2
  202.      ADMUX =_BV(REFS0)|_BV(MUX1);break;
  203.    case A3: //A3
  204.      ADMUX =_BV(REFS0)|_BV(MUX0)|_BV(MUX1);break;
  205.    case A4: //A4
  206.      ADMUX =_BV(REFS0)|_BV(MUX2);break;
  207.    case A5: //A5
  208.      ADMUX =_BV(REFS0)|_BV(MUX0)|_BV(MUX2);break;
  209.    case A6: //A6
  210.      ADMUX =_BV(REFS0)|_BV(MUX1)|_BV(MUX2);break;
  211.    case A7: //A7
  212.      ADMUX=_BV(REFS0)|_BV(MUX0)|_BV(MUX1)|_BV(MUX2);
  213.      break;
  214.    default:
  215.      break;
  216.   }
  217.   //ADMUX |= (1<<REFS1)|(1<<REFS0);//内部1.1V参考电压
  218. }

  219. //ADC分频,采样速率
  220. void ADC_adcsra(int key) {
  221.   switch (key){
  222.    case 4://ADC Sample=16MHz/4/13=307.6KHz,实测142.8KHz
  223.      ADCSRA = _BV(ADPS1); //7us采样一次
  224.      break;
  225.    case 8://ADC Sample=16MHz/8/13=153.8KHz,实测100KHz
  226.      ADCSRA = _BV(ADPS0)|_BV(ADPS1);  //10us采样一次
  227.      break;
  228.    case 16://ADC Sample=16MHz/16/13=76.8KHz,实测58.8KHz
  229.      ADCSRA = _BV(ADPS2);  //17us采样一次
  230.      break;
  231.    case 32://ADC Sample=16MHz/32/13= 38.4KHz,实测33.3KHz
  232.      ADCSRA = _BV(ADPS2)|_BV(ADPS0);  //30us采样一次
  233.      break;
  234.    case 64://ADC Sample=16MHz/64/13= 19.2KHz,实测17.8KHz
  235.      ADCSRA = _BV(ADPS2)|_BV(ADPS1);  //56us采样一次
  236.      break;
  237.    case 128://ADC Sample=16MHz/128/13=9600Hz,实测8928Hz
  238.      ADCSRA =_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0);  //112us
  239.      break;
  240.    default:
  241.      break;
  242.   }
  243.   ADCSRA |= _BV(ADEN);
  244. }

  245. //获取ADC采样值
  246. int _analogRead(void){
  247.   bitClear(ADCSRA, ADIF);
  248.   ADCSRA |= _BV(ADSC);
  249.   loop_until_bit_is_set(ADCSRA, ADIF);
  250.   return ADC;
  251. }

  252. //采样
  253. void sampling(){
  254.   ADC_pin(ch1);       //使用ch1采样(触摸屏会更改)
  255.   ADC_adcsra(8);       //使用4分频采样
  256.   //切换通道后前10次采样是错的,不要
  257.   for(i=0;i<15;i++){_analogRead();}
  258.   t = micros();       //采样开始时间
  259.   for(i=0;i<max_buf;i++){
  260.    buf[i]=_analogRead();
  261.    if(time[_us]>0){delayMicroseconds(time[_us]);}
  262.   }
  263.   t = (micros()-t)/max_buf; //采样1次时间
  264.   ADC_adcsra(128);     //恢复128分频给触摸屏
  265. }

  266. //计算参数
  267. void measure(void){
  268.   V_max = buf[0];V_min = buf[0];
  269.   for(i=0;i<max;i++){
  270.    V_max = ((V_max<buf[i])?buf[i]:V_max);//最大值
  271.    V_min = ((V_min>buf[i])?buf[i]:V_min);//最小值
  272.   }
  273.   V_mid = (V_max+V_min)/2; //平均值
  274.   Vpp   = (V_max-V_min);   //峰峰值
  275.   int H=map(Tv,30,210,1023,0);//触发值
  276.   
  277.   if(Vpp==V_max&&V_mid*2==Vpp){ //方波
  278.    //周期开始点
  279.    for (i=0; i<max;i++){
  280.      if(buf[i]<V_mid&&buf[i+1]>V_mid)
  281.        {i1=i;break;}
  282.      }
  283.    for(i=i1+1;i<max;i++){
  284.      //周期内高电平结束点
  285.      if(buf[i]>V_mid&&buf[i+1]<V_mid){i2=i;}
  286.      //周期结束点
  287.      if(buf[i]<V_mid&&buf[i+1]>V_mid)
  288.        {i3=i;break;}
  289.    }
  290.    Cycl=(i3-i1);  //周期时间=周期结速点-周期开始点
  291.    Pw=(i2-i1);     //低电平时间
  292.   
  293.    Duty =(Pw*100)/Cycl; //占空比=低电平时间/周期时间
  294.    Freq =1000000/Cycl/t; //频率
  295.    if(Vpp<H){
  296.      Cycl=0;Pw=0;Duty=0;Freq=0;
  297.    }else if(Freq<0){Freq=old_Freq;Duty=old_Duty;}
  298.   }
  299.   
  300. }

  301. //显示
  302. void display(void){
  303.   for(i=0;i<max+1;i++){
  304.    buf[i]=map(buf[i],0,1023,209,31);     //计算坐标
  305.   }
  306.   for(i=0;i<max;i++){
  307.    tft.drawLine(i, buf[i], i, buf[i+1], WHITE);
  308.    buf_old[i]=buf[i];
  309.   }
  310.   display_v();
  311.   old_Freq=Freq;
  312.   old_Duty=Duty;
  313. }

  314. void display_v(void){
  315.   int a=0;
  316.   tft.setTextColor(WHITE,BLUE);
  317.   if(parameter){
  318.   
  319.    //衰减倍数
  320.    if(mode==0){
  321.      a=1;
  322.    }else if(mode==1){
  323.      a=10;
  324.    }else if(mode==2){
  325.      a=100;
  326.    }
  327.    _Vmax=V_max*vatel/1023;
  328.    _Vmin=V_min*vatel/1023;
  329.    _Vmid=V_mid*vatel/1023;
  330.    _Vrms=Vpp*vatel/1023;
  331.   
  332.    tft.setCursor(2, 5);
  333.    tft.print("Freq:");
  334.    tft.print(Freq);
  335.    tft.print("Hz     ");
  336.    tft.setCursor(2, 20);
  337.    tft.print("Cycl:");
  338.    tft.print(Cycl*t);
  339.    tft.print("us   ");
  340.    tft.setCursor(85, 5);
  341.    tft.print("Pw:");
  342.    tft.print(Pw*t);
  343.    tft.print("us  ");
  344.    tft.setCursor(85, 20);
  345.    tft.print("Duty:");
  346.    tft.print(Duty);
  347.    tft.print("%   ");
  348.   
  349.    tft.setCursor(155, 5);
  350.    tft.print("Vmax:");
  351.    tft.print(_Vmax*a);
  352.    tft.print("V   ");
  353.    tft.setCursor(155, 20);
  354.    tft.print("Vmin:");
  355.    tft.print(_Vmin*a);
  356.    tft.print("V   ");
  357.    tft.setCursor(235, 5);
  358.    tft.print("Vmid:");
  359.    tft.print(_Vmid*a);
  360.    tft.print("V  ");
  361.    tft.setCursor(235, 20);
  362.    tft.print("Vrms:");
  363.    tft.print(_Vrms*a);
  364.    tft.print("V  ");
  365.   }else{
  366.    tft.setTextColor(WHITE,BLUE);
  367.    tft.setCursor(5, 14);
  368.    tft.print("Arduino Digital OSC V2.0");
  369.    tft.setCursor(250, 20);
  370.    tft.print("Delay:"+String(time[_us]) +"us  ");
  371.   }
  372. }


  373. //清除
  374. void display_cls(void){
  375.   for(i=0;i<max;i++){
  376.    tft.drawLine(i, buf_old[i], i, buf_old[i+1], BLACK);
  377.   }
  378.   
  379.   //绘网格
  380.   for(i=32;i<=320;i+=32){  //竖线
  381.    tft.drawLine(i, 30, i, 210, DARKGREY);
  382.   }
  383.   for(i=60;i<=180;i+=30){ //横线
  384.    tft.drawLine(0, i, 320, i, DARKGREY);
  385.   }
  386.   tft.drawLine(0, 120, 320, 120, RED);
  387.   tft.drawLine(160, 30, 160, 210, RED);
  388.   //触发电压
  389.   tft.drawLine(0, Tv, 3, Tv, YELLOW);
  390.   
  391. }
复制代码

评分

黑币 +80
收起理由
+ 80
共享资料的黑币奖励!

查看全部评分

手机版|小黑屋|51黑电子论坛|51黑电子论坛6群QQ管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网