各位先進,不好意思,小弟這邊有個問題想要提問,小弟現在是在實做一個光感測器經C8051F340 ADC轉換後再經USB傳給PC的裝置,程式皆是以Silicon Labs的Sample code改的,現在小弟的問題是,ADC0輸出的結果都會突然下降,例如:輸出值為160,會突然下降到10以下,下降後會在回來160然後又再下降,不知是什麼問題,已經困惑我多時了,希望各位先進可以給小弟一些建議,十分感謝!!
// Includes
#include "compiler_defs.h"
#include "C8051f340_defs.h"
#include <stddef.h>
#include "USB_API.h"
#define INTERRUPT_USBXpress 17
// Global CONSTANTS
#define Sw1 0x01
#define Sw2 0x02
#define SYSCLK 24500000
U8 Switch1State = 0;
U8 Switch2State = 0;
U8 Toggle1 = 0;
U8 Toggle2 = 0;
U8 flicker = 0x00;
U8 Out_Packet[8] = {0,0,0,0,0,0,0,0}; //從HOST接收(讀)
U8 In_Packet[8] = {0,0,0,0,0,0,0,0}; //傳送給HOST(寫)
/*** [BEGIN] USB Descriptor Information [BEGIN] ***/
SEGMENT_VARIABLE(USB_VID, U16, SEG_CODE) = 0x10C4;
SEGMENT_VARIABLE(USB_PID, U16, SEG_CODE) = 0xEA61;
SEGMENT_VARIABLE(USB_MfrStr[], U8, SEG_CODE) =
{
0x1A,
0x03,
'S',0,
'i',0,
'l',0,
'i',0,
'c',0,
'o',0,
'n',0,
' ',0,
'L',0,
'a',0,
'b',0,
's',0
};
SEGMENT_VARIABLE(USB_ProductStr[], U8, SEG_CODE) =
{
0x10,
0x03,
'U',0,
'S',0,
'B',0,
' ',0,
'A',0,
'P',0,
'I',0
};
SEGMENT_VARIABLE(USB_SerialStr[], U8, SEG_CODE) =
{
0x0A,
0x03,
'1',0,
'2',0,
'3',0,
'4',0
};
SEGMENT_VARIABLE(USB_MaxPower, U8, SEG_CODE) = 15;
SEGMENT_VARIABLE(USB_PwAttributes, U8, SEG_CODE) = 0x80;
SEGMENT_VARIABLE(USB_bcdDevice, U16, SEG_CODE) = 0x0100;
//-----------------------------------------------------------------------------
// Function Prototypes
//-----------------------------------------------------------------------------
void Timer_Init(void);
void Adc_Init(void);
void Port_Init(void);
void Suspend_Device(void);
void Initialize(void);
void Delay(unsigned int x);
//-----------------------------------------------------------------------------
// Main Routine
//-----------------------------------------------------------------------------
void main(void)
{
PCA0MD &= ~0x40;
USB_Clock_Start();
USB_Init(USB_VID,USB_PID,USB_MfrStr,USB_ProductStr,USB_SerialStr,USB_MaxPower,USB_PwAttributes,USB_bcdDevice);
Initialize();
USB_Int_Enable();
EA=1;
while (1)
{
In_Packet[0] = Switch1State;
In_Packet[1] = Switch2State;
In_Packet[2] = 0x00;
In_Packet[3] = 0x00;
In_Packet[4] = flicker;
}
}
//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------
//-------------------------
// Port_Init
//-------------------------
// Port Initialization
// - Configure the Crossbar and GPIO ports.
//
void Port_Init(void)
{
P2MDIN = 0xFB;
P0MDOUT |= 0x0F;
P1MDOUT |= 0x0F;
P2MDOUT |= 0x0C;
P2SKIP = 0x04; //0x20
XBR0 = 0x00;
XBR1 = 0x40;
}
//-------------------------
// Timer_Init
//-------------------------
// Timer initialization
// - 1 mhz timer 2 reload, used to check if switch pressed on overflow and
// used for ADC continuous conversion
//
void Timer_Init(void)
{
TMR2CN = 0x00;
CKCON &= ~0xF0;
TMR2RL = -(24500000 / 12);
TMR2 = 0xffff;
ET2 = 1;
TR2 = 1;
}
//-------------------------
// Adc_Init
//-------------------------
// ADC initialization
// - Configures ADC for single ended continuous conversion or Timer2
//
void Adc_Init (void)
{
ADC0CN = 0x02;
REF0CN = 0x00;
AMX0P = 0x02;
AMX0N = 0x1E;
ADC0CF = ((SYSCLK/3000000)-1)<<3;
ADC0CF |= 0x00;
EIE1 |= 0x08;
AD0EN = 1;
}
//-------------------------
// Suspend_Device
//-------------------------
// Called when a DEV_SUSPEND interrupt is received.
// - Disables all unnecessary peripherals
// - Calls USB_Suspend()
// - Enables peripherals once device leaves suspend state
//
void Suspend_Device(void)
{
// Disable peripherals before calling USB_Suspend()
P0MDIN = 0x00;
P1MDIN = 0x00;
P2MDIN = 0x00;
P3MDIN = 0x00;
REF0CN &= ~0x0E;
ADC0CN &= ~0x80;
ET2 = 0;
USB_Suspend();
// Once execution returns from USB_Suspend(), device leaves suspend state.
// Reenable peripherals
REF0CN = 0x0E;
ADC0CN |= 0x80;
P0MDIN = 0xFF;
P1MDIN = 0x7F;
P2MDIN = 0xFF;
P3MDIN = 0x01;
ET2 = 1;
}
//-------------------------
// Initialize
//-------------------------
// Called when a DEV_CONFIGURED interrupt is received.
// - Enables all peripherals needed for the application
//
void Initialize(void)
{
Port_Init();
Timer_Init();
Adc_Init();
}
//-------------------------
// Timer2_ISR
//-------------------------
// Called when timer 2 overflows, check to see if switch is pressed,
// then watch for release.
//
INTERRUPT(Timer2_ISR, INTERRUPT_TIMER2)
{
if (!(P2 & Sw1)) // Check for switch #1 pressed
{
if (Toggle1 == 0) // Toggle is used to debounce switch
{ // so that one press and release will
Switch1State = ~Switch1State; // toggle the state of the switch sent
Toggle1 = 1; // to the host
}
}
else Toggle1 = 0; // Reset toggle variable
if (!(P2 & Sw2)) // This is the same as above, but for Switch2
{
if (Toggle2 == 0)
{
Switch2State = ~Switch2State;
Toggle2 = 1;
}
}
else Toggle2 = 0;
TF2H = 0; // Clear Timer2 interrupt flag
}
//-------------------------
// Adc_ConvComplete_ISR
//-------------------------
// Called after a conversion of the ADC has finished
// - Updates the appropriate variable for either potentiometer or temperature sensor
// - Switches the Adc multiplexor value to switch between the potentiometer and temp sensor
//
INTERRUPT(Adc_ConvComplete_ISR, INTERRUPT_ADC0_EOC)
{
//U32 flicker;
U8 ADC0_A;
U8 ADC0_N;
U8 flicker_a;
AD0INT = 0; // Clear ADC0 conv. complete flag
if (AMX0P == 0x02) // This switches the AMUX between
{
ADC0_A = ADC0;
Delay(200);
ADC0_N = ADC0;
flicker_a = ADC0_A-(ADC0_A/32)+(ADC0_N/32); //result;
if(flicker_a > 21)
{
flicker = flicker_a;
}
AMX0P = 0x02; //0x04; // switch to potentiometer ('F340 - P2.5)
ADC0CF = 0xF8; // place ADC0 in left-adjusted mode
}
else
{
// Potentiometer = ADC0H;
AMX0P = 0x02; //1E; // switch to temperature sensor
ADC0CF = 0xF8; // place ADC0 in right-adjusted mode
}
AD0INT = 1;
Block_Write(In_Packet, 8);
}
// Example ISR for USB_API
INTERRUPT(USB_API_TEST_ISR, INTERRUPT_USBXpress)
{
U8 INTVAL = Get_Interrupt_Source(); //得到中斷類型
if (INTVAL & RX_COMPLETE) //數據發送完成
{
Block_Read(Out_Packet, 8);
}
if (INTVAL & DEV_SUSPEND) //設備掛起
{
Suspend_Device();
}
if (INTVAL & DEV_CONFIGURED) //設備初始化
{
Initialize();
}
}
void Delay(unsigned int x)
{
unsigned int a,b;
for(a=x;a>0;a--)
for(b=100;b>0;b--);
}
// Startup code for SDCC to disablt WDT before initializing variables so that
// a reset does not occur
#if defined SDCC
void _sdcc_external_startup (void)
{
PCA0MD &= ~0x40; // Disable Watchdog timer
}
#endif
// ============================================================================
// *** END OF FILE ***
// ============================================================================