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

problem with 18F4550 clock speed
Goto page 1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

problem with 18F4550 clock speed
PostPosted: Thu Apr 18, 2013 8:00 am     Reply with quote

Hi everyone,

This is my first post, really happy to be in this forum.

I have a clock speed problem with my PIC. I'm using a PIC 18F4550 it has a clock source of 16MHz crystal and I'm using CCS compiler to compile my program move it on MPLAB 8.89 and from a ICD2 programmer to my μC.
I work it on ccd class which works great, but I'm having a problem with the clock speed. I used spi_xfer to communicate with an 12-bit ADC 1Msps produce 16 clock pulses but the highest speed i get is 45KHz(frequency of all 16 pulses), otherwise the duration for 16 pulses is 22 μsec.

I'm trying to make a hardware SPI. I sent 16 pulses by setting and clearing PIN_C2 but the highest i get with CPUDIV1 is 3 MHz frequency for each clock.

Help would be useful, thanx

Code:

#include <18f4550.h> //
 #include <main.h>
 #use delay(clock=32000000)
 #use RS232 (BAUD=28800,XMIT=PIN_D4 ,RCV=PIN_C7 ,STREAM=COMA,FORCE_SW)
 #USE SPI (MASTER, CLK=PIN_C2, DI=PIN_C1, DO=PIN_D3, MODE=3, BITS=16, STREAM=first, MSB_FIRST, BAUD = 1000000)
 #include <usb_cdc.h> //Include the USB CDC library. If you want to see all the functions available look at usb_cdc.h and usb.h.
 int16 adc_result(void)
 
 {
 int counter;   
     output_low(PIN_C2);
     output_high(PIN_C2);   
   output_low(PIN_C2);     
 output_high(PIN_C2);   
   output_low(PIN_C2);   
   output_high(PIN_C2);   
   output_low(PIN_C2);
     output_high(PIN_C2);   
   output_low(PIN_C2);   
   output_high(PIN_C2);   
   output_low(PIN_C2);   
   output_high(PIN_C2);   
   output_low(PIN_C2);     
 output_high(PIN_C2);   
   output_low(PIN_C2);   
   output_high(PIN_C2);   
   output_low(PIN_C2);   
   output_high(PIN_C2);
     output_low(PIN_C2);
     output_high(PIN_C2);
     output_low(PIN_C2);   
   output_high(PIN_C2);
     output_low(PIN_C2);
     output_high(PIN_C2);
     output_low(PIN_C2);
     output_high(PIN_C2);
     output_low(PIN_C2);   
   output_high(PIN_C2);   
   output_low(PIN_C2);   
   output_high(PIN_C2);   
   output_low(PIN_C2);   
   output_high(PIN_C2);
  return 100;
   }
 void main()
 {   
 int c;  int i; 
  unsigned int16 res;             //these lines do some initialization 
    usb_cdc_init(); 
  usb_init(); 
  usb_wait_for_enumeration();   
 while(true)
 {   
    usb_task(); //handles connections to and disconnections from the computer, registering the PIC with the computer, etc. call this pretty often so that the PIC responds to being plugged in.           
        if(usb_cdc_kbhit())
 {
 //did we get some incoming data?     
      c = usb_cdc_getc(); //get one character of input
          output_low(PIN_C0);   
        //res=spi_xfer(first,i,16);   
        res = adc_result(); 
          //res>>=1;           
        //shift to corect adc     
         output_high(PIN_C0);       
              printf(" you typed: %c\r\n adc value %Lu \r\n", c,res);   
        printf(usb_cdc_putc, "  you typed: %c\r\n adc value %Lu \r\n", c,res); //print out a response over usb                                       
      }       
       }   
    }
 


Code:

