---
tags: Microcomputer
---
# 微算機重點超濃縮
## Test Skip Compare:
- TSTFSZ x: Test if, skip if zero
- DECFSZ x: Decrease x, skip if zero
- INCFSZ x: Increase x, skip if zero
## Delay Routine:

Delay for this function:
- = **MOVLW + MOVWF + (100-1)*(DECFSZ+BRA) + DECFSZ if skips + RETURN**
- = 1 + 1 + (100 - 1)*(1+1) + 2 + 1
- = 203
- for PIC18F, **1 instruction cycle = 4 clock cycles**, total delay = 203*4 = 812 microsecs.
## Clock
PIC18F clock generated by OSCCON. set by config OSC = INTIO2 in assembly
## Programmed IO
Set port to be input/output:
- BCF/BSF TRISx TRISxn
Set port to be currently high/low:
- BCF/BSF PORTx RCx
**ADCON1 = 0x0F** multiplex AN0-AN12 with PORTA, PORTB, PORTE, configure these three as digital inputs.
## Polled IO vs Interrupt IO:
Polled IO: program waiting in while loop and detect interrupt.
Interrupt IO: program receive a comfigured signal then switch to ISR.
## PIC18F External Interrupt:
Global:
- INTCON.GIE: global interrupt enable bit
- INTCON.PEIE: peripheral interrupt enable bit
- RCON.IPEN: global priority interrupt enable bit
- INTCON.GIEH: enable high priority interrupt
- INTCON.GIEL: enable low priority interrupt
INT0:
- INTCON.INT0IE: enable bit
- INTCON.INT0IF: flag bit
INT1:
- INTCON3.INT1IE: enable bit
- INTCON3.INT1IF: flag bit
- INTCON3.INT1IP: priority bit, 1 = high, 0 = low
INT2
- INTCON3.INT2IE: enable bit
- INTCON3.INT2IF: flag bit
- INTCON3.INT2IP: priority bit, 1 = high, 0 = low
Programming External Interrupt:
1. **Clear INTxIF = 0**
2. **Set INTxIE = 1**
3. **Set GIE = 1**
4. if multiplex with analog input, **ADCON1 = 0x0F**
Programming External Interrupt **with priority setting**:
1. **RCON.IPEN = 1**
2. **INTCON.GIEL, INTCON.GIEH = 1**
3. **set or clear INTCON3.INTxIP, high = 1 and low = 0**
## Timers
Timer0:
- 8 bit or 16 bit
- INTCON.TMR0IE: enable bit
- INTCON.TMR0IF: flag bit
- T0CON.TMR0ON: set timer to on
- TMR0H/TMR0L: counter value, when counter counts to 0xFF(FF), it will overflow and **create interrupt**.
- INTCON2.TMR0IP: interrupt priority bit
- time delay = **instruction cycle clock period * prescaler * postscaler * (counter value+1)**
Timer1:
- 16 bit timer/counter, CCP capture/compare
- PIE1.TMR1IE: enable bit
- PIR1.TMR1IF: flag bit
- T1CON.TMR1ON: set timer to on
- TMR1H/TMR1L: counter value, when counter counts to 0xFF(FF), it will overflow and **create interrupt**.
- time delay = **instruction cycle clock period * prescaler * postscaler * (counter value+1)**
Timer2:
- 8 bit timer, CCP PWM
- PIE1.TMR2IE: enable bit
- PIR1.TMR2IF: flag bit
- T2CON.TMR2ON: set timer to on
- PR2: **counter reach value, when TMR2 value inc and matchs PR2, interrupt occurs and clear TMR2**
- time delay = **instruction cycle clock period * prescaler * postscaler * (counter value+1)**
Timer3:
- 16 bit timer/counter, CCP capture/compare
- PIE2.TMR3IE: enable bit
- PIR2.TMR3IF: flag bit
- T3CON.TMR3ON: set timer to on
- TMR3H/TMR3L: counter value, when counter counts to 0xFF(FF), it will overflow and **create interrupt**.
Enable timer:
1. **TMRxON = 1**
2. **TMRxIF = 0, TMRxIE = 1**
3. **PIEI = 1, GIE = 1**
4. **when TMRxIF = 1, do work**
Postscaler and Prescaler setting:
- clock period = **1 / Fosc**
- instruction cycle clock period = **4 * clock period**
## AD Converter
ADCON0:
- GO/DONE bit: status bit, 1 = conversion in progress, 0 = idle
- ADON: enable bit
ADCON1:
- configures AN0~AN12, ranged from PORTA, PORTB, PORTE
- select voltage as reference
ADCON2:
- configures ADC clock source
- select left/right justified, 2Tad and Fosc/2
- after conversion, binary output **ADRESH:ADRESL** are placed in ADCON2
AD conversion setting:
1. **PIE1.ADIE = 1**, enabling ADC interrupt
2. **PIR1.ADIF = 0**
3. **INTCON.PEIE, INTCON.GIE = 1**
4. **ADCON0.GO = 1**, start AD conversion, wait for interrupt occurs implying that it has finished
## CCP Mode
Capture (CCPx = input)
- use TMR1 or TMR3, cause content of timer to be written in CCPRxH:CCPRxL
- steps:
1. load CCPxCON, configures CCPx as an input pin using TRISC
2. select TMR1 or TMR3, only T3CON is used (NO T1CON)
3. CCPxIF = 0, CCPRxH:CCPRxL = 0
4. check if CCPxIF = 1, as soon as CCPxIF = 1, set T1CON/T3CON = 1
5. save CCPRxH:CCPRxL in regs
6. clear CCPxIF = 0
7. check if CCPxIF = 1, as soon as CCPxIF = 1, set T1CON/T3CON = 0
8. disable capture by clearing CCPxCON
9. perform subtraction CCPRxH:CCPRxL - REGX:REGY => **we get period of waveform**
Compare (CCPx = output)
- use TMR1 or TMR3, output HIGH/LOW when **TMR = CCPRxH:CCPRxL**
- steps:
1. load CCPxCON, configures CCPx as an output pin using PORTC
2. load CCPRxH:CCPRxL with appropriate values
3. select TMR1 or TMR3, only T3CON is used (NO T1CON)
4. initialize TimerxH:TimerxL = 0
5. clear CCPxIF = 0
6. set T1CON/T3CON = 1
7. check if CCPxIF = 1, as soon as CCPxIF = 1, set T1CON/T3CON = 0
8. the programmed bit value (HIGH or LOW or Toggled or Unchanged) will be outputted to the CCPx pin
PWM (CCPx = output)
- use TMR2, generate a square wave on CCPx with a user-specified freq and duty cycle.
- PR2 = [(Fosc)/(4 x Fpwm x TMR2 Prescale Value)] – 1
- Fpwm = 1/[PWM period] = 1/[(PR2) + 1] x 4 x Tosc x (TMR2 Prescale Value)]
- PWM Duty Cycle = (CCPxL:CCPxCON<5:4>) × Tosc × (TMR2 Prescale Value)
- Steps:
1. init PR2
2. load 8-bit int into CCPRxL, fractional 2 bit into CCPxCONbits.5/4, disable PWM mode
3. configures CCPx to TRISCx bit
4. select Timer2 prescale
5. enable PWM mode by writing appropriate data into CCPxCON
6. init TMR2 = 0
7. T2CON.TMR2ON = 1
8. clear TMR2IF, if TMR2IF = HIGHT, then PWM waveform is generated
- Example: Write 4KHz PWM with 50% duty cycle on CCP1, Fosc = 4MHz
- PR2 = [4MHZ / (4 * 4KHZ * 1)] - 1 = 249
- 50% duty cycle = 249*0.5 = 124.5, so CCPR1L = 124, CCP1CON.5/4 = .5
Regs:
- CCPxCON.CCPxM3:CCPxM0: mode selection bits