久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 3536|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

基于AVR單片機(jī)的混合信號(hào)示波器DIY資料分享

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:93248 發(fā)表于 2018-5-19 09:25 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
在這里發(fā)一個(gè)基于AVR單片機(jī)的混合信號(hào)示波器,有興趣的朋友可以DIY一個(gè)來(lái)玩玩

關(guān)鍵元件
MCU:ATXMEGA32A
顯示:0.96 OLE,128 x64像素

規(guī)格:
2路模擬輸入
最大采樣率2MSPS
模擬帶寬200Khz
綬沖區(qū)256字節(jié)
輸入電壓范圍-14V到+20V

pc程序界面:


電路原理圖如下:




單片機(jī)源程序如下:
  1. /*****************************************************************************

  2. Xprotolab - AVR XMEGA Oscilloscope and Development Kit

  3. Gabotronics C.A.
  4. March 2011

  5. ATXMEGA32A4

  6. Compiled with GCC, -Os optimizations
  7. email me at: gabriel@gabotronics.com

  8. *****************************************************************************/

  9. #include <avr/io.h>
  10. #include <util/delay.h>
  11. #include <avr/pgmspace.h>
  12. #include <avr/interrupt.h>
  13. #include <avr/sleep.h>
  14. #include <avr/wdt.h>
  15. #include <stddef.h>

  16. #include "main.h"
  17. #include "mso.h"
  18. #include "logic.h"
  19. #include "awg.h"

  20. uint8_t SP_ReadCalibrationByte(uint8_t location);
  21. void Restore(void);
  22. uint16_t readVCC(void);

  23. uint8_t AWGBuffer[256];             // AWG Output Buffer
  24. // Big temp buffer to store tempFFT, tempAWG and temp ch data
  25. // Last 256 bytes hold CHD.data
  26. uint8_t bigtemp[1280];

  27. // EEProm variables
  28. uint8_t EEMEM EESleepTime = 64;     // Sleep timeout in minutes
  29. uint8_t EEMEM EEDACgain   = 0;      // DAC gain calibration
  30. uint8_t EEMEM EEDACoffset = 0;      // DAC offset calibration

  31. static void Calibrate(void);
  32. static void SimpleADC(void);
  33. void ScreenSaver(uint8_t minutes);
  34. static void CalibrateDAC(void);

  35. int main(void) {
  36.     uint8_t i,j,rx=0;
  37.     // Power reduction: Stop unused peripherals
  38.     PR.PRGEN = 0x18;        // Stop: AES, EBI
  39.     PR.PRPA  = 0x04;        // Stop: DAC
  40.     PR.PRPB  = 0x03;        // Stop: ADC, AC
  41.     PR.PRPC  = 0x7C;        // Stop: TWI, USART0, USART1, SPI, HIRES
  42.     PR.PRPD  = 0x7C;        // Stop: TWI, USART0, USART1, SPI, HIRES
  43.     PR.PRPE  = 0x6C;        // Stop: TWI,         USART1, SPI, HIRES

  44.     // PORTS CONFIGURATION
  45.     // Initial value PORTA.DIR       = 0x00; // CH2, CH1, 1V, K1, K2, K3, K4, REF
  46.     PORTA.PIN4CTRL  = 0x18; // Pull up on pin PA4
  47.     PORTA.PIN3CTRL  = 0x18; // Pull up on pin PA3
  48.     PORTA.PIN2CTRL  = 0x18; // Pull up on pin PA2
  49.     PORTA.PIN1CTRL  = 0x18; // Pull up on pin PA1
  50.     PORTA.INTCTRL   = 0x02; // PORTA will generate medium level interrupts
  51.     PORTA.INT0MASK  = 0x1E; // PA4, PA3, PA2, PA1 will be the interrupt 0 sources
  52.     PORTB.DIR       = 0x0B; // RES, AWG, D/C, R/W
  53.     // Initial Value PORTB.OUT       = 0x00; //
  54.     // Initial Value PORTC.DIR       = 0x00; // LOGIC
  55.     PORTC.INT0MASK  = 0x01; // PC0 (SDA) will be the interrupt 0 source
  56.     PORTC.INT1MASK  = 0x80; // PC7 (SCK) will be the interrupt 1 source
  57.     PORTD.DIR       = 0xFF; // LCD Data bus
  58.     // Initial Value PORTD.OUT       = 0x00;
  59.     PORTE.DIR       = 0x09; // TX, RX, EXT, E
  60.     // Initial Value PORTE.OUT       = 0x00; //
  61.     PORTCFG.VPCTRLA = 0x41; // VP1 Map to PORTE, VP0 Map to PORTB
  62.     PORTCFG.VPCTRLB = 0x32; // VP3 Map to PORTD, VP2 Map to PORTC
  63.     key = 0;

  64.     // Clock Settings
  65.     i=1;
  66.     OSC.XOSCCTRL = 0xCB;    // 0.4-16 MHz XTAL - 16K CLK Start Up
  67.     OSC.CTRL = 0x08;        // Enable External Oscillator
  68.     while(i && !testbit(OSC.STATUS,OSC_XOSCRDY_bp)) {   // wait until crystal stable
  69.         i++;
  70.         _delay_us(100);
  71.     }
  72.     OSC.PLLCTRL = 0xC2;     // XOSC is PLL Source - 2x Factor (32MHz)
  73.     OSC.CTRL = 0x19;        // Enable PLL & External Oscillator
  74.     while(i && !testbit(OSC.STATUS,OSC_PLLRDY_bp)) {         // wait until PLL stable
  75.         i++;
  76.         _delay_us(100);
  77.     }
  78.     // Swith to internal 32MHz if crystal fails  
  79.     if(i==0) {   // Timed out, use internal oscillator
  80.         OSC.XOSCCTRL = 0x00;    // Disable external oscillators
  81.         OSC.CTRL = 0x03;        // Enable internal 32MHz
  82.         while(!testbit(OSC.STATUS,OSC_RC32MRDY_bp));  // wait until 32MHz stable
  83.         CCPWrite(&CLK.CTRL, CLK_SCLKSEL_RC32M_gc);    // Use internal 32MHz
  84.         OSC.CTRL = 0x02;        // Disable internal 2MHz
  85.     }
  86.     else {  // Crystal OK!
  87.         CCPWrite(&CLK.CTRL, CLK_SCLKSEL_PLL_gc);    // Switch to PLL clock
  88.         OSC.CTRL = 0x18;        // Disable internal 2MHz
  89.     }

  90.     // Initialize USART
  91.     USARTE0.BAUDCTRLA = 0x17;   // BSCALE = -6, BSEL = 1047
  92.     USARTE0.BAUDCTRLB = 0xA4;   // ==> 115211 bps (~115.2kbps)
  93.     USARTE0.CTRLC = 0x03;       // Async, No Parity, 1 stop bit, 8 data bits
  94.     USARTE0.CTRLB = 0x18;       // Enable RX and TX

  95.     // Event System for ADC
  96.     EVSYS.CH0MUX = 0xE0;    // Event CH0 = TCE0 overflow used for ADC

  97.     // ADC
  98.         ADCA.CALL = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL0) );
  99.         ADCA.CALH = SP_ReadCalibrationByte(offsetof(NVM_PROD_SIGNATURES_t, ADCACAL1) );
  100.     ADCA.PRESCALER  = 0x06;     // Prescaler
  101.     ADCA.CTRLB      = 0x18;     // signed mode, free run, 12 bit
  102.     ADCA.REFCTRL    = 0x20;     // REF= AREF (2V)
  103.     ADCA.EVCTRL     = 0x45;     // Sweep channels 0,1
  104.     ADCA.CH0.MUXCTRL = 0x2A;    // Channel 0 input: ADC5 pin - ADC6 pin
  105.     ADCA.CH0.CTRL   = 0x03;     // Differential input with gain
  106.     ADCA.CH1.MUXCTRL = 0x2B;    // Channel 1 input: ADC5 pin - ADC7 pin
  107.     ADCA.CH1.CTRL   = 0x03;     // Differential input with gain
  108.     ADCA.CH2.MUXCTRL = 0x02;    // Channel 2 input: VCC/10
  109.     ADCA.CTRLA = 0x01;          // Enable ADC
  110.     // Initial Value ADCA.CH2.CTRL = 0x00;       // Internal input
  111.     // Initial Value ADCA.CH3.MUXCTRL = 0x00;    // Channel 3 input: temperature
  112.     // Initial Value ADCA.CH3.CTRL = 0x00;       // Internal input

  113.     ADCA.CH1.INTCTRL = 0x03;    // ADC is high level interrupt

  114.     // Event system for DAC
  115.     EVSYS.CH3MUX = 0xD0;    // Event CH3 = TCD0 overflow used for DAC

  116.     // Timer TCD0: 1MHz timer for DACA
  117.     TCD0.CTRLA = 0x01;      // Prescaler: clk/1
  118.     TCD0.PER   = 31;        // 1MHz

  119.     // DAC
  120.     DACB.CTRLB = 0x01;          // CH0 auto triggered by an event
  121.     DACB.CTRLC = 0x11;          // Use AREFA (2.0V), data is left adjusted
  122.     DACB.EVCTRL = 0x03;         // Event CH3 triggers the DAC Conversion
  123.     DACB.TIMCTRL = 0x50;        // Minimum 32 CLK between conversion (1uS)
  124.     DACB.GAINCAL = eeprom_read_byte(&EEDACgain);      // Load DACA gain calibration
  125.     DACB.OFFSETCAL = eeprom_read_byte(&EEDACoffset);  // Load DACA offset calibration
  126.     DACB.CTRLA = 0x05;          // Enable DACB and CH0

  127.     InitDMA();

  128.     // Arbitrary Waveform Generator
  129.     LoadAWGvars();              // Load AWG settings
  130.     BuildWave();                // Construct AWG waveform

  131.     // Interrupt Configuration
  132.     PMIC.CTRL = 0x07;       // Enable High, Medium and Low level interrupts
  133.     sei();      // Enable global interrupts

  134.     // Initialize LCD
  135.     GLCD_LcdInit();
  136.     if(testbit(display, flip)) {
  137.         LcdInstructionWrite(LCD_SET_SCAN_NOR);   // direction
  138.         LcdInstructionWrite(LCD_SET_SEG_REMAP1);
  139.     }
  140.         GLCD_DisplayPicture(LOGO);
  141. //    tiny_printp(45,3,PSTR("XPROTOLAB"));
  142.     tiny_printp(50/*39*/,7,VERSION);
  143.     if(CLK.CTRL & CLK_SCLKSEL_RC32M_gc) lcd_putsp(PSTR(" XT FAIL"));
  144.     show_display();

  145.     for(i=0; i<100; i++) {
  146.         if(testbit(USARTE0.STATUS,USART_RXCIF_bp)) {
  147.             j=USARTE0.DATA; // dummy read
  148.             rx++;
  149.         }
  150.         _delay_ms(30);
  151.     }

  152.     // Check if received data that should not have been received
  153.     if(rx<=4) USARTE0.CTRLB = 0x18;       // Enable RX and TX
  154.     else {
  155.         // Device is connected to a regular USB port on a PC, disable the USART
  156.         USARTE0.CTRLB = 0x00;   // Disable RX, TX
  157.         PR.PRPE  = 0x7C;        // Stop: TWI, USART0, USART1, SPI, HIRES
  158.         PORTE.DIR       = 0x01; // TX as input
  159.     }


  160.     // TCD1 controls LCD refresh rate
  161.     TCD1.CTRLA = 6;         // Prescaler: clk/256
  162.     TCD1.PER = 15624;       // Maximum LCD refresh rate is 8Hz

  163.     // TCC1 controls the auto trigger and auto key repeat
  164.     TCC1.CTRLA = 7;         // Prescaler: clk/256
  165.     TCC1.PER = 31999;       // Period is 1.024 seconds
  166.     TCC1.INTCTRLA = 0x01;   // Generate low level interrupt

  167.     // RTC Clock Settings
  168.         /* Set 1.024kHz from internal 32.768kHz RC oscillator */
  169.         CLK.RTCCTRL = CLK_RTCSRC_RCOSC_gc | CLK_RTCEN_bm;
  170.     i=eeprom_read_byte(&EESleepTime);
  171.     ScreenSaver(i);

  172.     if( testbit(PORTA.IN,1))   MSO();      // KD not pressed -> got to MSO

  173.     setbit(Signals, redraw);
  174.     key=0;

  175.     for(;;) {
  176.         while(!testbit(TCD1.INTFLAGS, TC1_OVFIF_bp)) {   // wait for refresh timeout
  177.             if(testbit(Signals, userinput))
  178.                 break;       // cancel if user input
  179.         }
  180.         setbit(TCD1.INTFLAGS, TC1_OVFIF_bp);
  181.         clr_display();
  182.         lcd_goto(0,0); printhex(VPORT2.IN);
  183.         tiny_printp(0,4,PSTR("XMEGA rev")); GLCD_Putchar('A'+MCU.REVID);
  184.         //tiny_printp(32,5,PSTR("VIN"));
  185.         tiny_printp(0,7,PSTR("OFFSET"));
  186.         tiny_printp(98,7,PSTR("RESTORE"));
  187.         tiny_printp(54,6,PSTR("SLEEP:"));

  188.         lcd_goto(58,7);
  189.         if(i) printN(i);
  190.         else lcd_putsp(PSTR("OFF"));
  191.         if(testbit(Signals, userinput)) {
  192.             clrbit(Signals, userinput);
  193.             switch(key) {
  194.                 case KA: Calibrate();       break;
  195.                 case KB: i+=16;
  196.                          ScreenSaver(i);
  197.                 break;
  198.                 case KC: Restore();         break;
  199.                 case KD: key=0; eeprom_write_byte(&EESleepTime, i);
  200.                         MSO();
  201.             }
  202.         }
  203.         //lcd_goto(20,5); printN(readVCC());
  204.         show_display();
  205.     }
  206.     return 0;
  207. }

  208. // Return sine fractional value
  209. int8_t Sin(uint8_t angle) {
  210.     if(angle>=128) return - pgm_read_byte(&sint[angle-128]);
  211.     return pgm_read_byte(&sint[angle]);
  212. }

  213. // Add unsigned with signed using saturation, return unsigned
  214. uint8_t addwsat(uint8_t a, int8_t b) {
  215.     if(b>=0) {
  216.         if(a>255-b) return 255;
  217.     }
  218.     else {
  219.         if(a<(-b)) return 0;
  220.     }
  221.     return a+b;
  222. }

  223. // ADC conversion complete, for sampling rates >= 1mS/div (srate>=9)
  224. ISR(ADCA_CH1_vect) {
  225.     static uint8_t i=0,n=0;
  226.     static int16_t sum1=0,sum2=0;
  227.     static int16_t *p1=bigtemp, *p2=bigtemp+512;
  228.     int16_t d1,d2;
  229.     d1=ADCA.CH0.RES; sum1 += d1;
  230.     d2=ADCA.CH1.RES; sum2 += d2;
  231.     n++;
  232.     if(n==2 && srate==7) {
  233.         if(CH1.ctrl.average) *p1++ = sum1>>1;
  234.         else                 *p1++ = d1;
  235.         if(CH2.ctrl.average) *p2++ = sum2>>1;
  236.         else                 *p2++ = d2;
  237.     }
  238.     else if(n==4 && srate==8) {
  239.         if(CH1.ctrl.average) *p1++ = sum1>>2;
  240.         else                 *p1++ = d1;
  241.         if(CH2.ctrl.average) *p2++ = sum2>>2;
  242.         else                 *p2++ = d2;
  243.     }
  244.     else if(n==8) {
  245.         if(CH1.ctrl.average) *p1++ = sum1>>3;
  246.         else                 *p1++ = d1;
  247.         if(CH2.ctrl.average) *p2++ = sum2>>3;
  248.         else                 *p2++ = d2;
  249.     }
  250.     else return;
  251.     CHD.data[i] = VPORT2.IN;
  252.     i++;
  253.     n=0;
  254.     sum1=0; sum2=0;
  255.     if(i==0) {
  256.         setbit(MStatus,acquired);   // Acquired all samples
  257.         ADCA.CH1.INTCTRL = 0x00;    // disable interrupt
  258.         p1=bigtemp;
  259.         p2=bigtemp+512;
  260.     }
  261. }

  262. // Tactile Switches - This is configured as a low level interrupt
  263. ISR(PORTA_INT0_vect) {
  264.     uint8_t i,in,j=0;
  265.     // Debounce: need to read 10 consecutive equal numbers
  266.     for(i=10; i>0; i--) {
  267.                 _delay_ms(1);
  268.                 in = PORTA.IN & 0x1E;      // Read port
  269.                 if(j!=in) { j=in; i++; }
  270.         }
  271.     key=0;
  272.     if(!testbit(in,1)) {
  273.          key = KD;  // Menu key
  274.     }
  275.     if(testbit(display, flip)) {
  276.         if(!testbit(in,4)) key |= KC;
  277.         if(!testbit(in,3)) key |= KB;
  278.         if(!testbit(in,2)) key |= KA;
  279.     }
  280.     else {
  281.         if(!testbit(in,4)) key |= KA;
  282.         if(!testbit(in,3)) key |= KB;
  283.         if(!testbit(in,2)) key |= KC;
  284.     }
  285.     if(key) {
  286.         setbit(Signals, update);         // Valid key
  287.         setbit(Signals, userinput);
  288.     }
  289.     else keyrep=0;
  290.     RTC.CNT=0;  // Clear screen saver timer
  291.     // TCC1 used for auto repeat key
  292.     TCC1.CNT = 0;            // Clear TCC1
  293.     setbit(TCC1.INTFLAGS, TC1_OVFIF_bp);    // Clear timeout interrupt
  294. }

  295. // From Application Note AVR1003
  296. void CCPWrite( volatile uint8_t * address, uint8_t value ) {
  297.     uint8_t volatile saved_sreg = SREG;
  298.     cli();

  299. #ifdef __ICCAVR__
  300.         asm("movw r30, r16");
  301. #ifdef RAMPZ
  302.         RAMPZ = 0;
  303. #endif
  304.         asm("ldi  r16,  0xD8 \n"
  305.             "out  0x34, r16  \n"
  306. #if (__MEMORY_MODEL__ == 1)
  307.             "st     Z,  r17  \n");
  308. #elif (__MEMORY_MODEL__ == 2)
  309.             "st     Z,  r18  \n");
  310. #else /* (__MEMORY_MODEL__ == 3) || (__MEMORY_MODEL__ == 5) */
  311.             "st     Z,  r19  \n");
  312. #endif /* __MEMORY_MODEL__ */

  313. #elif defined __GNUC__
  314.         volatile uint8_t * tmpAddr = address;
  315. #ifdef RAMPZ
  316.         RAMPZ = 0;
  317. #endif
  318.         asm volatile(
  319.                 "movw r30,  %0"              "\n\t"
  320.                 "ldi  r16,  %2"              "\n\t"
  321.                 "out   %3, r16"              "\n\t"
  322.                 "st     Z,  %1"       "\n\t"
  323.                 :
  324.                 : "r" (tmpAddr), "r" (value), "M" (CCP_IOREG_gc), "i" (&CCP)
  325.                 : "r16", "r30", "r31"
  326.                 );

  327. #endif
  328.         SREG = saved_sreg;
  329. }

  330. /*! \brief Function for GCC to read out calibration byte.
  331. *
  332. *  \note For IAR support, include the adc_driver_asm.S90 file in your project.
  333. *
  334. *  \param index The index to the calibration byte.
  335. *
  336. *  \return Calibration byte.
  337. */
  338. uint8_t SP_ReadCalibrationByte( uint8_t location )
  339. {
  340.         uint8_t result;

  341.         /* Load the NVM Command register to read the calibration row. */
  342.         NVM_CMD = NVM_CMD_READ_CALIB_ROW_gc;
  343.         result = pgm_read_byte(location);

  344.         /* Clean up NVM Command register. */
  345.         NVM_CMD = NVM_CMD_NO_OPERATION_gc;

  346.         return result;
  347. }

  348. // Calibrate offset, inputs must be connected to ground
  349. static void Calibrate(void) {
  350.     uint8_t i,j;
  351.     uint16_t average;
  352.     key=0;
  353.     clr_display();
  354.     tiny_printp(48,0,PSTR("Connnect CH1, CH2"));
  355.     tiny_printp(48,1,PSTR("to ground"));
  356.     tiny_printp(108,7,PSTR("START"));
  357. /*    // Show current calibration
  358.     for(i=0; i<8; i++) {
  359.         lcd_goto(0,i);
  360.         printN((int8_t)eeprom_read_byte(&offsetsCH1[i])+128);
  361.         printN((int8_t)eeprom_read_byte(&offsetsCH2[i])+128);
  362.     }*/
  363.     show_display();
  364.     while(!key);
  365.     if(key!=KC) {
  366.         key=0;
  367.         return;
  368.     }
  369.     key=0;
  370.     clr_display();
  371.     tiny_printp(84,0,PSTR("Calibrating"));
  372.     // Cycle thru all the 8 gains
  373.     for(i=0; i<8; i++) {
  374.         lcd_goto(0,i);
  375.         ADCA.CH0.CTRL = 0x03 | (i<<2);       // Set gain
  376.         ADCA.CH1.CTRL = 0x03 | (i<<2);       // Set gain
  377.         _delay_ms(50);
  378.         SimpleADC();
  379.         // Calculate offset for CH1
  380.         average=0;
  381.         j=0;
  382.         do {
  383.             average+= CH1.data[i];
  384.         } while(++j);
  385.         j = (uint8_t )(average>>8);
  386.         if(j>=128) CH1.offset=-(j-128);
  387.         else CH1.offset = (128-j);
  388.         eeprom_write_byte(&offsetsCH1[i], CH1.offset);
  389.         printN(CH1.offset+128);
  390.         // Calculate offset for CH2
  391.         average=0;
  392.         j=0;
  393.         do {
  394.             average+= CH2.data[i];
  395.         } while(++j);
  396.         j = (uint8_t )(average>>8);
  397.         if(j>=128) CH2.offset=-(j-128);
  398.         else CH2.offset = (128-j);
  399.         eeprom_write_byte(&offsetsCH2[i], CH2.offset);
  400.         printN(CH2.offset+128);
  401.         show_display();
  402.     }
  403.     _delay_ms(2000);
  404. }

  405. // Fill up channel data buffers
  406. void SimpleADC(void) {
  407.     uint8_t  *p1, *p2;  // temp pointers to unsigned 8 bits
  408.     int16_t  *q1, *q2;  // temp pointers to signed 16 bits
  409.     uint8_t j;
  410.     uint16_t data;
  411.     // Acquire using DMA
  412.     setbit(DMA.CH0.CTRLA, 7);
  413.     setbit(DMA.CH1.CTRLA, 7);
  414.     while(testbit(DMA.CH1.CTRLA,7)) ;
  415.     // Convert 12bit result to 8bit
  416.     p1=CH1.data; p2=CH2.data;
  417.     q1=bigtemp;  q2=bigtemp+512;
  418.     j=0; do {
  419.         data=*q1+2048;    // convert to unsigned
  420.         *p1 = (uint8_t)((data)>>4);
  421.         data=*q2+2048;    // convert to unsigned
  422.         *p2 = (uint8_t)((data)>>4);
  423.         p1++; p2++;
  424.         q1++; q2++;
  425.     } while (++j);
  426. }

  427. // Recieves a nibble, returns the corresponding ascii that represents the HEX value
  428. char NibbleToChar(uint8_t nibble) {
  429.     if(nibble<10) return '0'+nibble;   // '0' thru '9'
  430.     return '7'+nibble;            // 'A' thru 'F'   
  431. }

  432. // Prints a HEX number
  433. void printhex(uint8_t n) {
  434.     uint8_t temp;
  435.     temp = n>>4;
  436.     GLCD_Putchar(NibbleToChar(temp));
  437.     temp = n&0x0F;            
  438.     GLCD_Putchar(NibbleToChar(temp));
  439. }

  440. // Converts an uint to int, then calculates the half
  441. uint8_t half(uint8_t number) {
  442.     int8_t temp;
  443.     temp=(int8_t)(number-128);
  444.     temp=temp/2;
  445.     return (uint8_t)(temp+128);
  446. }

  447. /*
  448. // Calibrate DAC gain and offset, connect AWG to CH1
  449. // Adjust with rotary encoders
  450. static void CalibrateDAC(void) {
  451.     uint8_t i, step=0, data, average;
  452.     uint8_t test, bestoffset, bestgain, bestmeasure1;
  453.     uint16_t sum, bestmeasure2;
  454.     clr_display();

  455.     ADCA.CH0.CTRL = 0x03 | (6<<2);       // Set gain 6
  456.     CH1.offset=(signed char)eeprom_read_byte(&offsetsCH1[6]);

  457.     AWGAmp=127;         // Amplitude range: [0,127]
  458.     AWGtype=1;          // Waveform type
  459.     AWGduty=256;        // Duty cycle range: [0,512]
  460.     AWGOffset=0;        // 0V offset
  461.     desiredF = 100000;  // 1kHz
  462.     BuildWave();
  463.     while(step<7) {
  464.         while(!testbit(TCD1.INTFLAGS, TC1_OVFIF_bp));   // wait for refresh timeout
  465.         setbit(TCD1.INTFLAGS, TC1_OVFIF_bp);
  466.         // Acquire data

  467.         // Display waveform
  468.         i=0; sum=0;
  469.         do {
  470.             data=addwsat(CH1.data[i],CH1.offset);
  471.             sum+=data;
  472.             set_pixel(i>>1, data>>2);    // CH1
  473.         } while(++i);
  474.         average=(uint8_t)(sum>>8);

  475.         switch(step) {
  476.             case 0: // Connect AWG to CH1
  477.                 tiny_printp(0,0,PSTR("AWG Calibration Connect AWG CH1 Press 5 to start"));
  478.                 step++;
  479.             break;
  480.             case 1:
  481.                 if(key) {
  482.                     if(key==KC) step++;
  483.                     else step=7;         // Did not press 5 -> exit
  484.                 }
  485.             break;
  486.             case 2: // Output 0V from AWG
  487.                 AWGAmp=1;         // Amplitude range: [0,127]
  488.                 AWGtype=1;        // Waveform type
  489.                 BuildWave();
  490.                 tiny_printp(0,3,PSTR("Adjusting offset"));
  491.                 // ADS931 power, output enable, CH gains
  492. //                PORTE.OUT = 0;
  493.                 CH1.offset=(signed char)eeprom_read_byte(&offsetsCH1[0]);
  494.                 step++;
  495.                 bestoffset = 0;
  496.                 test = 0;
  497.                 bestmeasure1=0;
  498.                 DACB.OFFSETCAL = 0;
  499.             break;
  500.             case 3: // Adjust Offset
  501.                 if(abs((int16_t)average-128)<abs((int16_t)bestmeasure1-128)) {    // Current value is better
  502.                     bestoffset = test;
  503.                     bestmeasure1=average;
  504.                     lcd_goto(0,4);
  505.                     if(bestoffset>=0x40) printN(0x40-bestoffset);
  506.                     else printN(bestoffset);
  507.                 }
  508.                 lcd_line(0,bestmeasure1>>1,127,bestmeasure1>>1);
  509.                 test++;
  510.                 DACB.OFFSETCAL = test;
  511.                 if(test>=128) {
  512.                     step++;
  513.                     DACB.OFFSETCAL = bestoffset;   // Load DACA offset calibration
  514.                 }
  515.             break;
  516.             case 4: // Output -1.75V from AWG
  517.                 AWGAmp=0;           // Full Amplitude
  518.                 AWGtype=1;          // Waveform type
  519.                 AWGOffset=112;      // Offset = -1.75
  520.                 BuildWave();
  521.                 tiny_printp(0,5,PSTR("Adjusting gain"));
  522. //                PORTE.OUT = 4;  // 0.5V / div
  523.                 CH1.offset=(signed char)eeprom_read_byte(&offsetsCH1[4]);
  524.                 step++;
  525.                 bestgain = 0;
  526.                 test=0;
  527.                 bestmeasure2=0;
  528.                 DACB.GAINCAL = 0;
  529.             break;
  530.             case 5: // Adjust gain
  531.                 // (1.75/0.5)*32+128)*256 = 61440
  532.                 if(abs((int32_t)sum-61696)<abs((int32_t)bestmeasure2-61696)) {    // Current value is better
  533.                     bestgain = test;
  534.                     bestmeasure2=sum;
  535.                     lcd_goto(0,6);
  536.                     if(bestgain>=0x40) printN(0x40-bestgain);
  537.                     else printN(bestgain);
  538.                 }
  539.                 test++;
  540.                 DACB.GAINCAL = test;
  541.                 if(test>=128) {
  542.                     step++;
  543.                     DACB.GAINCAL = bestgain;
  544.                 }
  545.             break;
  546.             case 6: // Calibration complete
  547.                 // Save calibration results
  548.                 AWGAmp=0;
  549.                 eeprom_write_byte(&EEDACoffset, bestoffset);    // Save offset calibration
  550.                 eeprom_write_byte(&EEDACgain, bestgain);        // Save gain calibration
  551.                 tiny_printp(0,15,PSTR("Cal complete"));
  552.                 step++;
  553.             break;
  554.         }
  555.     }
  556.     // Restore Waveform
  557.     LoadAWGvars();              // Load AWG settings
  558.     BuildWave();                // Construct AWG waveform
  559. }*/

  560. void Restore(void) {
  561.     key=0;
  562.     clr_display();
  563.     tiny_printp(0,0,PSTR("PRESS K1 TO RESTORE DEFAULTS"));
  564.     show_display();
  565.     while(!key);
  566.     if(key!=KA) {
  567.         key=0;
  568.         return;
  569.     }
  570.     key=0;
  571.     srate = 6;              // Sampling rate, start with 512uS/s
  572.     tdelay = 0;             // Trigger delay
  573.     tlevel = 128;           // Trigger level
  574.     tpre = 128;             // Number of Pre Trigger samples
  575.     tsource = 1;            // Trigger source, start with CH1
  576.     CH2.option  = 0x01;     // CH2 on, 5V/div
  577.     CH2.gain    = 1;        // CH2 gain
  578.     CH2.position = -32;            // CH2 vertical position
  579.     CH1.option  = 0x01;     // CH1 on, 5V/div
  580.     CH1.gain    = 1;        // CH1 gain
  581.     CH1.position = -96;     // CH1 vertical position
  582.     CHD.option  = 0x04;     // CHD off, thick line when low
  583.     CHD.param   = 0x00;     // Decode parameters
  584.     CHD.decode  = 0x00;     // Decode
  585.     CHD.mask    = 0xFF;     // Mask logic inputs
  586.     CHD.position = 0;       // CHD vertical position
  587.     Mcursor     = 0x00;     // Cursors off
  588.     MStatus     = 0x01;     // Set free trigger
  589.     Mset        = 0x1C;     // Set scope mode, show settings, line
  590.     MFFT        = 0x21;     // Use hamming window, no logarithm
  591.     display     = 0x01;     // Standard grid
  592.     SaveEE();
  593.     AWG.type     = 1;        // Type
  594.     AWG.amp      = -64;          // Amplitude
  595.     AWG.offset   = 0;        // Offset
  596.     AWG.duty     = 256;      // Duty cycle high byte
  597.     AWG.desiredF = 100000;   // desired F x 100
  598.     SaveAWGvars();
  599.     tiny_printp(0,2,OKtext);
  600.     show_display();
  601.     _delay_ms(1000);
  602. }

  603. // Configures the Screen Saver time out
  604. void ScreenSaver(uint8_t minutes) {
  605.     RTC.PER = (uint16_t)(minutes)*60;
  606.     RTC.CNT = 0;
  607.     if(minutes) {
  608.         RTC.INTCTRL = 0x01;     // Generate low level interrupt
  609.         RTC.CTRL = 0x07;        // Divisor 1024 (1 second per count)
  610.     }
  611.     else {
  612.         RTC.INTCTRL = 0;
  613.         RTC.CTRL = 0;
  614.     }
  615. }

  616. // RTC clock, this function is called when the sleep timeout has been reached
  617. ISR(RTC_OVF_vect) {
  618.     GLCD_LcdOff();
  619.     SaveEE();       // Save MSO settings
  620.     SaveAWGvars();  // Save AWG settings
  621.     SLEEP.CTRL = SLEEP_SMODE_PDOWN_gc | SLEEP_SEN_bm;
  622. ……………………

  623. …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼



所有資料51hei提供下載:
原理圖.rar (193.79 KB, 下載次數(shù): 18)
圖片.rar (474.94 KB, 下載次數(shù): 12)
驅(qū)動(dòng)及源碼.rar (905.83 KB, 下載次數(shù): 14)














評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏2 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表
主站蜘蛛池模板: 日韩欧美在线一区 | 视频一区中文字幕 | 亚洲国产精品成人久久久 | 91精品国产91久久久久青草 | 美女视频h | 91av在线免费看 | 四虎影| 国产午夜精品久久久 | 亚洲成人精品国产 | 日本aⅴ中文字幕 | 一级黄色片在线免费观看 | 伊人精品在线 | 日本成人在线播放 | 中文字幕免费在线 | 一区二区三区国产精品 | 日韩毛片 | 国产成人小视频 | 九九九久久国产免费 | 国产区第一页 | 成人在线精品视频 | 91亚洲国产成人久久精品网站 | 欧美成人h版在线观看 | 精品久久久久久久久久久久久久 | 成人免费av| 国产激情精品一区二区三区 | jdav视频在线观看免费 | 日日夜夜草 | 成人精品一区 | 久久成人免费视频 | 亚洲欧美成人影院 | 一区二区在线 | 91在线精品一区二区 | 天天操天天插天天干 | 青青草综合网 | 国产精品区一区二区三区 | 亚洲综合精品 | 欧美一区二区在线视频 | 亚洲在线看 | www.青娱乐| 日韩另类| 久久久久综合 |