#FUSES NOWDT                    //No Watch Dog Time
 #FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
 #FUSES PLL4                     //Divide By 4(16MHz oscillator input)
 #FUSES CPUDIV1                  //No System Clock Postscaler
 #FUSES USBDIV                   //USB clock source comes from PLL divide by 2
 #FUSES HS                    //High Speed Crystal/Resonator with PLL enabled
 #FUSES FCMEN                    //Fail-safe clock monitor enabled
 #FUSES IESO                     //Internal External Switch Over mode enabled
 #FUSES NOPUT                    //No Power Up Timer
 #FUSES NOBROWNOUT               //No brownout reset
 #FUSES BORV20                   //Brownout reset at 2.0V
 #FUSES VREGEN                   //USB voltage regulator enabled
 #FUSES PBADEN                   //PORTB pins are configured as analog input channels on RESET
 #FUSES LPT1OSC                  //Timer1 configured for low-power operation#FUSES MCLR
 #FUSES STVREN                   //Stack full/underflow will cause reset
 #FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
 #FUSES ICPRT                    //ICPRT enabled
 #FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
 #FUSES NODEBUG                  //No Debug mode for ICD
 #FUSES NOPROTECT                //Code not protected from reading
 #FUSES NOCPB                    //No Boot Block code protection
 #FUSES NOCPD                    //No EE protection
 #FUSES NOWRT                    //Program memory not write protected
 #FUSES NOWRTC                   //configuration not registers write protected
 #FUSES NOWRTB                   //Boot block not write protected
 #FUSES NOWRTD                   //Data EEPROM not write protected
 #FUSES NOEBTR                   //Memory not protected from table reads
 #FUSES NOEBTRB                  //Boot block not protected from table reads
 
#use delay(clock=32000000)
 
 
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Apr 18, 2013 10:52 am     Reply with quote

There's too much for me to wade through.

Post the SHORTEST possible, complete, compilable code I can copy and paste to test.

Mike
alan



Joined: 12 Nov 2012
Posts: 357
Location: South Africa

View user's profile Send private message

PostPosted: Thu Apr 18, 2013 11:05 am     Reply with quote

Remove printf and test again. It is known that printf takes an awefully long time to execute.
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Thu Apr 18, 2013 11:05 am     Reply with quote

thanks for the reply

Try this, the program has no errors, it compiles.
You need an oscillator to see the frequency that PIN_C2 toggles.
You will need all the main library where the FUSES are written.

Thanks


Code:

#include <18f4550.h> //
 #include <main.h>
 #use delay(clock=32000000)
#USE SPI (MASTER, CLK=PIN_C2, DI=PIN_C1, DO=PIN_D3, MODE=3, BITS=16, STREAM=first, MSB_FIRST, BAUD = 1000000)
 #include <usb_cdc.h> //Include the USB CDC library. If you want to see all 
 int16 adc_result(void)
 
 {
 int counter;   
     output_low(PIN_C2);
     output_high(PIN_C2);   
   output_low(PIN_C2);     
 output_high(PIN_C2);   
}
 void main()
 {   
 int c;  int i; 
  unsigned int16 res;             //these lines do some initialization 
    usb_cdc_init(); 
  usb_init(); 
  usb_wait_for_enumeration();   
 while(true)
 {   
    usb_task(); //handles connections to and disconnections from the computer, registering the PIC with the computer, etc. call this pretty often so that the PIC responds to being plugged in.           
        if(usb_cdc_kbhit())
 {
c = usb_cdc_getc(); //get one character of input
          output_low(PIN_C0);   
        //res=spi_xfer(first,i,16);   
        res = adc_result(); 
          //res>>=1;           
        //shift to corect adc     
         output_high(PIN_C0);       
              printf(" you typed: %c\r\n adc value %Lu \r\n", c,res);   
        printf(usb_cdc_putc, "  you typed: %c\r\n adc value %Lu \r\n", c,res); //print out a response over usb                                       
      }       
       }   
    }
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Thu Apr 18, 2013 11:09 am     Reply with quote

Thank you Mike i will try tomorrow removing the printf.
But you think it slows down the speed so much?

It should be working on 32MHz or 48MHz according to
the FUSES set up.
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Thu Apr 18, 2013 2:52 pm     Reply with quote

If you use the HS fuse, the CPU clock comes from the crystal oscillator, not the USB clock source. Your crystal is running at 16MHz, so this is the _maximum_ you can clock your CPU this way. You are using CPUDIV1, so your CPU will be running at 16MHz.

The clocks you can run the CPU at are:
HS
CPUDIV1 16MHz
CPUDIV2 8MHz
CPUDIV3 5.33MHz
CPUDIV4 4MHz

HSPLL
CPUDIV1 48MHz
CPUDIV2 32MHz
CPUDIV3 24MHz
CPUDIV4 16MHz

So to run at your required 32MHz, you need to change the HS fuse to HSPLL, and the CPUDIV fuse to CPUDIV2

The data sheet does explain it (except for the confusion caused by the same divider numbers giving different divisions from the USB clock, which is made very 'non obvious' by CCS calling the divider numbers by the division they give from the crystal only).

