You are on page 1of 27

Programming 8-bit PIC Microcontrollers in C

Martin Bates Elsevier 2008

This presentation contains selected illustrations and program listings from the book Programming 8-bit PIC Microcontrollers in C by Martin Bates
Part 1 Microcontroller Systems describes in detail the internal architecture and interfaces available in a typical PIC chip, and outlines the main features of the MPLAB development system Part 2 C Programming Essentials provides simple examples which introduce the basic principles of C programming for microcontrollers using CCS C

Part 3 C Peripheral Interfaces provides example programs for operating PIC chips with a full range of peripherals, using timers and interrupts

Part 3

C PERIPHERAL INTERFACES

Figure 3.1

Single analogue input and display

Listing 3.1
/*

Simple analogue input test

ANALIN.C MPB 5-1-07 Read & display analogue input ***************************************************************************/ #include "16F877A.h" #device ADC=8 #use delay(clock=4000000) #use rs232(baud=9600, xmit=PIN_D0, rcv=PIN_D1)

// 8-bit conversion

// LCD output

void main() //************************************************************ { int vin0; // Input variable setup_adc(ADC_CLOCK_INTERNAL); setup_adc_ports(ALL_ANALOG); set_adc_channel(0); for(;;) { // ADC clock // Input combination // Select RA0

delay_ms(500); vin0 = read_adc(); vin0 = (vin0/32)+0x30;

// Get input byte // Convert to ASCII // Clear screen // Display input

putc(254); putc(1); delay_ms(10); printf("Input = "); putc(vin0); }

Table 3.1
ANALOGUE INPUTS ADC SETUP ADC PINS SETUP ADC CHANNEL SELECT ADC READ

CCS C Analogue Input Functions

Initialise ADC Initialise ADC pins

setup_adc(ADC_CLOCK_INTERNAL); setup_adc_ports(RA0_ANALOG);

Select ADC input


Read analogue input

set_adc_channel(0);
inval = read_adc();

Table 3.2

CCS C Interrupt Functions

Label INTERRUPT CLEAR INTERRUPT DISABLE

Operation Clears peripheral interrupt Disables peripheral interrupt Enables peripheral interrupt Checks if interrupt flag set Selects interrupt trigger edge Jump to address of ISR

Syntax Example clear_interrupt(int_timer0); disable_interrupts(int_timer0) ; enable_interrupts(int_timer0); interrupt_active(int_timer0); ext_int_edge(H_TO_L); jump_to_isr(isr_loc);

INTERRUPT ENABLE
INTERRUPT ACTIVE INTERRUPT EDGE INTERRUPT JUMP

Tables 3.3 & 3.4

PIC 16F877 Interrupt Sources

INTERUPT LABEL INT_EXT INT_RB INT_RTCC INT_TIMER0

REGISTER CODE

