--- 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: ![](https://i.imgur.com/theWCjS.png) 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