Best Wishes
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 12:43 am     Reply with quote

Quote:
If you use the HS fuse, the CPU clock comes from the crystal oscillator, not the USB clock source


Sorry guys it's a typing mistake, i already use HSPLL.
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 12:50 am     Reply with quote

probeoil wrote:
Quote:
If you use the HS fuse, the CPU clock comes from the crystal oscillator, not the USB clock source


Sorry guys it's a typing mistake, i already use HSPLL.


In which case you need to change your divider to CPUDIV2 to give 32MHz. With CPUDIV1 which you show, you will be running at 48MHz.

Best Wishes
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 12:57 am     Reply with quote

Quote:
In which case you need to change your divider to CPUDIV2 to give 32MHz. With CPUDIV1 which you show, you will be running at 48MHz.


I know but with CPUDIV1 i get 6 MHz CPU speed and with CPUDIV2 i get 4 MHz.
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 1:46 am     Reply with quote

I commented out printf and did not work, on every loop adc_result function is called and gives 16 pulses, then gives a print and starts another loop.
Ttelmah



Joined: 11 Mar 2010
Posts: 19568

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 3:40 am     Reply with quote

So, use CPUDIV1, and change your clock statement to 48MHz. Then at least you are using the speed you declare. Otherwise things like serial are never going to work correctly.

Now, you talk about getting a particular speed. You do realise that even at 48MHz, you are only getting 12MIPS, and a C instruction will always be multiple CPU instructions?. If (for instance), you are counting a counter, and shifting out bits from a variable (which is what the software code will have to do), then this will involve several machine instructions per bit. '22uSec' for 16 pulses sounds quite good to me, unless you switch to using hardware SPI....

Throw away 90% of your code (Mike Walne's comment, and _essential_ for debugging). Just send an individual byte in a loop. Time this. Then (since now the code will only be a few dozen instructions), try this in MPLAB simulator. This will tell you how many instructions the code actually is, and how fast it should be at your clock.

Best Wishes
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 4:09 am     Reply with quote

Thank you for the response Ttelmah.
I'll try it out
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 5:30 am     Reply with quote

I tried the most simple program.
Code:

#include <18f4550.h>
#include <main.h>

#use delay(clock=48000000)
void main() {
   int c;
   int i;
   unsigned int16 res;
  while(true) {
   output_low(PIN_C0);
           output_high(PIN_C0);
 }
           
   }


to go from low state to high it needs 169 nsec.
If the controller needs 2 cycles to do this then the cpu is running at 6 MHz and i need at least 24MHz

The fusses are the same as before.
Code:

#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES PLL4                         //16 MHz crystal
#FUSES CPUDIV1                 //48 MHz speed
           
#FUSES USBDIV

#FUSES HSPLL    Crystal/Resonator with PLL enabled
[/quote]
probeoil



Joined: 02 Apr 2013
Posts: 20
Location: greece

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 5:31 am     Reply with quote

when i say 2 cycles i mean to do
output_low(PIN_C0);
output_high(PIN_C0);
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Apr 19, 2013 6:50 am     Reply with quote

Quote:
to go from low state to high it needs 169 nsec.
If the controller needs 2 cycles to do this then the cpu is running at 6 MHz and i need at least 24MHz
Don't confuse MIPS and MHz. The PIC processor needs 4 clock cycles to execute 1 instruction. So, as Ttelmah already pointed out, when running at 48MHz the processor can execute 12 instructions every us.
Executing the high/low commands in 169ns == 2 instructions == 12 instructions / us
Just as expected.
If this is too slow for you, then software SPI is not the right solution for you. Hey, perhaps that's why they invented a hardware SPI module?

I don't know what you want to create, but I see you mention a CCD? Please note that the PIC processors are not very good for image processing, they are relative slow and have very limited memory.

You want to clock in 16 bits at a 1Msample rate, that is 16 bits every microsecond, or a bit rate of 16Mbit/s
The maximum clock speed for SPI in the PIC18F4550 is 1/4 the CPU clock, that requires a minimum PIC CPU speed of 16Mbit/s * 4 = 48MHz.
So, the SPI hardware in your processor is just fast enough to process your data stream. Tricky part is that your CPU also requires time to read the SPI data and save it somewhere in RAM. Seems possible, but depends largely on which memory you want to use for saving the data and how many bytes you want to save.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2, 3  Next
Page 1 of 3

 
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