CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

USB with Timer1 interrupt

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
prayami



Joined: 22 Dec 2004
Posts: 78

View user's profile Send private message

USB with Timer1 interrupt
PostPosted: Mon Aug 29, 2005 11:18 pm     Reply with quote

Hi...I have run example program of USB for 18F4550. And It is working
fine means windows device manager recognize the HID device properly.

Now I added the Timer1 Interrupt which is generating pulses of 10KHz.

Means interrupting every 50us. And it is now creating problem. Some
time it is recognize properly and sometime giving error and having
yellow ! sign indicating error in recognizing the device.

Any body used interrupt with USB code? How can I use the same?

Thanks.....
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Mon Aug 29, 2005 11:51 pm     Reply with quote

Just today I got my copy of "USB Complete" in the mail from Amazon. I've read the first two chapters, and I can tell you that the host PC is not very forgiving at all in the timing during enumeration. This means that when the PC first establishes contact with the usb device, timing is absolutely critical - it expects quick replies. You probably shouldn't have timer 1's interrupt enabled during this time.
Ttelmah
Guest







PostPosted: Tue Aug 30, 2005 4:04 am     Reply with quote

50uSec call intervals. You don't say what frequency you are running the processor at?. Assume 40MHz (normal for the USB confgurations). This corresponds to 500 instruction times between interrupts. Even assuming no 'handler' time is involved, the chip will be spending about 1/4 of it's time, just running the global handler. If the code in the interrupt is at all significant, the ability of the chip to do other things will be becoming massively degraded. How long is the interrupt handler?. The interrupt behaviour on the PIC, is (to my mind), rather poor, involving a lot of overhead for tidying up. Post the handler used in the 10KHz interrupt. It may be possible to use this with the 'fast' handler, and save less registers than CCS normally does, to give better responses.

Best Wishes
prayami



Joined: 22 Dec 2004
Posts: 78

View user's profile Send private message

PostPosted: Tue Aug 30, 2005 3:07 pm     Reply with quote

Hi...

I am using PIC18F4550 using 20Mhz Crystal and following #fuses which
is allready there in the example program.

Quote:

#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)


If I run the example program then it is working correctly. But I have
modified the example program as below and now every 1 out of 6 attempt
approximately it is recognize and rest five times it does not. I just got
the latest update from CCS of PCH compiler.

Quote:


