Recently I helped my students with a PIC18F8722 microcontroller project. Hardware setup:
- UNI-DS6 Development System + microboard with PIC18F8722 and seven segment display
- PICkit 3 In-Circuit Debugger
- Windows 10 PC + MPLAB X IDE + XC8 compiler
Notes:
- Pay attention on how the cable is connected to PICKit 3.
- Difference between PORT and LAT: The latch is the output latch onto which values are written. The port is the voltage at the actual pin… So in most situations, you will write to the latch and read from the port. When you're reading from LATx, you're reading what is in the Data Register, when you read from PORTx, you're reading the actual I/O pin value. PIC uses read-modify-write to write operations and this can be a problem, so they use this shadow register to avoid it.
- Setting timer and interrupt bits:
//Clear interruptsINTCONbits.GIE = 0; //Global interrupt enableINTCONbits.TMR0IE = 0; //Timer0 interrupt enable.TMR0L = 0;TMR1 = 0;//TIMER 0 (PIC18F8722)INTCONbits.GIE = 1; //Global interrupt enableINTCONbits.TMR0IE = 1; //Timer0 interrupt enable.INTCONbits.TMR0IF = 0;T0CONbits.T08BIT = 1;T0CONbits.T0CS = 0; //internal clock selectedT0CONbits.PSA = 1; //prescaler is NOT assignedT0CONbits.T0PS0 = 0;T0CONbits.T0PS1 = 0;T0CONbits.T0PS2 = 0;T0CONbits.TMR0ON = 1;//TIMER 1T1CONbits.RD16 = 1;T1CONbits.T1CKPS0 = 0;T1CONbits.T1CKPS1 = 0;T1CONbits.T1OSCEN = 0;T1CONbits.TMR1CS = 0;T1CONbits.TMR1ON = 1;T1CONbits.T1RUN = 1;
- Using two timers with interrupt:
void __interrupt() isr(void) {if(TMR0IF) { //Timer 0 overflowTMR0IF = 0; //Clear Timer 0 interrupt flagTMR0 = 0; //Timer 0 counter}if(TMR1IF) { //Timer 1 overflowTMR1IF = 0; //Clear Timer 1 interrupt flagTMR1 = 30000; //Set counter so that overflow takes less time}}
- Calculating timer overflow period:
- For 40MHz oscillator, use #pragma config OSC = HSPLL
- Frequency of instruction cyles = 40Mhz/4 = 10MHz → 1 instruction cyle = 0.1us
- 8 bit timer overflows every 2^8 instruction cycles = 256 * 0.1 = 25.6us
- 16 bit timer overflows every 2^16 instruction cycles = 6553.6us = 6.5536ms
- XC8 problem: Cannot use const int nTimer0_500ms = 19531; int maxTimer0 = nTimer0_500ms; XC8 displays message “error: (712) can't generate code for this expression” at the int maxTimer0 = nTimer0_500ms line. I had to use #define nTimer0_500ms (19531).
- cTimer0 > 2 * 19531 → we expected 1s delay but the board LEDs behaved strangely. When we used a prescaler of 1:2 (000), it worked as expected.
- Make Timer 1 faster by setting TMR1 to e.g. 30000 so that it start counting from TMR1 and number of counts until overflow would be 2^16 - TMR1.
- Finding a binary number corresponding to row: nb += 1 << iRow
- PORTA = 0b0011: Turn on first two LEDs in column A of board
- Turn on 4th bit of a number: nb |= 1<<4
- Turn off 4th bit of a number: nb &= ~(1<<4)
- You have to check button presses multiple times to give user time and to do debouncing.
No comments:
Post a Comment