我用C8051f120内置12位ADC,直流信号可以采集,但采集的交流信号转换为模拟电压却总是等于Vref值,这个是为什么呀?
我是直接将函数发生器的输出(交流叠加直流所有信号为正极性)加到AIN0.0脚的。下面是我的源程序:
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include <math.h>
#include "c8051f120.h"
#include "FFT_Code_Tables.h" // Code Tables for FFT routines
//-----------------------------------------------------------------------------
// 16-bit SFR Definitions for ‘F12x
//-----------------------------------------------------------------------------
sfr16 DP = 0x82; // data pointer
sfr16 ADC0 = 0xbe; // ADC0 data
sfr16 ADC0GT = 0xc4; // ADC0 greater than window
sfr16 ADC0LT = 0xc6; // ADC0 less than window
sfr16 RCAP2 = 0xca; // Timer2 capture/reload
sfr16 RCAP3 = 0xca; // Timer3 capture/reload
sfr16 RCAP4 = 0xca; // Timer4 capture/reload
sfr16 TMR2 = 0xcc; // Timer2
sfr16 TMR3 = 0xcc; // Timer3
sfr16 TMR4 = 0xcc; // Timer4
sfr16 DAC0 = 0xd2; // DAC0 data
sfr16 DAC1 = 0xd2; // DAC1 data
sfr16 PCA0CP5 = 0xe1; // PCA0 Module 5 capture
sfr16 PCA0CP2 = 0xe9; // PCA0 Module 2 capture
sfr16 PCA0CP3 = 0xeb; // PCA0 Module 3 capture
sfr16 PCA0CP4 = 0xed; // PCA0 Module 4 capture
sfr16 PCA0 = 0xf9; // PCA0 counter
sfr16 PCA0CP0 = 0xfb; // PCA0 Module 0 capture
sfr16 PCA0CP1 = 0xfd; // PCA0 Module 1 capture
//-----------------------------------------------------------------------------
// Global CONSTANTS and Variable Type Definitions
//-----------------------------------------------------------------------------
#define NUM_BITS 16 // Number of Bits in Data
#define DATA_BEGIN 0x0000 // Beginning of XRAM Data
#define SYSCLK 49000000 // Output of PLL derived from
// (INTCLK*2/1)
#define VREF 3.3 //参考电压
#define SAMPLE_RATE 20480 // Sample frequency in Hz
#define RUN_ONCE 1 // Setting to a non-zero value will
// cause the program to stop after one
// data set.
unsigned int xdata Redata[NUM_FFT];
char xdata data_H[NUM_FFT],data_L[NUM_FFT];
int xdata i;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------
void SYSCLK_Init (void);
void PORT_Init (void);
void ADC0_Init (void);
void TIMER3_Init (int counts);
void ADC0_ISR (void);
void delay_us(unsigned int);
unsigned int BinNum;
bit Conversion_Set_Complete; // This indicates when the data has been
// stored, and is ready to be processed
// using the FFT routines
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------
void main()
{
int xdata i;
unsigned int xdata data1[NUM_FFT],data2[NUM_FFT],data3[NUM_FFT];
float xdata Voltage[NUM_FFT];
char xdata data_H1[NUM_FFT],data_L1[NUM_FFT];
//disable watchdog timer
WDTCN = 0xde;
WDTCN = 0xad;
SYSCLK_Init(); // initialize external clock and PLL
PORT_Init (); // set up Port I/O
TIMER3_Init (SYSCLK/SAMPLE_RATE); // initialize Timer3 to overflow at
// <SAMPLE_RATE>
ADC0_Init (); // init ADC0
EA = 1; // globally enable interrupts
while (1)
{
ADC_Index = 0;
Conversion_Set_Complete = 0;
EIE2 |= 0x02; // enable ADC interrupts
SFRPAGE = LEGACY_PAGE;
while(!Conversion_Set_Complete);
for(i=0;i<=NUM_FFT;i++)
{
data1[i]=Real[i];
data_H1[i] = data_H[i];
data_L1[i] = data_L[i];
data2[i] = data1[i] >> 4;
Voltage[i]=data2[i]/4096.0*VREF; //计算实际电压
}
if (RUN_ONCE)
while(1);
}
} // END MAIN
//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
void SYSCLK_Init (void) //49MHz
{
int i;
char old_SFRPAGE = SFRPAGE; // Store current
SFRPAGE = CONFIG_PAGE;
OSCICN = 0x83;
CCH0CN &= ~0x20;
SFRPAGE = LEGACY_PAGE;
FLSCL = 0x90;
SFRPAGE = CONFIG_PAGE;
CCH0CN |= 0x20;
PLL0CN |= 0x01;
PLL0DIV = 0x01;
PLL0FLT = 0x21;
PLL0MUL = 0x02;
for (i = 0; i < 15; i++); // Wait 5us for initialization
PLL0CN |= 0x02;
while ((PLL0CN & 0x10) == 0);
CLKSEL = 0x22;
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
void PORT_Init (void)
{
SFRPAGE = CONFIG_PAGE;
XBR2 = 0x40;
}
//-----------------------------------------------------------------------------
// ADC0_Init
//-----------------------------------------------------------------------------
//
// Configure ADC0 to use Timer3 overflows as conversion source, to
// generate an interrupt on conversion complete, and to use left-justified
// output mode. Enables ADC0 end of conversion interrupt. Enables ADC0.
//
void ADC0_Init (void)
{
char old_SFRPAGE = SFRPAGE; // Store current SFRPAGE
SFRPAGE = ADC0_PAGE; // Switch to ADC0 Setup Page
ADC0CN = 0x05; // ADC disabled; normal tracking
// mode; ADC conversions are initiated
// on overflow of Timer3, left-justify
REF0CN = 0x03; // enable on-chip VREF and output buffer
AMX0CF = 0x00; // Single-ended AIN0.0 input
AMX0SL = 0x00;
ADC0CF = (SYSCLK/(2*2500000)) << 3; // ADC conversion clock <= 2.5MHz
ADC0CF |= 0x00; // PGA gain = 1
AD0EN = 1; // enable ADC0
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
//-----------------------------------------------------------------------------
// TIMER3_Init
//-----------------------------------------------------------------------------
//
// Configure Timer3 to auto-reload at interval specified by <counts> (no
// interrupt generated) using SYSCLK as its time base.
//
void TIMER3_Init (int counts)
{
char old_SFRPAGE = SFRPAGE; // Save Current SFR page
SFRPAGE = TMR3_PAGE; // Switch to Timer3 Setup Page
TMR3CN = 0x00; // Stop Timer3; Clear TF3
TMR3CF = 0x08; // use SYSCLK as timebase
RCAP3 = -counts; // Init reload values
TMR3 = 0xffff; // set to reload immediately
EIE2 &= ~0x01; // disable Timer3 interrupts
TR3 = 0x01; // start Timer3
SFRPAGE = old_SFRPAGE; // restore SFRPAGE
}
//-----------------------------------------------------------------------------
// Interrupt Service Routines
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// ADC0_ISR
//-----------------------------------------------------------------------------
//// ADC end-of-conversion ISR
// The ADC sample is stored in memory, and an index variable is incremented.
// If enough samples have been taken to process the FFT, then a flag is set,
// and ADC interrupts are disabled until the next set is requested.
//
void ADC0_ISR (void) interrupt 15 using 3
{
AD0INT = 0; // clear ADC conversion complete
// flag
Real[ADC_Index] = ADC0; // store ADC value
data_H[ADC_Index] = ADC0H;
data_L[ADC_Index] = ADC0L;
ADC_Index++; // Increment the index into memory
if (ADC_Index >= NUM_FFT) // If enough samples have been collected
{
Conversion_Set_Complete = 1; // Tell the Main Routine and...
EIE2 &= ~0x02; // disable ADC interrupts
}
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
很简单了,你接了两级运放,问题就出在这两级运放上。有几种可能,
运放带宽不够。这个没办法,想办法调增益以改善。
运放干扰大。这个得想办法屏蔽了。
运放输入电阻太小。这个也得调增益。
一周热门 更多>