/////////////////////////////////////////////////////////////////////////
//// ////
//// ex_usb_hid.c ////
//// ////
//// A simple demo that shows how to use the HID class to send ////
//// and receive custom data from the PC. Normally HID is used ////
//// with pre-defined classes, such as mice and keyboards, but ////
//// can be used for vendor specific classes as shown in this ////
//// example. ////
//// ////
//// The first byte sent by the PIC is the ADC reading ////
//// on channel 0 (AN0), the second byte is the status of the ////
//// pushbutton. The two bytes sent by the PC are LED on/off ////
//// toggle status. If you want to change the protocol to ////
//// send/receive more than 2 bytes you must change the HID report ////
//// descriptor. ////
//// ////
//// CCS has provided an example Windows program that reads / writes ////
//// to the HID device provided in this example. This Windows ////
//// example is called hiddemo.exe. ////
//// ////
//// For extra documentation on developing your own code, see ////
//// the header files and comments located in the other files ////
//// of the CCS PIC USB drivers. ////
//// ////
//// This example will work with the PCM and PCH compilers. ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// ABOUT HID: ////
//// ////
//// HID devices are useful because HID drivers are generally ////
//// installed and supplied with modern operating systems. ////
//// However, since HID is a general device with general drivers ////
//// there are limitations to what a HID device can do: ////
//// ////
//// - A report (message) can't be larger than 255 bytes. ////
//// (A report or message != A packet) ////
//// ////
//// - On slow speed devices the max packet size is 8. ////
//// On a full speed device the max packet size is 64. ////
//// ////
//// - Data is obtained on the host / PC through polling the HID ////
//// device (PC polls the PIC) ////
//// ////
//// - On a full speed device, max polling rate is 1 transaction ////
//// per 1ms. This is 64000 bytes per second (64 byte packets ////
//// every 1ms). ////
//// ////
//// - On a slow speed device, max polling rate is 1 transaction ////
//// per 10ms. This is 800 bytes per second (8 byte packets every ////
//// 10ms) ////
//// ////
//// - No guarantee that polls will happen at a guaranteed rate. ////
//// If you want guaranteed transfer rate you must use Isochronous ////
//// transfers, which HID is not. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// WINDOWS DRIVERS: ////
//// ////
//// USB HID drivers come included with all Windows, starting ////
//// with Windows 98 and up. Windows 95 does not include USB ////
//// support, unless you are running Windows 95 Gold (aka OSR2, or ////
//// Windows 95b). ////
//// ////
//// If you plug in the USB device, and it is working, a "Found new ////
//// device" window should pop-up. The Add Device wizard then will ////
//// install the HID drivers automatically. ////
//// ////
//// If you plug in the USB device and do not get this window then ////
//// the device is not working, or USB does not work on your ////
//// computer. Goto the Device Manager (Right Click on my Computer, ////
//// it is located under one of the Tabs. It is located under the ////
//// Hardware tab of Windows2000), and make sure that "Universal ////
//// Serial Bus controllers" is installed. Open "Universal Serial ////
//// Bus controllers" and you should see 1 or more "USB Root Hubs". ////
//// If you see these then that's a good indication that USB is ////
//// working on your computer. If you see a question mark and ////
//// an unkown USB device then this is quite possibly your USB ////
//// device that is not working. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// NOTE ABOUT ENDPOINT BUFFER SIZE: ////
//// ////
//// Although this application sends and receives only 2 bytes from ////
//// the PC, this demo defines USB_EP1_TX_SIZE and USB_EP1_RX_SIZE ////
//// to 8 to allocate 8 bytes for these endpoint. These constants ////
//// are also used in the endpoint descriptor to specify the ////
//// endpoint max size. If you were concious of RAM savings you ////
//// could redefine these to 2 (or even 1!), but you would lose ////
//// throughput. The reason for throughput loss is that if you send ////
//// a packet that is the same size as the max packet size then ////
//// you need to send a 0 len packet to specify end of message ////
//// marker. The routines usb_puts() and usb_gets() send and ////
//// receive multiple packet message, waiting for a 0 len packet ////
//// or a packet that is smaller than max-packet size. ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// ////
//// VERSION HISTORY ////
//// ////
//// June 20th, 2005: 18fxx5x initial release. ////
//// ////
//// March 22nd, 2005: Cleanup to work with PIC18Fxx5x ////
//// ////
//// June 24th, 2004: Cleanup to work with updated USB API ////
//// ////
/////////////////////////////////////////////////////////////////////////
//// (C) Copyright 1996,2005 Custom Computer Services ////
//// This source code may only be used by licensed users of the CCS ////
//// C compiler. This source code may only be distributed to other ////
//// licensed users of the CCS C compiler. No other use, ////
//// reproduction or distribution is permitted without written ////
//// permission. Derivative programs created using this software ////
//// in object code form are not restricted in any way. ////
/////////////////////////////////////////////////////////////////////////

//set to 1 to use a PIC's internal USB Peripheral
//set to 0 to use a National USBN960x peripheral
#define __USB_PIC_PERIF__ 1

#if __USB_PIC_PERIF__

#DEFINE LED1 PIN_A5

#if defined(__PCM__)
#include <16C765.h>
#device *=16
#fuses HS,NOWDT,NOPROTECT
#use delay(clock=24000000)
#elif defined(__PCH__)
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN
#use delay(clock=48000000)
#endif
#else //use the National USBN960x peripheral
#DEFINE LED1 PIN_B3
#if defined(__PCM__)
#include <16F877A.h>
#device *=16
#fuses HS,NOWDT,NOPROTECT,NOLVP
#elif defined(__PCH__)
#include <18F452.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#endif
#use delay(clock=20000000)

#endif //endif check to see which peripheral to use

//#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)


/////////////////////////////////////////////////////////////////////////////
//
// 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
//
/////////////////////////////////////////////////////////////////////////////

//Tells the CCS PIC USB firmware to include HID handling code.
#DEFINE USB_HID_DEVICE TRUE

