Tag Archives: microchip

Microchip’s C18 V3.45 Compiler is Junk

As I continue to use the Microchip C18 compiler I find more and more issues. Microchip’s idiots appear to have left the peripherals lib out of the linker for the PIC18F2x/45K50 chips.
After changing over to use the K22 series of microcontrollers (specifically the PIC18F26K22), I found that the SPI libraries are missing from the linker. The USART libraries are there, but not the SPI.
Programs using SPI compile just fine, but won’t link…

Keep it up Microchip, and you may yet convince everyone to use Atmel.

So, I switched to an older compiler, version 3.40, and it works fine.

Here’s the code:

/*
* Uses SPI to read an MCP3004, and writes the results to the serial port.
*/

#include <p18F26K22.h>
#include <usart.h>
#include <stdio.h>
#include <stdlib.h>
#include <spi.h>
#include <delays.h>

#pragma config FOSC = INTIO7 //, MCLRE = ON
#pragma  WDTEN = 0;  // Disable the watchdog timer

/*
IRCF<2:0>: Internal RC Oscillator Frequency Select bits(2)
111 = HFINTOSC ? (16 MHz)
110 = HFINTOSC/2 ? (8 MHz)
101 = HFINTOSC/4 ? (4 MHz)
100 = HFINTOSC/8 ? (2 MHz)
011 = HFINTOSC/16 ? (1 MHz)(3)
*/
unsigned char msb1, msb2, lsb1, lsb2;

int ch_data;

/* SPI pins
* 14 SCK
* 15 SDI = MISO
* 16 SDO = MOSI */
#define ADC_CS PORTCbits.RC2 // pin 13 = chip select for ADC

void main(void)
{
OSCCONbits.IRCF = 0b101; //change Fosc to 4Mhz

ANSELC = 0; //Analog ports set to digital

// Have to explicitly set the IO on the SPI pins
TRISCbits.RC2 = 0; // Chip Select ADC_CS
TRISCbits.RC3 = 0; // SCK 1
TRISCbits.RC4 = 1; // SDI 1
TRISCbits.RC5 = 0; // SDO 1
OpenSPI1(SPI_FOSC_16, MODE_11, SMPEND);

Delay10TCYx(5);
ADC_CS = 1; // disable chip

// Open the USART configured as 8N1, 2400 baud, in polled mode
Open1USART (USART_TX_INT_OFF &

USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH, 103);

// write a break and Hello to the serial port.
putrs1USART(“\n\n\n\n\n\n\r !!! hello !!! \n\r”);

Delay10TCYx(1);
while (1) {

ADC_CS = 0; // pull chip select low RA4

WriteSPI1(0x01);
msb1 = ReadSPI1();
lsb1 = ReadSPI1();

ADC_CS = 1; // disable chip
ch_data = msb1;
ch_data = ch_data << 8;
ch_data = ch_data + lsb1;

// write the data to the serial port
printf(“MSB,LSB %d,%d combined: %d\r\n”,msb1,lsb1,ch_data);
Delay10TCYx(200);
}

}

PIC18F26K22 – Blink

Here’s a fancier version of the usual blink routine that also demonstrates the various options for setting the internal oscillator.

/*
* A more complicated Blink program for the PIC18F26K22
*
* Set the clock:
* 111 = HFINTOSC ? (16 MHz)
* 110 = HFINTOSC/2 ? (8 MHz)
* 101 = HFINTOSC/4 ? (4 MHz)
* 100 = HFINTOSC/8 ? (2 MHz)
* 011 = HFINTOSC/16 ? (1 MHz)(3)
*
* Use the PLL to quadruple the frequency.
* OSCTUNEbits.PLLEN = 1;
*
* connect LEDs to RA0 - RA5
*
* The program clock speed can be measured on pin RA6
*/
#include /* MCU header file ***********/
#include

#pragma config WDTEN = OFF
#pragma config FOSC=INTIO7 // ;Internal oscillator block
#pragma config PLLCFG = ON
#pragma config PRICLKEN = ON
#pragma config IESO = OFF
#pragma config PWRTEN = OFF // ;Power up timer disabled

int counter;
void main (void)
{
OSCCON = 0x62; // Fosc = 8MHz
OSCCONbits.SCS0 = 0;
OSCCONbits.SCS1 = 0;
OSCTUNEbits.PLLEN = 1; // Use the PLL to up the clock to 32Mhz

counter = 1;
TRISA = 0; /* configure PORTB for output */
while (counter <= 255)
{
PORTA = counter; /* display value of ‘counter’ on the LEDs */
Delay10KTCYx(100);
counter++;
}

}

PIC18F26K22 – Serial Hello World example

After having compiler issues using the new PIC18F25K50 chip, I switched to the K22 series.  Specifically the 28 pin PIC18F26K22.  The dual USART, dual SPI/I2C interfaces will be handy and allow for more flexible board layouts.

But, I had some difficulty getting the serial output to work.  I read through a variety of examples, and questions/problems posted by others, most without responses.  I did find several examples, but none of these worked.  With some additional messing about, I managed to come up with this minimal Hello World example.

Hopefully the following will save someone else some time.

/* Serial Hello World
* This works!
* Clock set to 4Mhz, no PLL, transmits at 2400 Baud
* PIC18F26K22
* Complier: C18 v 3.45
*/

#include
#include
#include
#include
#include
#include

#pragma config FOSC = INTIO7 // internal clock, clock output on RA6

/*
IRCF: Internal RC Oscillator Frequency Select bits(2)
111 = HFINTOSC (16 MHz)
110 = HFINTOSC/2 (8 MHz)
101 = HFINTOSC/4 (4 MHz)
100 = HFINTOSC/8 (2 MHz)
011 = HFINTOSC/16 (1 MHz)
*/

void main (void)
{
OSCCONbits.IRCF = 0b101; //change Fosc to 4Mhz
// wait until IOFS = 1 (osc. stable)
while (!OSCCONbits.IOFS)
/*
* Open the USART configured as
* 8N1, 2400 baud, in polled mode
*/
Open1USART (USART_TX_INT_OFF &
USART_RX_INT_OFF &
USART_ASYNCH_MODE &
USART_EIGHT_BIT &
USART_CONT_RX &
USART_BRGH_HIGH, 103);

while (1)
{
putrs1USART(“Hello World!\n\r”);
Delay1KTCYx(1);
}
}