程序代写 PIC18 C Programming

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 #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 #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 #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