//the following defines needed for the CCS USB PIC driver to enable the TX endpoint 1
// and allocate buffer space on the peripheral
#define USB_EP1_TX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for IN bulk/interrupt transfers
#define USB_EP1_TX_SIZE 8 //allocate 8 bytes in the hardware for transmission

//the following defines needed for the CCS USB PIC driver to enable the RX endpoint 1
// and allocate buffer space on the peripheral
#define USB_EP1_RX_ENABLE USB_ENABLE_INTERRUPT //turn on EP1 for OUT bulk/interrupt transfers
#define USB_EP1_RX_SIZE 8 //allocate 8 bytes in the hardware for reception


/////////////////////////////////////////////////////////////////////////////
//
// If you are using a USB connection sense pin, define it here. If you are
// not using connection sense, comment out this line. Without connection
// sense you will not know if the device gets disconnected.
// (connection sense should look like this:
// 100k
// VBUS-----+----/\/\/\/\/\----- (I/O PIN ON PIC)
// |
// +----/\/\/\/\/\-----GND
// 100k
// (where VBUS is pin1 of the USB connector)
//
/////////////////////////////////////////////////////////////////////////////
//#define USB_CON_SENSE_PIN PIN_B2


/////////////////////////////////////////////////////////////////////////////
//
// Include the CCS USB Libraries. See the comments at the top of these
// files for more information
//
/////////////////////////////////////////////////////////////////////////////
#if __USB_PIC_PERIF__
#if defined(__PCM__)
#include <pic_usb.h> //Microchip PIC16C765 hardware layer for usb.c
#else
#include <pic18_usb.h> //Microchip 18Fxx5x hardware layer for usb.c
#endif
#else
#include <usbn960x.c> //National 960x hardware layer for usb.c
#endif
#include <usb_desc_hid.h> //USB Configuration and Device descriptors for this UBS device
#include <usb.c> //handles usb setup tokens and get descriptor reports


/////////////////////////////////////////////////////////////////////////////
//
// Configure the demonstration I/O
//
/////////////////////////////////////////////////////////////////////////////
#define LED2 PIN_B4
#define LED3 PIN_B5
#DEFINE BUTTON PIN_A4
#define LED_ON output_low
#define LED_OFF output_high

//-----Knock---------
//With respect to Knock Sensor
#define CHIP_SELECT PIN_D0 //for CS
#define INT_HOLD PIN_D1
#define KNOCK_CLK PIN_B1 //SCK

unsigned int16 IntTimer1, Tcounttimer1=24003;
int1 HighPulse=0;
int8 KnockValue;


int8 out_data[20];
int8 in_data[2];
int8 send_timer=0;

/////////////////////////////////////////////////////////////////////////////
//
// usb_debug_task()
//
// When called periodically, displays debugging information over serial
// to display enumeration and connection states. Also lights LED1 based upon
// enumeration and status.
//
/////////////////////////////////////////////////////////////////////////////
void usb_debug_task(void) {
static int8 last_connected;
static int8 last_enumerated;
int8 new_connected;
int8 new_enumerated;

new_connected=usb_attached();
new_enumerated=usb_enumerated();

if (new_enumerated)
LED_ON(LED1);
else
LED_OFF(LED1);
/*
if (new_connected && !last_connected)
printf("\r\n\nUSB connected, waiting for enumaration...");
if (!new_connected && last_connected)
printf("\r\n\nUSB disconnected, waiting for connection...");
if (new_enumerated && !last_enumerated)
printf("\r\n\nUSB enumerated by PC/HOST");
if (!new_enumerated && last_enumerated)
printf("\r\n\nUSB unenumerated by PC/HOST, waiting for enumeration...");
*/
last_connected=new_connected;
last_enumerated=new_enumerated;
}



#INT_TIMER1 // fast
void timer1_isr() {


if(HighPulse==0)
{
output_high(PIN_D2);
HighPulse=1;

}
else
{
output_low(PIN_D2);
HighPulse=0;


KnockValue=(int8)(read_adc());

}//if(HighPulse==1)

set_timer1(64936);



}//timer1_isr


