# 微算機幹幹 [微算機幹](https://hackmd.io/TSxQSxvwSKuFpMxKgMBu3A) [Instruction set](http://technology.niagarac.on.ca/staff/mboldin/18F_Instruction_Set/) ## Template ```= LIST p=18f4520 #include<p18f4520.inc> org 0x00 init: endl: end ``` ## Lab1 ```= LIST p=18f4520 #include<p18f4520.inc> org 0x00 start: clrf 0xCC clrf WREG clrf TRISD movlw 0xF loop: addwf TRISD, 1 decfsz WREG goto loop addwf TRISD, 0 END ``` ## Lab2 ```= LIST p=18f4520 #include<p18f4520.inc> org 0x00 start: lfsr FSR0, 0x0100 clrf WREG loop1: movwf INDF0 incf WREG, 0 btfss POSTINC0, 3 goto loop1 lfsr FSR0, 0x0100 lfsr FSR1, 0x0110 clrf WREG loop2: addwf INDF0, 0 movwf POSTINC1 btfss POSTINC0, 3 goto loop2 nop END ``` ## Lab3 xor(0xFF) implement not ```= LIST p=18f4520 #include<p18f4520.inc> org 0x00 init: movlw 0xDF movwf 0x00 ;X movlw 0x9E movwf 0x01 ;Y movlw 0x5B movwf 0x02 ;I movlw 0xC4 movwf 0x03 ;J movlw 0xFF movwf 0x05 ;temp nand: movff 0x00, WREG andwf 0x01, 0, 0 xorwf 0x05, 0, 0 movwf LATA ; X nand Y nor: movff 0x02, WREG iorwf 0x03, 0, 0 xorwf 0x05, 0, 0 movwf LATB ; I nor J endl: end ``` Left shift 5 times with carry. Due to the carry bit inital value is zero, so five times is correct. ```= LIST p=18f4520 #include<p18f4520.inc> org 0x00 init: movlw 0x08 movwf TRISB ;X movlw 0x0B movwf TRISC ;Y clrf TRISA ;ANS = 0 clrf WREG mul: rlncf TRISA, 1, 0 ;ANS = ANS << 1 rlcf TRISC, 1, 0 ;Y = Y << 1 movff TRISB, WREG ;W = X btfsc TRISC, 4, 0 ;check Y 000X_0000 addwf TRISA, 1, 0 ;ANS += W bnc nul ;if carry bit, then endl endl: rrncf TRISA, 1, 0 end ``` ## Lab 4 ```= LIST p=18f4520 #include<p18f4520.inc> CONFIG WDT = OFF org 0x00 init: movlf macro literal,F movlw literal movwf F endm addfff macro f1,f2,f_res movff f1, WREG addwf f2, 0 movwf f_res clrf WREG endm movlf 0x01, 0x10 movlf 0x01, 0x11 start: rcall fib btfss 0x12, 3 movlf 0x08, PCL rcall finish fib: addfff 0x10, 0x11, 0x12 movff 0x11, 0x10 movff 0x12, 0x11 return finish: end ``` ## Lab5 ```= #include <xc.inc> GLOBAL _divide PSECT mytext, local, class=CODE, reloc=2 _divide: movlw 0x09 movff WREG, LATC movff 0x003, LATD sl: dcfsnz LATC, 1, 0 goto endl rlcf 0x001, 1, 0 rlcf 0x002, 1, 0 sub: movff LATD, W subwf 0x002, 0, 0 bn sl movff LATD, WREG subwf 0x002, 1, 0 incf 0x001, 1,0 goto sl endl: return ``` ```c= #include <xc.h> extern unsigned int divide(unsigned int a, unsigned int b); void main(void) { volatile unsigned int res = divide(255, 13); volatile unsigned char quotient = (res<<8)>>8; volatile unsigned char remainder = (res>>8); while(1) return; } ``` ## lab6 * TRIS_: configure port as INPUT or OUTPUT * PORT_: read from device * LAT_ : output example: * TRISC = b'00110000' * RC4 & RC5 is input * otherwise output ```= #include "p18f4520.inc" CONFIG OSC = INTIO67 ; Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7) CONFIG WDT = OFF ; Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit)) CONFIG PBADEN = OFF ; PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset) CONFIG LVP = OFF ; Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) org 0x00 cnt_i set 0x14 cnt_j set 0x15 DELAY macro numOut, numIn local innerLoop local outerLoop movlw numOut movwf cnt_i outerLoop: movlw numIn movwf cnt_j innerLoop: nop nop nop nop nop nop nop decfsz cnt_j, 1, 0 bra innerLoop decfsz cnt_i, 1, 0 bra outerLoop endm init: movlw B'00111100' movwf ADCON1 clrf PORTA bsf TRISA, 4 ; SET RA4 as INPUT clrf LATD bcf TRISD, 0 ; SET RD0 as OUTPUT pressCheck: btfsc PORTA, 4 bra pressCheck bra lightup lightup: btg LATD, 0 DELAY d'50', d'250' bra pressCheck end ``` ## lab7 p42 * RCON - control register * IPEN - interrupt priority enable bit p93 * INTCON - interrupt control register * GIE - global interrupt enable bit - Enables all high-priority interrupts * INT0IE - TMR0 Overflow Interrupt Enable bit - Enables the TMR0 overflow interrupt * INT0IF - INT0 External Interrupt Flag bit - The INT0 external interrupt occurred ```= #include "p18f4520.inc" CONFIG OSC = INTIO67 CONFIG WDT = OFF CONFIG PBADEN = OFF CONFIG LVP = OFF CNTVAL equ d'253' L1 equ 0x14 L2 equ 0x15 org 0x00 goto INITIAL DELAY macro num1, num2 local LOOP1 local LOOP2 movlw num2 movwf L2 LOOP2: movlw num1 movwf L1 LOOP1: nop nop nop nop decfsz L1, 1 goto LOOP1 decfsz L2, 1 goto LOOP2 endm ISR: org 0x08 btg 0x11, 0 ;0x11[0] toggle bcf INTCON, INT0IF retfie INITIAL: movlw 0x11 movwf 0x10 ;0x10==b'00010001' clrf 0x11 ;0x11[0]==0 clrf PORTA clrf LATA bsf TRISB, 0 ;set RA4 as input clrf TRISD clrf PORTD movlw b'11111000' ;setup T0CON movwf T0CON, 0 clrf TMR0L, 0 ;set up timer bsf RCON, IPEN bsf INTCON, GIE bsf INTCON, INT0IE bcf INTCON, INT0IF movlw CNTVAL movwf TMR0L, 0 MAIN: btfsc 0x11, 0 rrncf 0x10, 1 ;0x11[0]==1 btfss 0x11, 0 rlncf 0x10, 1 ;0x11[0]!=1 clrf LATD btfsc 0x10, 0 ;lightup RD0 if 0x10[0]==1 btg LATD, 0 btfsc 0x10, 1 ;lightup RD1 if 0x10[1]==1 btg LATD, 1 btfsc 0x10, 2 ;lightup RD2 if 0x10[2]==1 btg LATD, 2 btfsc 0x10, 3 ;lightup RD3 if 0x10[3]==1 btg LATD, 3 DELAY d'200', d'90' goto MAIN end ``` ## lab8 * Timer0 ![](https://i.imgur.com/7xV8ers.png) * OSCCON ![](https://i.imgur.com/uJgOKWd.png) * Timer1 & Timer3 ![](https://i.imgur.com/8fUsoGP.png) * Timer2 * 8-bit 模式的計時器,有預除器及後除器之功能。 * TMR2 會自動加一並與設定的值(PR2)相比;若相等則送出訊號至後除器或產生中斷,並自動將自己清除為零,重新計時。 ![](https://i.imgur.com/Fydrmcg.png) * PIE * enable * p98 * PIR * request * p96 * IPR * priority * p100 ```cpp= #include "lab8.h" #include <stdbool.h> bool status = false; void __interrupt(high_priority) Mi_ISR(void){ if(status == false){ if(LATD == 8){ LATD = 0; } else if (LATD == 0){ LATD = 1; } else{ LATD <<= 1; } status = true; PIR1bits.TMR2IF = 0; return; } else{ status = false; PIR1bits.TMR2IF = 0; return; } } void __interrupt(low_priority) Lo_ISR(void){ return; } int init(void){ OSCCONbits.IRCF = 3; //011 -> 500kHx TRISD = 0; T2CON = 127; // 1:16 post, 16 pre, onbit PR2 = 244; // INTCONbits.GIE = 1; INTCONbits.PEIE = 1; PIE1bits.TMR2IE = 1; PIR1bits.TMR2IF = 0; IPR1bits.TMR2IP = 1; LATD = 0; return 0; } int main(void){ init(); while(1){ } } ``` ```cpp= #include <xc.h> // PIC18F4520 Configuration Bit Settings // Assembly source line #pragma config statements // #pragma config1H #pragma config OSC = INTIO67 // Oscillator Selection bits (Internal oscillator block, port function on RA6 and RA7) #pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable bit (Fail-Safe Clock Monitor disabled) #pragma config IESO = OFF // Internal/External Oscillator Switchover bit (Oscillator Switchover mode disabled) // #pragma config2L #pragma config PWRT = OFF // Power-up Timer Enable bit (PWRT disabled) #pragma config BOREN = SBORDIS // Brown-out Reset Enable bits (Brown-out Reset enabled in hardware only (SBOREN is disabled)) #pragma config BORV = 3 // Brown Out Reset Voltage bits (Minimum setting) // #pragma config2H #pragma config WDT = OFF // Watchdog Timer Enable bit (WDT disabled (control is placed on the SWDTEN bit)) #pragma config WDTPS = 32768 // Watchdog Timer Postscale Select bits (1:32768) // #pragma config3H #pragma config CCP2MX = PORTC // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1) #pragma config PBADEN = OFF // PORTB A/D Enable bit (PORTB<4:0> pins are #pragma configured as analog input channels on Reset) #pragma config LPT1OSC = OFF // Low-Power Timer1 Oscillator Enable bit (Timer1 #pragma configured for higher power operation) #pragma config MCLRE = ON // MCLR Pin Enable bit (MCLR pin enabled// RE3 input pin disabled) // #pragma config4L #pragma config STVREN = ON // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset) #pragma config LVP = OFF // Single-Supply ICSP Enable bit (Single-Supply ICSP disabled) #pragma config XINST = OFF // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode)) // #pragma config5L #pragma config CP0 = OFF // Code Protection bit (Block 0 (000800-001FFFh) not code-protected) #pragma config CP1 = OFF // Code Protection bit (Block 1 (002000-003FFFh) not code-protected) #pragma config CP2 = OFF // Code Protection bit (Block 2 (004000-005FFFh) not code-protected) #pragma config CP3 = OFF // Code Protection bit (Block 3 (006000-007FFFh) not code-protected) // #pragma config5H #pragma config CPB = OFF // Boot Block Code Protection bit (Boot block (000000-0007FFh) not code-protected) #pragma config CPD = OFF // Data EEPROM Code Protection bit (Data EEPROM not code-protected) // #pragma config6L #pragma config WRT0 = OFF // Write Protection bit (Block 0 (000800-001FFFh) not write-protected) #pragma config WRT1 = OFF // Write Protection bit (Block 1 (002000-003FFFh) not write-protected) #pragma config WRT2 = OFF // Write Protection bit (Block 2 (004000-005FFFh) not write-protected) #pragma config WRT3 = OFF // Write Protection bit (Block 3 (006000-007FFFh) not write-protected) // #pragma config6H #pragma config WRTC = OFF // Configuration Register Write Protection bit (Configuration registers (300000-3000FFh) not write-protected) #pragma config WRTB = OFF // Boot Block Write Protection bit (Boot block (000000-0007FFh) not write-protected) #pragma config WRTD = OFF // Data EEPROM Write Protection bit (Data EEPROM not write-protected) // #pragma config7L #pragma config EBTR0 = OFF // Table Read Protection bit (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks) #pragma config EBTR1 = OFF // Table Read Protection bit (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks) #pragma config EBTR2 = OFF // Table Read Protection bit (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks) #pragma config EBTR3 = OFF // Table Read Protection bit (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks) // #pragma config7H #pragma config EBTRB = OFF // Boot Block Table Read Protection bit (Boot block (000000-0007FFh) not protected from table reads executed in other blocks) ``` ## lab9 * Capture - timer1,3 * Compare - timer1,3 * PWM - timer2 ```c= #include <xc.h> #include <pic18f4520.h> #pragma config OSC = INTIO67 // Oscillator Selection bits #pragma config WDT = OFF // Watchdog Timer Enable bit #pragma config PWRT = OFF // Power-up Enable bit #pragma config BOREN = ON // Brown-out Reset Enable bit #pragma config PBADEN = OFF // Watchdog Timer Enable bit #pragma config LVP = OFF // Low Voltage (single -supply) In-Circute Serial Pragramming Enable bit #pragma config CPD = OFF // Data EEPROM Memory Code Protection bit (Data EEPROM code protection off) #define _XTAL_FREQ 1000000 void __interrupt(high_priority) Mi_ISR(void) { while(CCPR1L!=18) { __delay_ms(5); CCPR1L++; } CCPR1L = 4; INT0IF = 0; return; } void __interrupt(low_priority) Lo_ISR(void) { return; } void init() { // RB0 as input, RC2 as , init TRISB = 0x01; TRISC = 0x00; LATB = 0; LATC = 0; // timer2, prescaler=4 T2CON = 0b01111101; // 125 // OSC - Fosc=125k, Tosc=8us OSCCONbits.IRCF = 0b001; // CCP1 CCP1CONbits.CCP1M = 0b1100; CCP1CONbits.DC1B = 0b00; // pr2, period=20ms // period = (PR2+1)*4*Tosc*(TMR2 prescaler) PR2 = 0x9b; // 155 // CCPR1L, dutyCycle=512us // duty cycle = (CCPR1L:CCP1CON<5:4>)*Tosc*(TMR2 prescaler) CCPR1L = 4; // 4*2*2=16 // timer0 interrupt T0CON = 0b11111000; IPEN = 1; GIE = 1; INT0IE = 1; INT0IF =0; return; } int main(void) { init(); while (1) { } return 0; } ``` ## lab10 `https://hackmd.io/@a20034294/mcu-lab10` * ADCON0,1,2 - p223 * PIR1bits.ADIF * PIE1bits.ADIF * IPR1bits.ADIP * INTCONbits.GIE * RCONbits.IPEN ```clike= #include "lab10.h" void __interrupt(high_priority) Hi_ISR(void) { // check bits int input = (ADRESH << 8) + ADRESL; int bitShow = (input - (input % 64)) / 64; LATD = bitShow; // Clear ADIF PIR1bits.ADIF = 0x0; // Turn AD Conversion Status to Idle ADCON0bits.GO = 0x1; return; } void __interrupt(low_priority) Lo_ISR(void) { // low priority interrupt here return; } void init(){ // Set Oscillator to 8MHz OSCCONbits.IRCF = 7; // set TRISA<0> as INPUT TRISA = 0x01; // set TRISD<0-3> as OUTPUT TRISD = 0x00; // clear LEDs LATD = 0x00; // set VREF- to -5V ADCON1bits.VCFG1 = 0; // set VREF+ to 5V ADCON1bits.VCFG0 = 0; // set AD Port Configuration ADCON1bits.PCFG = 0xE; // set Analog Channel Select bits ADCON0bits.CHS = 0x0; // set AD Conversion Clock Select bits ADCON2bits.ADCS = 0x1; // Select A/D Acquisition Time Select bit ADCON2bits.ACQT = 0x4; // Turn A/D On ADCON0bits.ADON = 0x1; // set AD Result Format Select bit ADCON2bits.ADFM = 0x1; // first clear ADIF PIR1bits.ADIF = 0x0; // enable AD Converter Interrupt PIE1bits.ADIE = 0x1; // enable Global Interrupt INTCONbits.GIE = 0x1; // set AD Converter Interrupt Priority to High IPR1bits.ADIP = 0x1; // Turn AD Conversion Status to Running ADCON0bits.GO = 0x1; // TEST RCONbits.IPEN = 0x1; } void main(void) { init(); while(1){ // Turn AD Conversion Status to Running ADCON0bits.GO = 0x1; continue; }; return; } ``` ## lab11 先跑 sample code 改 main.c DEMO > IRCF2 = 1; // default setting 4MHz > TXSTAbits.SYNC = 0; // > TXSTAbits.BRGH = 1; // > BAUDCONbits.BRG16 = 0; // > ![](https://i.imgur.com/uNU0WGY.png) ```c= ... #define _XTAL_FREQ 8000000 void Mode1() { ClearBuffer(); UART_Write_Text("Enter mode1"); return; } void Mode2() { ClearBuffer(); UART_Write_Text("Enter mode2"); strcpy(str, GetString()); float n = 0; while (1) { strcpy(str, GetString()); if (str[0] == 'e') { ClearBuffer(); break; } n = ADC_Read(7); n = n / 1023 * 5; char f2[10]; sprintf(f2, "%.2f", n); UART_Write_Text(f2); __delay_ms(100); } return; } void main(void) { SYSTEM_Initialize(); while (1) { strcpy(str, GetString()); if (str[0] == 'm' && str[1] == 'o' && str[2] == 'd' && str[3] == 'e' && str[4] == '1') { Mode1(); ClearBuffer(); } if (str[0] == 'm' && str[1] == 'o' && str[2] == 'd' && str[3] == 'e' && str[4] == '2') { Mode2(); ClearBuffer(); } } return; } ... ```