INTERRUPT SOURCE External interrupt has been detected Change on Port B has been detected Timer 0 has overflowed (same as TIMER0 Timer 0 has overflowed (same as RTCC)

0x0B10 0x0B08 0x0B20 0x0B20

INT_TIMER1 INT_CCP1
INT_TIMER2 INT_CCP2 INT_AD INT_SSP INT_PSP INT_EEPROM

0x8C10 0x8C04
0x8C02 0x8D01 0x8C40 0x8C08 0x8C80 0x8D10

Timer 1 has overflowed Timer 1 matches preset value?


Timer 2 has overflowed Timer 2 matches preset value? Analogue to digital converter has finished Serial data has been received Data ready at parallel serial port Data EEPROM write completed

Figure 3.3

External interrupt test hardware

Listing 3.3

External interrupt test program source code

// INTEXT.C MPB 10-4-07 // Demo external interrupt RB0 low interrupts foreground output count #include "16F877A.h" #use delay(clock=4000000) #int_ext void isrext() { output_D(255); delay_ms(1000); } // Interrupt name // Interrupt service routine name // ISR action

void main() //************************************************************** { int x; enable_interrupts(int_ext); enable_interrupts(global); ext_int_edge(H_TO_L); while(1) { output_D(x); x++; delay_ms(100); } } // Enable named interrupt // Enable all interrupts // Interrupt signal polarity // Foreground loop

Table 3.5
TIMERS TIMERX SETUP TIMERX READ Set up the timer mode

Timer functions

setup_timer0( RTCC_INTERNAL | RTCC_DIV_8 ); count0 = get_timer0(); set_timer0(126); setup_ccp1(ccp_pwm); set_pwm1_duty(512);

Read a timer register (8 or 16 bits) Preload a timer register (8 or 16 bits) Select PWM, capture or compare mode Set PWM duty cycle

TIMERX WRITE
TIMER CCP SETUP TIMER PWM DUTY

Figure 3.4

Compare Hardware Block Diagram

Preload Set Interrupt Flag (CCP1IF)

CCPR1H

CCPR1L

Comparator

Set/Clear Pin RC2

TMR1H

TMR1L

Instruction Clock

Listing 3.4

Pulse width modulation program source code

// PWM.C MPB 11-4-07 // Demo PWM output #include "16F877A.h" void main() { setup_ccp1(ccp_pwm); // Select timer module and mode set_pwm1_duty(500); // Set on time setup_timer_2(T2_DIV_BY_16,248,1); // Clock rate & // output period while(1){} }

Figure 3.5

Capture Hardware

Set Interrupt Flag (CCP1IF)

Prescale & Edge select

CCPR1H

CCPR1L

Capture Enable
TMR1H TMR1L Instruction Clock

Pulse Input Pin RC2

Listing 3.5
// PERIOD.C MPB 11-4-07 // Demo of period measurement

Capture mode demo program

#include "16F877A.h" //******************************************************** #int_ccp1 void isr_ccp1() { set_timer1(0); clear_interrupt(INT_CCP1); } // Interrupt name // Interrupt function // Clear Timer1 // Clear interrupt flag

void main()//****************************************************** { setup_timer_1(T1_INTERNAL); // Internal clock setup_ccp1(CCP_CAPTURE_RE); // Capture rising edge on RC2 enable_interrupts(GLOBAL); enable_interrupts(INT_CCP1); while(1){} } // Enable all interrupts // Enable CCP1 interrupt

Figure 3.6

Capture mode used to measure input period

Table 3.6
RS232 SERIAL PORT Title RS232 SET BAUD RATE RS232 SEND BYTE RS232 SEND SELECTED RS232 PRINT SERIAL RS232 PRINT SELECTED RS232 PRINT STRING RS232 RECEIVE BYTE RS232 RECEIVE STRING RS232 RECEIVE SELECTED RS232 CHECK SERIAL RS232 PRINT ERROR

RS232 Serial Port Functions


requires #USE RS232, #USE DELAYS (Clock=nnnnnnnn) Description Example

Set hardware RS232 port baud rate


Write a character to the default port Write a character to selected port Write a mixed message Write string to selected serial port Print a string and write it to arrav Read a character to an integer Read input string to character array Read input string to character array Check for serial input activity Write programmed error message

setup_uart(19200);
putc(65) s = fputc(A,01);
printf(Answer:%4.3d,n); fprintf(01,Message); sprintf(astr,Ans=%d,n);

n = getc(); gets(spoint);
astring= fgets(spoint,01);

s = kbhit();
assert(a<3);

Figure 3.1.1

RS232 peripheral simulation

Listing 3.6

Hardware UART

// HARDRS232.C MPB 13-6-07 // Serial I/O using hardware RS232 port #include "16F877A.h" #use delay(clock=8000000) RS232 #use rs232(UART1)

// Delay function needed for // Select hardware UART

void main() //*************************************************** { int incode; setup_uart(9600); // Set baud rate while(1) { incode = getc(); printf(" ASCII = %d ",incode); putc(13); } }

// Read character from UART // Display it on // New line on display

Table 3.7
SPI SERIAL PORT Operation SPI SETUP SPI READ SPI WRITE SPI TRANSFER SPI RECEIVED Description Initialise SPI serial port

SPI function set

Example setup_spi(spi_master); inbyte = spi_read(); spi_write(outbyte); inbyte = spi_xfer(outbyte); done = spi_data_is_in();

Receives data byte from SPI port Sends data byte via SPI port Send and receive via SPI Check if SPI data received

Figure 3.8

SPI test system schematic

Listing 3.7

SPI slave transmitter source code

// SPIMASTER.C MPB 20-6-07 // Serial I/O using SPI synchronous link // Simulation hardware SPIC.DSN, master program, attach to U1 #include "16F877A.h" void main() { int number; //**********************************************

setup_spi(spi_master);

// Set SPI master mode

while(1) { number = spi_read(); spi_write(number); }


}

// Read SPI input BCD code // Re-send BCD code to slave

Figure 3.9

I2C test system

Table 3.8
I2C SERIAL PORT I2C START I2C WRITE I2C READ I2C STOP I2C POLL Issue start command in master mode Send a single byte Read a received byte

I2C functions

i2c_start(); i2c_write(outbyte); inbyte = i2c_read(); i2c_stop(); sbit = i2c_poll();

Issue a stop command in master mode Check to see if byte received

Figure 3.10

PSP test system

Table 3.9
PARALLEL SLAVE PORT Operation PSP SETUP PSP DIRECTION Description Enable or disable PSP Set the PSP data direction

PSP functions

Example setup_psp(PSP_ENABLED); set_tris_e(0); pspo = psp_output_full();

PSP OUTPUT READY


PSP INPUT READY PSP OVERFLOW

Checks if output byte is ready to go

Checks if input byte is ready to read


Checks for data overwrite error

pspi = psp_input_full();
pspv = psp_overflow();

Listing 3.10

PSP master test program

// PSPMASTER.C // Test system master controller program, design file PSP.DSN, U1 #include "16F877A.h" void main() //************************************************ { int sendbyte; port_b_pullups(1); // Activate Port B pullups while(1) { sendbyte = input_B(); output_D(sendbyte); output_low(PIN_E2); output_low(PIN_E1); output_high(PIN_E1); } }

// Get test byte // Output on PSP bus // Select PSP slave // Write byte to slave port // Reset write enable

You might also like