Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Pickit2/Junebug notes.

Status
Not open for further replies.

3v0

Coop Build Coordinator
Forum Supporter
A few ramdom notes that may interest some.

Target Clock Speed vrs IDE Performance

I had been working with the 18F1330 at 32MHz. Today I wrote code for the Junebug 18F1320 8 MHz onboard target.

The IDE seemed sluggish.

The debugger preformance we see is the result of the interaction of MPLAB with Junebug; and Junebug with the debug monitor resident on the target chip.

When you slow the target from 32 to 8 MHz you also slow the target's debug monitor which handles the interface between itself and Junebug. Overall IDE preformance/speed suffers.

By the same token when you switch from a 8 MHz target to a 32 MHz target the IDE seems to fly.

Programming I2C EEPROMS with Junebug

When working on the BTC audio playback project I needed to program the speach bits into a 24LC512 I2C serial EEPROM. It was easy to do using Pickit2 V2.40 software and the Junebug. I made a simple adaptor board that plugged into the socket next to the Junebug processor chip. Ask if you want details on how to make one.
 
C18 Junebug Interrupt Driven Multiplexed LED code (long)

This is advanced compared to the simple examples Bill and I talked about in the Sordfish thread. Comments here and help in the original example should make this understanable. If not feel free to ask question.

If you do not understand C for loops and switch statements you need to study them first. You should also read the 18F1320 datasheet section on timer0 if you want to fully understand this.

This was adapted from the Microchip file indicated in the comments.
LEDs do following pattern where X's are illuminated and 0's are not.

0X0X0X | repeat 4 times
X0X0X0 |

0000XX
000XX0
00XX00
0XX000
XX0000
0XX000
00XX00
000XX0
0000XX

The README file in C:/MCC18/example/users_guide/example1 walks through the Microchip example line by line. If you are new to C or the C18 start by understanding that example first. Once you do this will not be difficult. I have not made any changes to timer0 use other then using timer0 in the 8 bit mode rather then the 16.

This program has a loop in main that sets a LED pattern and then waits till it nees to set the next pattern. Quite simple.
Timer0 is free running. Each time it reaches zero it generates an interrupt and lights up just one of the LEDs that need to be lit. This happens fast enough such that all the selected/enabled LEDs seem to be on at the same time.
Code:
/*
 * adapted from Microchip
 * C:/MCC18/example/users_guide/example1/leds.c
 * The following sample application will flash the Junebug's LEDs connected to PORTA 
 * PIC18F1320 microcontroller.
 * 
 * 
 * This sample covers the following items:
 * 
 * 1. Interrupt handling (#pragma interruptlow, interrupt vectors,
 *      interrupt service routines)
 * 2. System header files
 * 3. Processor-specific header files
 * 4. #pragma sectiontype
 * 5. Inline assembly
 * 6. Display multiplexing using timer0.
 */

/*
 * Build in the MPLAB IDE using C18 and device type 181320.
 * Project requires linker file 18f1320i.lkr
 */
#include <p18cxxx.h>
#include <timers.h>
#include <delays.h>

#define byte unsigned char 
#define delay1 100

void timer_isr (void);

static unsigned char s_count = 0;
byte ledBits;   // LEDs one per bit, 0 is off, 1 is on
byte ledScan;   // used to select one LED at a time, shifting bit


// Delay of 1ms calculation
// Cycles = (TimeDelay * Fosc) / 4
// Cycles = (1ms * 32MHz) / 4
// Cycles = 8,000
void delay_ms(long t)   // delays t millisecs
{
   do
   {
       Delay1KTCYx(8);    // time will be a small bit over because of overhead, close % wise
   } while(--t);
}


/*
 * For PIC18xxxx devices, the low interrupt vector is found at 000000018h.
 * Change the default code section to the absolute code section named
 * low_vector located at address 0x18.
 */
#pragma code low_vector=0x18
void low_interrupt (void)
{
  /*
   * Inline assembly that will jump to the ISR.
   */
  _asm GOTO timer_isr _endasm
}

/*
 * Returns the compiler to the default code section.
 */
#pragma code

/*
 * Specifies the function timer_isr as a low-priority interrupt service
 * routine. This is required in order for the compiler to generate a
 * RETFIE instruction instead of a RETURN instruction for the timer_isr
 * function.
 */
#pragma interruptlow timer_isr

