|
|
View previous topic :: View next topic |
Author |
Message |
daniaccount
Joined: 04 Apr 2012 Posts: 1
|
Interrupt Problem with Acquisition Board |
Posted: Thu Apr 05, 2012 7:35 am |
|
|
Acquisition board
My application is to get an acquisition of 50KHZ store them in ping and pong buffers then put them trough usb port to the PC.
I'm using timer2 (20 microsecond) to get the analog data. I developed a c++ application to read from usb and trace the acquisition in a file. Comparing this acquisition file with the original one, I notice that some data are lost I put a toggling in timer 2. So I notice that a drift occurs in this toggle just when I use the command usb_puts to put the buffer to usb port, otherwise everything is ok. I put timer2 to high priority but nothing is changed. I tried to send just one packet of 64 bytes with usb_puts and eliminated the whole code in timer2 except toggling but the drift problem is the same. I didn't find any relation between this command or usb interrupt and timers interrupt. This problem is the same with timer0 and timer1.
This is my code:
Code: |
#include <18F4550.h>
#DEVICE HIGH_INTS=TRUE
#PRIORITY TIMER2
#DEVICE ADC=16
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=20000000)
/////////////////////////////////////////////////////////////////////////////
//
// CCS Library dynamic defines. For dynamic configuration of the CCS Library
// for your application several defines need to be made. See the comments
// at usb.h for more information
//
/////////////////////////////////////////////////////////////////////////////
#DEFINE USB_HID_DEVICE FALSE
#define USB_EP1_TX_ENABLE USB_ENABLE_BULK //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE USB_ENABLE_BULK //turn on EP1 for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE 64 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE 64 //size to allocate for the rx endpoint 1 buffer
#include <pic18_usb.h>
#include <usb_desc.h> //USB Configuration and Device descriptors for this UBS device
#include <usb.c> //handles usb setup tokens and get descriptor reports
//#define size 294
#define size 8
#define LED1 PIN_D0
#define LED2 PIN_D1
unsigned int16 packet_size;
static int16 index;
#LOCATE index = 0x31
int16 i ;
int1 BUFFER_COMPLETE_FLAG ;
int16 value;
int8 PingBuffer[size];
int8 PongBuffer[size];
int8 PingPong;
int8 Ext_Buffer[size];
#INT_TIMER2 HIGH
void TIMER2_isr(void) {
output_toggle(LED1);
value=read_adc(ADC_READ_ONLY );
read_adc(ADC_START_ONLY );
value=(int16)((int16)value ^ 0x8000);
if (PingPong)
{
PingBuffer[index]=make8(value,1);
index++;
PingBuffer[index]=make8(value,0);
if(index<(size-1)) index++; else {index=0; BUFFER_COMPLETE_FLAG=1;PingPong = 0;}
}
else
{
PongBuffer[index]=make8(value,1);
index++;
PongBuffer[index]=make8(value,0);
if(index<(size-1)) index++; else {index=0; BUFFER_COMPLETE_FLAG=1;PingPong = 1;}
}
}
#zero_ram
void main( void )
{
PingPong = 1;
BUFFER_COMPLETE_FLAG=0;
setup_adc_ports(AN0|VSS_VDD);
setup_adc(ADC_CLOCK_INTERNAL);
setup_psp(PSP_DISABLED);
setup_spi(SPI_SS_DISABLED);
setup_wdt(WDT_OFF);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_1);
setup_timer_2(T2_DIV_BY_1,112,2); //20 micro second
setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
enable_interrupts(INT_TIMER2);
enable_interrupts(GLOBAL);
usb_init_cs();
while( TRUE )
{
if (BUFFER_COMPLETE_FLAG)
{
BUFFER_COMPLETE_FLAG=0;
usb_task();
if (PingPong)
usb_puts( 1,PongBuffer,size,10);
else
usb_puts( 1,PingBuffer,size,10);
}
}
}
|
Please can I get help with this issue?!
Best Regards. _________________ DAN |
|
|
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Thu Apr 05, 2012 8:35 am |
|
|
Some questions for you:
What is the total conversion time when using the internal clock?
What is the interrupt latency time?
How much time does your interrupt code take to run?
If am pretty sure that your interrupt code is taking too long and your ADC won't convert fast enough, remembering that the processor will take the interrupt latency time BEFORE it can service the ADC, so the absolute minimum cycle time is the latency PLUS the ADC conversion time, and that doesn't take into account any code in ISR, which in any case looks to be more complicated than it really needs to be. With any 18 series all that is always going longer than 20us, so you are going to miss interrupts and sample slower than you expect.
Its good to see you're overlapping conversions with processing but even so 50kHz for an 18 series is not realistic.
It may/should be possible on a 24, dsPIC or 32 series.
RF Developer |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Thu Apr 05, 2012 9:06 am |
|
|
Seriously, you are not going to do this.
You are running the ADC off the internal clock. Typical cycle time for this is 4uSec. An ADC sample takes 11 cycles off the clock. Then the ADC takes a minimum of Tacq to reacquire the signal after the reading (6.4uSec). So the absolute fastest that readings can be taken, and reflect the incoming signal at all well, is 50.4uSec/sample. Just over 20KHz.....
First thing to do is change to the right clock. Boost your CPU frequency to 40MHz, and use CLOCK/64 for the ADC, which then gives 1.6uSec/cycle, and brings the maximum allowable sample rate up to 41.6KHz. At this the CPU will be able to do basically nothing else.
However you then have to realise that sampling will have to stop for USB interrupts. USB transactions _have_ to be serviced, with minimal delays, or the interface will fail. Switching buffers means the delays can be quite short, but they will still be present.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|