Chapter 9 Introduction to PIC18 C Programming
Why program the PIC18 in C?
• C programming is easier and less time consuming
Copyright By PowCoder代写 加微信 powcoder
• C is easier to modify and update
• Existing libraries available (e.g., delays)
• C code is portable to other microcontroller with little or no modification
• We will be using Microchip C18 compiler
Example – Delay Program in Lab 1
Memory Usage Gauge
Same Program Coded in C
Memory Usage Gauge
Disadvantages of C
• The code produced is less space-efficient and runs more slowly than native assembly code.
• A compiler is much more expensive than an assembler.
Image courtesy of S. Katzen, The essential PIC18 Microcontroller, Springer
Data Types, Sizes and Ranges
Size in Bits
Data Range
unsigned char
(signed) char
-128 to +127
unsigned int
0 to 65535
(signed) int
-32768 to 32767
Data Types, Sizes and Ranges
• Because PIC18 is an 8-bit microcontroller, char data type is most commonly used.
• C compliers use the signed type as default unless the qualifier unsigned is put in front.
• int variables are stored in two 8-bit
registers.
• Don’t use int unless we have to. If one 8-bit register is enough to store a variable, we don’t want to use 2 registers.
Use of C to generate time delay
• Using assembly language, we can control the exact instructions executed in a time delay subroutine and thus be able to control the exact time delay.
DelayLoop: decfsz DELAY_L bra DelayLoop
decfsz DELAY_H
bra DelayLoop
Use of C to generate time delay
• C compliers convert C statements to assembly instructions.
• Different compliers produce assembly code of different length.
• The actual time delay generated by the following function depends on the complier used.
void Delay {
unsigned int i; for(i=0; i<10000; i++); return;
• Need to measure the exact time delay using MPLAB StopWatch tool.
I/O Programming in C
• Recall: I/O Programming involves PORTx and TRISx registers.
• Byte I/O Programming: Change the whole byte stored in PORTx or TRISx.
• e.g., PORTB = 0x18 TRISB = 0X20
I/O Programming in C
I/O Programming in C
• Bit-addressable I/O programming: Change a single bit without disturbing the rest of the PORTx or TRISx registers.
• PORTBbits.RB7 = 7th bit of PORTB
• TRISBbits.TRISB7 = 7th bit of TRISB
• Same function as bcf or bsf in assembly language
• e.g., bcf PORTB, 5 is expressed as PORTBbits.RB5 = 0 in C
• e.g., bcf TRISB, 5 is expressed as TRISBbits.TRISB5 = 0 in C
Logic Operations in C
Bit-wise operators:
– Extract lower nibble: PORTB & 0x0F
– e.g., SPI_VALUE = 0x30 | SPI_HI
3.Exclusive OR (^): 1^1 = 0
4.Inverter (~)
– e.g., Toggle PORTB: PORTB = ~PORTB
if statement: Conditional branching
if (CONDITION) { Statement
• CONDITION: The condition in which statement would be executed (if 1, execute statement; if 0, skip statement)
for(INITIALIZATION; CONDITION; INC/DEC){ Statement
• INITIALIZATION: Initialize the “COUNT” variable
• CONDITION: The condition in which this loop will continue (if 1, continue; if 0, exit)
• INC/DEC: Increment/decrement the “COUNT” variable
• Used when you know how many times the loop should run
An example :
//Using for loops to add numbers 1 - 5 unsigned char sum = 0;
for(int i = 1; i<6; i++)
{ sum += i; }
while loop
while(CONDITION){ Statement
• CONDITION: The condition in which this
loop will continue (if 1, continue; if 0, exit)
• Used when you DO NOT know how many
times the loop should run or if the loop
should run infinitely many times (use while(1)).
Simplicity of C: An Example
Lab 2 Task 2
Task: Display your group number of the 4- digit 7-segment LED.
Remember how much work you have done to make it work in assembly?
Very simple coding in C.
Simplicity of C: An Example
void Delay(unsigned int cnt) {
while(cnt != 0) { cnt--;
void main(void)
unsigned char Segment[10] = {0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f};
unsigned char DispBuf[4] = {0, 0, 1, 8}; unsigned char i;
ADCON1 = 0x0f;
TRISB = 0b00000000;
TRISD = 0b00000000;
while(1) {
for(i=0; i<=3; i++) {
//Set All Port Digit I/O
//Set PortB Output
//Set PortD Output
PORTD = 0;
PORTB = i;
PORTD = Segment[DispBuf[i]]; Delay(400);
C18 Timers Library
• C18 Timers Functions:
Description
OpenTimerx()
Configure and enable timer x.
ReadTimerx()
Read the value of timer x.
WriteTimerx()
Write a value into timer x.
CloseTimerx()
Disable timer x.
To use the Timers library, simply put following statement before use
#include
Our interrupt program revisited
#include
#pragma config OSC = HS, WDT = OFF, LVP = OFF
void timer_isr_internal(void); //—————————————————————————- #pragma code timer_isr = 0x08 // Store the below code at address 0x08
void timer_isr(void)
_asm GOTO timer_isr_internal _endasm // allowed to write part of your code in ASM.
//—————————————————————————- #pragma code
void main (void)
TRISBbits.RB5 = 0;
PORTBbits.RB5 = 0;
//T0CON = 0x08; //TMR0H = 0xD8; //TMR0L = 0xF0; WriteTimer0(0xD8F0);
RCONbits.IPEN = 0;
INTCONbits.TMR0IF = 0;
//INTCONbits.TMR0IE = 1;
INTCONbits.GIE = 1;
//set RB5 output
// Timer0, 16-bit, no prescale, internal ck
//disable priority levels
// Interrupt enabled by the TIMER_INT_ON option in OpenTimer0
OpenTimer0(TIMER_INT_ON & T0_16BIT & T0_SOURCE_INT & T0_PS_1_1); //T0CONbits.TMR0ON = 1;
while(1); }
Our interrupt program revisited
#pragma interrupt timer_isr_internal
void timer_isr_internal (void)
if (INTCONbits.TMR0IF)
INTCONbits.TMR0IF=0;
PORTBbits.RB5 = ~PORTBbits.RB5;//toggle
PortB.5 to create sq. wave
//TMR0H = 0xD8; //TMR0L = 0xF0;
WriteTimer0(0xD8F0);
interrupt, interruptlow
• #pragma interrupt fname
– retfie 1 ends the ISR.
– WREG, BSR and STATUS registers are restored from the shadow registers.
• #pragma interruptlow fname
– retfie ends the ISR.
– WREG, BSR and STATUS registers are restored from temporary registers.
Just like in assembly language
C18 ADC Library
• C18 ADC Library Functions:
Description
Configure the A/D convertor.
SetChanADC()
Select A/D channel to be used.
ConvertADC()
Start an A/D conversion.
Is A/D converter currently performing a conversion?
Read the results of an A/D conversion.
CloseADC()
Disable the A/D converter.
To use the Timers library, simply put following statement before use
#include
ADC Example in Assembly
movlw movwf movlw movwf movlw movwf
b’00001110′ ADCON1 b’00000001′ ADCON0 b’00010100′ ADCON2
;Set AN0 Analog Port, others Digital I/O ;Select ADC Channel 0, Enable ADC
; ADFM Left justified, ACQT 4TAD, FOSC/4
; set PORTD output
; start Conversion
; adc_wait waits for ADC to be done
;display Top 8 bit
clrf TRISD
MainLoop: bsf ADCON0, GO adc_wait: btfsc ADCON0, GO
bra adc_wait
movff ADRESH, PORTD bra MainLoop
Equivalent Operation in C
#include
#pragma config OSC=HS, WDT=OFF, LVP=OFF
void main( void ) {
static int result;
TRISD = 0x00;
OpenADC(ADC_LEFT_JUST & ADC_FOSC_4 & ADC_4_TAD, ADC_CH0 & ADC_REF_VDD_VSS & ADC_INT_OFF, ADC_1ANA);
while(1) {
ConvertADC();
while(BusyADC());
result = ReadADC();
PORTD = result >> 8;
// Start conversion
// Wait for completion
I2C Functions
Description
EEByteWrite
Write a single byte.
EEPageWrite
Write a string of data.
EERandomRead
Read a single byte from an arbitrary address.
EESequentialRead
Read a string of data.
EEAckPolling
Generate acknowledgement polling sequence: Send the control byte repeatedly to test whether the EEPROM has completed the internal reading cycle.
I2C Example
#include
#pragma config OSC = HS, WDT = OFF, LVP = OFF
#pragma code
void main (void)
unsigned char i, WordAddress;
unsigned char DigitsToI2C[4] = {1, 2, 3, 4}; unsigned char DigitsReadFromI2C[4];
unsigned int DigitsToI2Cint;
unsigned char err;
ADCON1 = 0x0F;
//TRISCbits.RC3 = TRISCbits.RC4 = 1; Done in OpenI2C
OpenI2C(MASTER, SLEW_OFF);
SSPADD = 0x09;
I2C Example
WordAddress = 0;
// Byte Write:
for (i = 0; i < 4; i++)
EEByteWrite(0xA0, WordAddress, DigitsToI2C[i]);
WordAddress++;
EEAckPolling(0xA0);
WordAddress = 0;
// Byte Read:
for (i = 0; i < 4; i++) {
DigitsToI2Cint = EERandomRead(0xA0, WordAddress);
//This function return a 16-bit int. The byte read is
stored in the LSB.
DigitsToI2C[i] = DigitsToI2Cint & 0x00FF;
WordAddress++;
I2C Example
//Page Write:
EEPageWrite(0xA0, 0x00, DigitsToI2C); EEAckPolling(0xA0);
// Sequential Read:
EESequentialRead(0xA0, 0x00, DigitsReadFromI2C, 4);
程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com