/*
 * Define the timer_isr function. Notice that it does not take any
 * parameters, and does not return anything (as required by ISRs). 
 */
void
timer_isr (void)
{
  /*
   * Clears the TMR0 interrupt flag to stop the program from processing the
   * same interrupt multiple times.
   */
  INTCONbits.TMR0IF = 0;


  /*
   * Turn on a single LED each time we visit this ISR
   */

  
  if (ledBits == 0)   // just turn all LEDs off
  {
      ledScan = 1;
      LATA = 0x00;
      TRISA = 0xFF;
      return;      
  }
  
 
  // skip to next active LED 
  while ( (ledScan & ledBits) == 0)
  {
      ledScan = ledScan<<1;
      if (ledScan > 0x20)
        ledScan = 1;  
  }   
         
  // We could store the LATA and TRISA values using 2 arrays but we will save
  // that for another example.
  switch (ledBits&ledScan)
  {
      case 0x01:
        LATAbits.LATA0 = 1;	 // muliplexing hardware dependant code 
	    LATAbits.LATA6 = 0;
	    TRISA = 0b10000000;
	    break;
	  case 0x02:
        LATAbits.LATA0 = 0;	
	    LATAbits.LATA6 = 1;
	    TRISA = 0b10000000;
	    break;
	  case 0x04:
        LATAbits.LATA6 = 1;	
	    LATAbits.LATA7 = 0;
	    TRISA = 0b00000001;
	    break;
	  case 0x08:
        LATAbits.LATA6 = 0;	
	    LATAbits.LATA7 = 1;
	    TRISA = 0b00000001;
	    break;
	  case 0x10:
        LATAbits.LATA0 = 0;	
	    LATAbits.LATA7 = 1;
	    TRISA = 0b01000000;
	    break;
	  case 0x20:
        LATAbits.LATA0 = 1;	
	    LATAbits.LATA7 = 0;
	    TRISA = 0b01000000;
	    break;
  }   
  ledScan = ledScan<<1;  
  if (ledScan > 0x20)
  {
      ledScan = 1;  // warp back to LED1
  }     
}

void main (void)
{
    // speed up the clock to 8MHz, 18F1320 
	OSCCONbits.IRCF0=1;
	OSCCONbits.IRCF1=1;
	OSCCONbits.IRCF2=1;

  /*
   * Initialize the special function registers TRISA and PORTA.
   */
  TRISA = 0;
  PORTA = 0;

  /*
   * Enable the TMR0 interrupt, setting up the timer as an internal
   * 8-bit clock. Not picky about value just let it overflow
   */
  OpenTimer0 (TIMER_INT_ON & T0_SOURCE_INT & T0_8BIT);
  
  /*
   * Enable global interrupts.
   */
  INTCONbits.GIE = 1;

  ledScan = 1;
  while (1)
  {
    int idx;
    
    for (idx=0; idx<5; idx++)
    {
        ledBits = 0b00101010;    // turn on LEDs 1, 3 and 5
        delay_ms(delay1);
        ledBits = 0b00010101;	// turn on LEDs 2, 4 and 6
        delay_ms(delay1);
    }
    
    ledBits = 0;
    delay_ms(delay1);
    
    for (ledBits=3; ledBits<0x20; ledBits=ledBits<<1)
    {      
        delay_ms(delay1);
    }
    
    for (; ledBits>0x01; ledBits=ledBits>>1)
    {      
        delay_ms(delay1);
    }
    
    ledBits = 0;
    delay_ms(delay1);    
  }
}
 
blueroomelectronics said:
I guess what I'm asking is when you are debugging C18 it single steps through the compiled assembly code.

Presumably you mean when using the ICD? - as this is done in the hardware, the only code that's in there is the machine code.
 
A few notes about debugging C18 code.

blueroomelectronics said:
I guess what I'm asking is when you are debugging C18 it single steps through the compiled assembly code.

The compiler generates a COF file (Common Output Format) which contains the info the debugger needs to tell which machine statements go with each line of C source code. This info allows the debugger to step over.

User code starts at main(). Prior to running your code the computer needs to set up the stack and initializing your data. This is done in a function generically called C0 or in the case of C18 C018.c. Unless you have a reason to debug this code set a breakpoint on the first executable statement in main and run to it.

Some functions provided by C18 are written in assembly. You can either step over these or step at the machine level if you choose to enter them.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top