void main() {


set_tris_b(0xFD);
set_tris_d(0x00);

LED_OFF(LED1);
LED_OFF(LED2);
LED_OFF(LED3);

delay_ms(5);

usb_init();

delay_ms(10);

//---Start Knock---------------------------
output_low(INT_HOLD); //disable any SPI transmission
output_low(KNOCK_CLK);

//setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
setup_spi(SPI_MASTER | SPI_H_TO_L | SPI_CLK_DIV_16);

output_low(CHIP_SELECT);


output_low(CHIP_SELECT);
spi_write(0x48); //Set the prescaler and SDO status
//spi_write(0x49); //Set the prescaler and SDO status
output_high(CHIP_SELECT);

delay_us(1);

output_low(CHIP_SELECT);
spi_write(0xE0); //Select the channel=1
//spi_write(0xE1); //Select the channel=2
output_high(CHIP_SELECT);

delay_us(1);

output_low(CHIP_SELECT);
//spi_write(0x18); //Set the band-pass center frequency
//spi_write(0x30); //Set the band-pass center frequency
spi_write(0x27); //Set the band-pass center frequency=6.27KHz
output_high(CHIP_SELECT);

delay_us(1);

output_low(CHIP_SELECT);
//spi_write(0x19); //Set the gain
//spi_write(0x94); //Set the gain=0.739
spi_write(0x8E); //Set the gain=1
//spi_write(0x80); //Set the gain=2

output_high(CHIP_SELECT);

delay_us(1);

output_low(CHIP_SELECT);
//spi_write(0xD8); //tried 0x98 //Set the integration time constant
//spi_write(0xC3); //Set the integration time constant=55us
spi_write(0xDF); //Set the integration time constant=600us
output_high(CHIP_SELECT);

delay_us(10);

output_high(CHIP_SELECT);

output_high(INT_HOLD); //disable any SPI transmission

#if defined(AN0)
setup_adc_ports(AN0);
#elif defined(AN0_AN1_AN3)
setup_adc_ports(AN0_AN1_AN3);
#else
#error CONFIGURE ADC PORTS SO WE CAN READ CHANNEL 0
#endif

setup_adc(ADC_CLOCK_INTERNAL);
set_adc_channel(0);

setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); //For Motor RPM
set_timer1(64936);

enable_interrupts(INT_TIMER1);
enable_interrupts(GLOBAL);


while (TRUE) {



//----------Testing--------------------------
usb_task();
usb_debug_task();
if (usb_enumerated()) {
if (!send_timer) {
send_timer=250;
out_data[0]=KnockValue;
out_data[1]=!input(BUTTON);

usb_put_packet(1, out_data, 2, USB_DTS_TOGGLE); //by prashant
//usb_put_packet(1, out_data, 1, USB_DTS_TOGGLE);


}

if (usb_kbhit(1)) {
usb_get_packet(1, in_data, 1);
//usb_get_packet(1, in_data, 2); //Changed by Prashant
// printf("\r\n--> Received data: 0x%X 0x%X",in_data[0],in_data[1]);

delay_us(1);

if (in_data[0]) {LED_ON(LED2);} else {LED_OFF(LED2);}
// if (in_data[1]) {LED_ON(LED3);} else {LED_OFF(LED3);}
}


send_timer--;
delay_ms(1);
}

//---------End Testing-----------------------


}



}
Ttelmah
Guest







PostPosted: Tue Aug 30, 2005 3:54 pm     Reply with quote

Forget reading the ADC in the timer interrupt as you show. Sequence the ADC task instead, with something like:
Code:

void int_timer(void) {
   static int8 state;
   switch (state) {
   case 0:
      read_adc(ADC_START_ONLY);
      state=1;
      break;
   case 1:
      read_adc(ADC_READ_ONLY);
      state=0;
      break;
   }

Add the actual handling of the detection tasks onto this.
As it stands, the ADC, will take about 10 instruction times per bit to sample (a total of 120 instruction times, for the ten bits, plus the extras involved in it's operation). Add the instructions to exit the routine, and those for entering the routine, and the interrupt code will take a total of something in the order of 200 instruction times to execute. Perhaps 40uSec inside the routine....
Even with the adc sampling taken out of the interrupt time, I would suggest turning off the interrupt in the handler code, once enumeration begins, till it has completed.

Best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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