|
|
View previous topic :: View next topic |
Author |
Message |
itisme
Joined: 10 Feb 2013 Posts: 3
|
12 bit ADC over USB serial @ 10kHz |
Posted: Sun Feb 10, 2013 1:19 pm |
|
|
Hello,
I'm trying sample one channel ADC at 10kHz and transmit the data over USB serial. The code is below.
Unfortunately USB halt after transmitting several tens of samples. I think the problem with the speed of "printf(usb_cdc_putc,...)", but have no idea how to solve it.
I'll appreciate for help.
[/code]
Code: | #include <18F2553.h>
#device ADC = 12
//configure a 20MHz crystal to operate at 48MHz
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
//#use rs232(baud = 115200, xmit = PIN_C6, rcv = PIN_C7)
#include <usb_cdc.h>
//#include <input.c>
//#include <stdlib.h>
unsigned int16 adc_data;
int32 i=0;
int8 s2r=1; //s2r - Seconds to record
int32 c2t; //c2r - Cycles to transmit
//Initializing the RTOS Program
#use rtos(timer = 0, minor_cycle = 10us)
#task(rate = 100us, max = 10us) // 100uS -> 10kHz
void transmit_over_usb()
{
//adc_data = read_adc();
printf(usb_cdc_putc, "%Lu\n\r", read_adc());
if(++i==10000)//(i == c2t)
rtos_terminate( );
}
void main()
{
#use standard_io(A)
setup_adc_ports(ALL_ANALOG);
setup_adc(ADC_CLOCK_DIV_64); // for 48MHz OSC
//setup_adc(ADC_CLOCK_DIV_16); // For 20 MHz OSC
set_adc_channel(0);
delay_us(10);
usb_cdc_init();
usb_init();
while(!usb_cdc_connected()) {}
do
{
usb_task();
if (usb_enumerated())
{
wait_usb: // Label
while (usb_cdc_getc() != 'r') ;
i=0;
s2r=1;
c2t = (s2r*1e6)/250; // How many cycles to transmit the data. NOTE: Denumerator should be equal to "rate" in main RTOS task
output_high(PIN_B0);
rtos_run();
output_low(PIN_B0);
// printf("Done!\n\r");
printf(usb_cdc_putc,"5002\n\r");
goto wait_usb;
}
} while (TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19548
|
|
Posted: Sun Feb 10, 2013 3:35 pm |
|
|
Time.
You certainly have not got time to do this with the RTOS. 10uSec, is every 120 instructions. The printf, will take at least this long (you are asking it to format the number, so it has to perform repeated divisions. Each int16 division takes 26uSec on it's own.....
Not even close to possible.
Best Wishes |
|
|
itisme
Joined: 10 Feb 2013 Posts: 3
|
|
Posted: Mon Feb 11, 2013 1:01 am |
|
|
Hi,
Thank you for reply.
Any idea how can I transmit A/D data without formatting then decode it at PC side?
Best regards! |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19548
|
|
Posted: Mon Feb 11, 2013 2:00 am |
|
|
Don't use the RTOS. This has a significant overhead you don't want....
Just have a timer tick using (say) Timer2, set to interrupt at 10uSec intervals (best timer for this). Then don't use an interrupt handler, just poll the interrupt flag. Save time by starting the new ADC conversion as soon as you have read the last. So (hypothetical only):
Code: |
int16 icount,adc_val;
setup_timer_2(T2_DIV_BY_1, 119,1); //will trigger every 120 instructions
set_timer2(0);
clear_interrupt(INT_TIMER2);
read_adc(ADC_START_ONLY);
delay_us(8); //ensure the first conversion completes
for (icount=0;icount<10000;icount++) {
while (!interrupt_active(INT_TIMER2)) ; //wait for interrupt to fire
//get here when the timer interrupt triggers
clear_interrupt(INT_TIMER2);
adc_val=read_adc(ADC_READ_ONLY); //read the already ready ADC
read_adc(ADC_START_ONLY);
//Now start the next ADC conversion. This will be going on _while_
//the data is being sent. Overlapped working.....
usb_cdc_putc_fast(make8(adc_val,0));
usb_cdc_putc_fast(make8(adc_val,1)); //send LSB, then MSB
}
|
It'll still be very tight on time (two putc's). You might need to do direct I/O to the USB driver instead. As written, it'll throw away characters if the USB can't keep up.
Best Wishes |
|
|
itisme
Joined: 10 Feb 2013 Posts: 3
|
|
Posted: Mon Feb 11, 2013 9:05 am |
|
|
I'm really appreciate for idea ...
All the best! |
|
|
|
|
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
|