# 微算機幹幹
[微算機幹](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

* OSCCON

* Timer1 & Timer3

* Timer2
* 8-bit 模式的計時器,有預除器及後除器之功能。
* TMR2 會自動加一並與設定的值(PR2)相比;若相等則送出訊號至後除器或產生中斷,並自動將自己清除為零,重新計時。

* 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; //
> 
```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;
}
...
```