現在可以提供下載了
- /*
- 廢棄的顯示屏示波器
- */
- #include <Arduino.h>
- #include <U8g2lib.h>
- #include <EEPROM.h>
- #ifdef U8X8_HAVE_HW_SPI
- #include <SPI.h>
- #endif
- U8G2_ST7565_EA_DOGM128_F_4W_SW_SPI u8g2(U8G2_R0,/*clock=*/5,/*data=*/4,/*cs=*/8,/*dc=*/6,/*reset=*/7);
- int input =A0; //采集信號輸入口
- int Key_hold =12; //hold顯示
- int Key_mode =13; //延時選擇
- int dis_width =128; //顯示屏寬度
- int dis_hight =64; //顯示屏高度
- int x; //繪點座標
- int Buffer[128]; //緩存值儲存數組
- long Freq; //頻率
- float Vp_p,Vpp; //實際電壓,峰值電壓
- int Dr; //占空比
- int t,i1,i2,i3,V_min,V_max,V_mid,hold=0;
- float a,b;
- int mode=0;
- int adc_n=4;
- int dTime=1;
- //產生62.5K方波
- void pwm_62_5k()
- {
- cli(); //禁止中斷
- pinMode(9, OUTPUT);
- pinMode(10, OUTPUT);
- //設置timer1快速pwm,頻率62.5kHz,D9 = OCR1A; D10 = OCR1B
- TCCR1A = 0;
- TCCR1B = 0;
- //比較匹配時清零 OC1A/OC1B
- TCCR1A |= _BV(COM1A1) | _BV(COM1B1);
- //配置8位快速PWM, TOP = 0xFF
- TCCR1A |= _BV(WGM10);
- TCCR1B |= _BV(WGM12);
- //時鐘無分頻,輸出頻率: 16 MHz/1/256= 62500Hz
- TCCR1B |= _BV(CS10);
- OCR1A = 127; // 占空比127/255=50%
- OCR1B = 25.5; // 占空比25.5/255=10%
- sei(); //允許中斷
- }
- void setup(void) {
- Serial.begin(115200);
- u8g2.begin();
- pinMode(input,INPUT); //A0要接20K下拉電阻到地
- pinMode(Key_hold,INPUT_PULLUP);//接1K下拉電阻低電平觸發
- pinMode(Key_mode,INPUT_PULLUP); //采樣模式和速率選擇
- u8g2.setFont(u8g2_font_blipfest_07_tr);
- u8g2.setFontDirection(0);
- u8g2.setContrast(180); //設置屏幕對比度0-255
- pwm_62_5k();
- set_adc(16); //ADC 16分頻模式采樣
- pinMode(11,OUTPUT);
- analogWrite(11,127);
- }
- void loop(void) {
- sample(); //ADC采樣
- Measure(); //測量參數
- Transform(); //計算坐標
- u8g2.firstPage(); //清屏
- if (hold==0){ //凍結顯示
- do{draw();}
- while (u8g2.nextPage());
- }
- san_key();
- }
- //寄時器中斷處理A0-A5
- ISR(PCINT1_vect){
- /*ADC中斷
- 放在setup內
- PCMSK1 |= bit (PCINT8); //PCINT8關聯A0中斷
- PCIFR |= bit (PCIF1);
- PCICR |= bit (PCIE1);
- */
- }
- //使用寄時器ADC采樣,analogRead(pin)函數的采樣速率太慢
- void sample(){
- ADCSRA |= _BV(ADSC); //第一次讀數不準
- for(x = 0;x < dis_width;x++){
- ADCSRA |= _BV(ADSC);
- loop_until_bit_is_set(ADCSRA, ADIF);
- Buffer[x] = ADC;
- bitClear(ADCSRA, ADIF);
- //暫停x微秒
- //delayMicroseconds(dTime);
- }
- }
- //測量參數
- void Measure(){
- V_max=Buffer[0];//取最大值
- V_min=Buffer[0];//取最小值
- for(x=0;x<dis_width;x++){
- if(Buffer[x]>V_max)
- V_max=Buffer[x];
- if(Buffer[x]<V_min)
- V_min=Buffer[x];
- }
- //平均值=(最大值+最小值)/2
- V_mid=(V_max+V_min)/2;
- //振幅電壓=(最大值+最小值)/2*基準電壓/1023
- Vp_p=(V_max+V_min)/2*4.99/1023;
- //峰值電壓=(最大值-最小值)*基準電壓/1023
- Vpp=(V_max-V_min)*4.99/1023;
- for(x=0;x<dis_width-2;x++){
- //周期開始點
- if(Buffer[x]<V_mid&&Buffer[x+1]>=V_mid)
- {i1=x;break;}
- }
- for(x=i1+1;x<dis_width-2+i1;x++){
- //周期內高電平結束點
- if(Buffer[x]>V_mid&&Buffer[x+1]<=V_mid)
- {i3=x;}
- //周期結束點
- if(Buffer[x]<V_mid&&Buffer[x+1]>=V_mid)
- {i2=x;break;}
- }
- //周期時間=周期結速點-周期開始點
- t=i2-i1;
- //高電平時間=高電平結束時間-周期開始點
- a=(i3-i1);
- //占空比=高電平時間/周期時間(高電平時間+低電平時間)
- Dr=a/t*100;
- //頻率=1000000/周期時間(高電平時間+低電平時間)
- if(t>1){
- if(adc_n<=16){
- Freq=16000000/adc_n/t; //16分頻模式
- }else if(adc_n>16){
- Freq=16000000/255/adc_n;//非16分頻模式
- }
- }else{
- Freq=0;
- }
- if(mode==0){
- //自動選擇采樣速率以適應高頻低頻信號
- if(t>30||t<10){
- adc_n=adc_n*2;
- if(adc_n>128){adc_n=4;}
- set_adc(adc_n);
- }
- }
- }
- //計算座標
- void Transform(){
- for(x = 0;x < dis_width;x++){
- //使用map函數將0-1023的模擬值映射為7~62之間的坐標值
- Buffer[x] = map(Buffer[x],0,1023,55,7);
- }
- }
-
- //顯示
- void draw(){
- int dis_h=dis_hight/2;
- //顯示電壓峰值
- u8g2.drawStr(6,7, "V:");
- u8g2.setCursor(13, 7);
- u8g2.print(Vpp);
- //顯示實際電壓
- u8g2.drawStr(35,7, "Vp:");
- u8g2.setCursor(45, 7);
- u8g2.print(Vp_p);
- //顯示頻率
- u8g2.drawStr(68,7, "Hz:");
- u8g2.setCursor(78, 7);
- u8g2.print(Freq);
- //顯示占空比
- u8g2.drawStr(105,7, "DR:");
- u8g2.setCursor(115, 7);
- u8g2.print(Dr);
- //畫x坐標軸
- u8g2.drawLine(0,dis_h,dis_width,dis_h);
- //畫y坐標軸
- u8g2.drawLine(dis_hight,7,dis_hight,dis_width);
- //畫邊框
- u8g2.drawFrame(4,0,124,dis_hight);
- for(int x=1;x<dis_width;x++){
- //顯示波形
- u8g2.drawLine(x,Buffer[x],x,Buffer[x+1]);
- }
- for(x=0;x<dis_width;x+=4){
- //畫x坐標刻度
- u8g2.drawLine(x,dis_h-1,x,dis_h+1);
- if (x<=dis_hight-14){
- //畫Y坐標刻度
- u8g2.drawLine(dis_hight-1,x+7,dis_hight+1,x+7);
- }
- }
- //ADC采樣模式,采樣速率
- if(mode==0){
- u8g2.drawStr(6,62, "A:");//自動選頻
- }else{
- u8g2.drawStr(6,62, "M:");//手動設置
- }
- u8g2.setCursor(12,62);
- u8g2.print(adc_n);
- //發送數據給顯示屏
- u8g2.sendBuffer();
- }
- void san_key(){
- if(digitalRead(Key_hold)==LOW){
- while(digitalRead(Key_hold)==LOW);
- hold=~hold;
- }
- if(digitalRead(Key_mode)==LOW){
- while(digitalRead(Key_hold)==LOW);
- mode=mode+1;
- if(mode>6){mode=0;Serial.print(0,DEC);}
- if(mode!=0){
- adc_n=adc_n*2;
- if(adc_n>128){adc_n=4;}
- set_adc(adc_n);
- }
-
- }
- }
- //配置 ADC,提高ADC采樣速率
- void set_adc(int key) {
- ADMUX = _BV(REFS0); // 使用A0腳采樣,精度為(0-1023)
- //ADMUX=_BV(REFS0)|_BV(ADLAR)|0; //精度降為(0-255)
- switch (key){
- case 4://ADC Prescaler = 4
- //理論 Sample Rate可達16MHz/4/13=307.6KHz
- ADCSRA &= ~(1 << ADPS2); // 0
- ADCSRA |= (1 << ADPS1); // 1
- ADCSRA &= ~(1 << ADPS0); // 0
- break;
- case 8://ADC Prescaler = 8
- //理論 Sample Rate可達16MHz/8/13=153.8KHz,實測93.5KH
- ADCSRA &= ~(1 << ADPS2); // 0
- ADCSRA |= (1 << ADPS1); // 1
- ADCSRA |= (1 << ADPS0); // 1
- break;
- case 16://ADC Prescaler = 16
- //理論 Sample Rate 可達16MHz/32/13=76.8KHz
- ADCSRA |= (1 << ADPS2); // 1
- ADCSRA &= ~(1 << ADPS1); // 0
- ADCSRA &= ~(1 << ADPS0); // 0
- break;
- case 32://ADC Prescaler = 32
- //理論 Sample Rate 可達16MHz/32/13= 38.4KHz
- ADCSRA |= (1 << ADPS2); // 1
- ADCSRA &= ~(1 << ADPS1); // 0
- ADCSRA |= (1 << ADPS0); // 1
- break;
- case 64://ADC Prescaler = 64
- //理論 Sample Rate 可達16MHz/64/13= 19.2KHz
- ADCSRA |= (1 << ADPS2); // 1
- ADCSRA |= (1 << ADPS1); // 1
- ADCSRA &= ~(1 << ADPS0); // 0
- //ADCSRA = ADCSRA&(~7)|0x06;
- break;
- case 128://ADC Prescaler = 128
- //理論 Sample Rate 可達16MHz/128/13=9600Hz
- ADCSRA |= (1 << ADPS2); // 1
- ADCSRA |= (1 << ADPS1); // 1
- ADCSRA |= (1 << ADPS0); // 1
- break;
- default:
- break;
- }
- }
復制代碼
|