找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5685|回复: 10
收起左侧

Arduino r3驱动废弃电子产品的LCD128*64显示屏制作示波器

  [复制链接]
ID:349565 发表于 2019-2-27 22:03 来自手机 | 显示全部楼层 |阅读模式
这个diy的示波器彩样频率大概1M左右,可以显示峰值电压,幅值电压,频率!占空比。后续功能再添加。
IMG_20190227_145258.jpg
IMG_20190222_094415.jpg

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:349565 发表于 2019-2-27 22:04 来自手机 | 显示全部楼层
想上传代码附件不知道怎么上传
回复

使用道具 举报

ID:1 发表于 2019-2-28 02:17 | 显示全部楼层
先把附件压缩成rar格式,这里有上传教程http://www.51hei.com/bbs/dpj-49501-1.html
回复

使用道具 举报

ID:349565 发表于 2019-3-2 11:30 | 显示全部楼层
现在可以提供下载了
  1. /*
  2. 废弃的显示屏示波器
  3. */

  4. #include <Arduino.h>
  5. #include <U8g2lib.h>
  6. #include <EEPROM.h>

  7. #ifdef U8X8_HAVE_HW_SPI
  8. #include <SPI.h>
  9. #endif

  10. U8G2_ST7565_EA_DOGM128_F_4W_SW_SPI u8g2(U8G2_R0,/*clock=*/5,/*data=*/4,/*cs=*/8,/*dc=*/6,/*reset=*/7);

  11. int input     =A0;      //采集信号输入口
  12. int Key_hold  =12;      //hold显示
  13. int Key_mode  =13;      //延时选择
  14. int dis_width =128;     //显示屏宽度
  15. int dis_hight =64;      //显示屏高度
  16. int x;                  //绘点座标
  17. int Buffer[128];        //缓存值储存数组
  18. long Freq;              //频率
  19. float Vp_p,Vpp;         //实际电压,峰值电压
  20. int Dr;                 //占空比
  21. int t,i1,i2,i3,V_min,V_max,V_mid,hold=0;
  22. float a,b;
  23. int mode=0;
  24. int adc_n=4;
  25. int dTime=1;

  26. //产生62.5K方波
  27. void pwm_62_5k()
  28. {
  29.   cli(); //禁止中断
  30.   pinMode(9, OUTPUT);
  31.   pinMode(10, OUTPUT);
  32.   //设置timer1快速pwm,频率62.5kHz,D9 = OCR1A; D10 = OCR1B
  33.   TCCR1A = 0;
  34.   TCCR1B = 0;
  35.   //比较匹配时清零 OC1A/OC1B
  36.   TCCR1A |= _BV(COM1A1) | _BV(COM1B1);
  37.   //配置8位快速PWM, TOP = 0xFF
  38.   TCCR1A |= _BV(WGM10);
  39.   TCCR1B |= _BV(WGM12);
  40.   //时钟无分频,输出频率: 16 MHz/1/256= 62500Hz
  41.   TCCR1B |= _BV(CS10);
  42.   OCR1A = 127;    // 占空比127/255=50%
  43.   OCR1B = 25.5;   // 占空比25.5/255=10%
  44.   sei(); //允许中断
  45. }

  46. void setup(void) {
  47.   Serial.begin(115200);
  48.   u8g2.begin();
  49.   pinMode(input,INPUT);          //A0要接20K下拉电阻到地
  50.   pinMode(Key_hold,INPUT_PULLUP);//接1K下拉电阻低电平触发
  51.   pinMode(Key_mode,INPUT_PULLUP); //采样模式和速率选择
  52.   u8g2.setFont(u8g2_font_blipfest_07_tr);
  53.   u8g2.setFontDirection(0);
  54.   u8g2.setContrast(180);         //设置屏幕对比度0-255
  55.   pwm_62_5k();
  56.   set_adc(16);                    //ADC 16分频模式采样
  57.   pinMode(11,OUTPUT);
  58.   analogWrite(11,127);
  59. }

  60. void loop(void) {
  61.   sample();          //ADC采样
  62.   Measure();         //测量参数
  63.   Transform();       //计算坐标
  64.   u8g2.firstPage();  //清屏
  65.   if (hold==0){      //冻结显示
  66.     do{draw();}
  67.     while (u8g2.nextPage());
  68.   }
  69.   san_key();
  70. }

  71. //寄时器中断处理A0-A5
  72. ISR(PCINT1_vect){
  73.   /*ADC中断
  74.   放在setup内
  75.   PCMSK1 |= bit (PCINT8); //PCINT8关联A0中断
  76.   PCIFR |= bit (PCIF1);
  77.   PCICR |= bit (PCIE1);
  78.   */
  79. }

  80. //使用寄时器ADC采样,analogRead(pin)函数的采样速率太慢
  81. void sample(){
  82.     ADCSRA |= _BV(ADSC);          //第一次读数不准
  83.   for(x = 0;x < dis_width;x++){
  84.     ADCSRA |= _BV(ADSC);
  85.     loop_until_bit_is_set(ADCSRA, ADIF);
  86.     Buffer[x] = ADC;
  87.     bitClear(ADCSRA, ADIF);
  88.     //暂停x微秒
  89.     //delayMicroseconds(dTime);
  90.   }
  91. }

  92. //测量参数
  93. void Measure(){
  94.   V_max=Buffer[0];//取最大值
  95.   V_min=Buffer[0];//取最小值
  96.   for(x=0;x<dis_width;x++){
  97.     if(Buffer[x]>V_max)
  98.     V_max=Buffer[x];
  99.     if(Buffer[x]<V_min)
  100.     V_min=Buffer[x];
  101.   }
  102.   //平均值=(最大值+最小值)/2
  103.   V_mid=(V_max+V_min)/2;
  104.   //振幅电压=(最大值+最小值)/2*基准电压/1023
  105.   Vp_p=(V_max+V_min)/2*4.99/1023;
  106.   //峰值电压=(最大值-最小值)*基准电压/1023
  107.   Vpp=(V_max-V_min)*4.99/1023;
  108.   for(x=0;x<dis_width-2;x++){
  109.     //周期开始点
  110.     if(Buffer[x]<V_mid&&Buffer[x+1]>=V_mid)
  111.     {i1=x;break;}
  112.   }
  113.   for(x=i1+1;x<dis_width-2+i1;x++){
  114.     //周期内高电平结束点
  115.     if(Buffer[x]>V_mid&&Buffer[x+1]<=V_mid)
  116.     {i3=x;}
  117.     //周期结束点
  118.     if(Buffer[x]<V_mid&&Buffer[x+1]>=V_mid)
  119.     {i2=x;break;}
  120.   }
  121.   //周期时间=周期结速点-周期开始点
  122.   t=i2-i1;
  123.   //高电平时间=高电平结束时间-周期开始点
  124.   a=(i3-i1);
  125.   //占空比=高电平时间/周期时间(高电平时间+低电平时间)
  126.   Dr=a/t*100;
  127.   //频率=1000000/周期时间(高电平时间+低电平时间)
  128.   if(t>1){
  129.     if(adc_n<=16){
  130.        Freq=16000000/adc_n/t;  //16分频模式
  131.     }else if(adc_n>16){
  132.        Freq=16000000/255/adc_n;//非16分频模式
  133.     }
  134.   }else{
  135.     Freq=0;
  136.   }
  137.   if(mode==0){
  138.     //自动选择采样速率以适应高频低频信号
  139.     if(t>30||t<10){
  140.       adc_n=adc_n*2;
  141.       if(adc_n>128){adc_n=4;}
  142.       set_adc(adc_n);
  143.     }
  144.   }
  145. }

  146. //计算座标
  147. void Transform(){
  148.   for(x = 0;x < dis_width;x++){
  149.     //使用map函数将0-1023的模拟值映射为7~62之间的坐标值
  150.     Buffer[x] = map(Buffer[x],0,1023,55,7);  
  151.   }
  152. }
  153.    
  154. //显示
  155. void draw(){
  156.   int dis_h=dis_hight/2;
  157.   //显示电压峰值
  158.   u8g2.drawStr(6,7, "V:");
  159.   u8g2.setCursor(13, 7);
  160.   u8g2.print(Vpp);
  161.   //显示实际电压
  162.   u8g2.drawStr(35,7, "Vp:");
  163.   u8g2.setCursor(45, 7);
  164.   u8g2.print(Vp_p);
  165.   //显示频率
  166.   u8g2.drawStr(68,7, "Hz:");
  167.   u8g2.setCursor(78, 7);
  168.   u8g2.print(Freq);
  169.   //显示占空比
  170.   u8g2.drawStr(105,7, "DR:");
  171.   u8g2.setCursor(115, 7);
  172.   u8g2.print(Dr);
  173.   //画x坐标轴
  174.   u8g2.drawLine(0,dis_h,dis_width,dis_h);
  175.   //画y坐标轴
  176.   u8g2.drawLine(dis_hight,7,dis_hight,dis_width);
  177.   //画边框
  178.   u8g2.drawFrame(4,0,124,dis_hight);
  179.   for(int x=1;x<dis_width;x++){
  180.     //显示波形
  181.     u8g2.drawLine(x,Buffer[x],x,Buffer[x+1]);
  182.   }
  183.   for(x=0;x<dis_width;x+=4){
  184.     //画x坐标刻度
  185.     u8g2.drawLine(x,dis_h-1,x,dis_h+1);
  186.     if (x<=dis_hight-14){
  187.       //画Y坐标刻度
  188.       u8g2.drawLine(dis_hight-1,x+7,dis_hight+1,x+7);
  189.     }
  190.   }
  191.   //ADC采样模式,采样速率
  192.   if(mode==0){
  193.     u8g2.drawStr(6,62, "A:");//自动选频
  194.   }else{
  195.     u8g2.drawStr(6,62, "M:");//手动设置
  196.   }
  197.   u8g2.setCursor(12,62);
  198.   u8g2.print(adc_n);
  199.   //发送数据给显示屏
  200.   u8g2.sendBuffer();
  201. }

  202. void san_key(){
  203.   if(digitalRead(Key_hold)==LOW){
  204.     while(digitalRead(Key_hold)==LOW);
  205.     hold=~hold;
  206.    }
  207.   if(digitalRead(Key_mode)==LOW){
  208.     while(digitalRead(Key_hold)==LOW);
  209.       mode=mode+1;
  210.       if(mode>6){mode=0;Serial.print(0,DEC);}
  211.       if(mode!=0){
  212.         adc_n=adc_n*2;
  213.         if(adc_n>128){adc_n=4;}
  214.         set_adc(adc_n);
  215.       }
  216.       
  217.    }
  218. }

  219. //配置 ADC,提高ADC采样速率
  220. void set_adc(int key) {
  221.   ADMUX = _BV(REFS0); // 使用A0脚采样,精度为(0-1023)
  222.   //ADMUX=_BV(REFS0)|_BV(ADLAR)|0; //精度降为(0-255)
  223.   switch (key){
  224.     case 4://ADC Prescaler = 4
  225.       //理论 Sample Rate可达16MHz/4/13=307.6KHz
  226.       ADCSRA &=  ~(1 << ADPS2);  // 0
  227.       ADCSRA |=  (1 << ADPS1);   // 1
  228.       ADCSRA &=  ~(1 << ADPS0);  // 0
  229.       break;
  230.     case 8://ADC Prescaler = 8
  231.       //理论 Sample Rate可达16MHz/8/13=153.8KHz,实测93.5KH
  232.       ADCSRA &=  ~(1 << ADPS2); // 0
  233.       ADCSRA |=  (1 << ADPS1);  // 1
  234.       ADCSRA |=  (1 << ADPS0);  // 1
  235.       break;
  236.     case 16://ADC Prescaler = 16
  237.       //理论 Sample Rate 可达16MHz/32/13=76.8KHz
  238.       ADCSRA |=  (1 << ADPS2);   // 1
  239.       ADCSRA &=  ~(1 << ADPS1);  // 0
  240.       ADCSRA &=  ~(1 << ADPS0);  // 0
  241.       break;
  242.     case 32://ADC Prescaler = 32
  243.       //理论 Sample Rate 可达16MHz/32/13= 38.4KHz
  244.       ADCSRA |=  (1 << ADPS2);  // 1
  245.       ADCSRA &=  ~(1 << ADPS1); // 0
  246.       ADCSRA |=  (1 << ADPS0);  // 1
  247.       break;
  248.     case 64://ADC Prescaler = 64
  249.       //理论 Sample Rate 可达16MHz/64/13= 19.2KHz
  250.       ADCSRA |=  (1 << ADPS2);  // 1
  251.       ADCSRA |=  (1 << ADPS1);  // 1
  252.       ADCSRA &=  ~(1 << ADPS0); // 0
  253.       //ADCSRA  = ADCSRA&(~7)|0x06;
  254.       break;
  255.     case 128://ADC Prescaler = 128
  256.       //理论 Sample Rate 可达16MHz/128/13=9600Hz
  257.       ADCSRA |=  (1 << ADPS2);  // 1
  258.       ADCSRA |=  (1 << ADPS1);  // 1
  259.       ADCSRA |=  (1 << ADPS0);  // 1
  260.       break;
  261.     default:
  262.       break;
  263.   }
  264. }
复制代码


回复

使用道具 举报

ID:276663 发表于 2019-12-13 09:07 | 显示全部楼层
厉害!
回复

使用道具 举报

ID:525052 发表于 2019-12-15 11:25 | 显示全部楼层
回复

使用道具 举报

ID:242562 发表于 2020-4-11 17:21 | 显示全部楼层
引脚图呢???
回复

使用道具 举报

ID:377382 发表于 2020-6-9 23:43 | 显示全部楼层

谢谢分享
回复

使用道具 举报

ID:429705 发表于 2020-11-10 08:41 | 显示全部楼层
感谢分享,楼主大人有没有接线图啊
回复

使用道具 举报

ID:491340 发表于 2020-11-10 10:37 | 显示全部楼层
这个厉害了 我记得有个U  哪天试试
回复

使用道具 举报

ID:830831 发表于 2020-11-10 12:03 | 显示全部楼层
强人呀,给力
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

Powered by 单片机教程网

快速回复 返回顶部 返回列表