MCU: PIC18F45K20

IDE: MPLAB X IDE v6.00

Compiler: XC8 v2.36

 

 

데이터시트를 참조하여 인터럽트를 사용하여 타이머를 구동해 보도록 해 보겠습니다.

 

File > New Project를 클릭하여 프로젝트를 생성합니다.

Standalone Project 선택 후 Next >

 

알맞는 Device를 선택하고 Next >

 

Compiler 선택하고 Next >

 

 

Project Name, Location 설정하고 Finish

 

 

프로젝트 생성 완료

 

main.c 파일을 생성합니다.

 

 

기본 설정 코드는 아래 링크에서 사용했던 것을 사용합니다.

[PIC][MPLABX][XC8] GPIO :: 취미 블로그 (tistory.com)

 

[PIC][MPLABX][XC8] GPIO

MCU: PIC18F45K20 IDE: MPLAB X IDE v6.00 Compiler: XC8 안녕하세요. 이번 시간에는 데이터시트를 보고 PIC18F45K20의 GPIO를 제어하도록 해 보겠습니다 보드의 정보는 아래 링크에서 확인 할 수 있습니다. DM164..

jeonhj.tistory.com

 

 

 

 

1. Timer0 레지스터

아래는 타이머0의 블럭 다이어그램입니다.

 

 

타이머 0 인터럽트 플래그인 TMR0IF는

8Bit Mode에서는 TMR0가 255 -> 0 으로 되었을 때

16Bit Mode에서는 TMR0가 65535 - > 0 으로 되었을 때 

1로 설정됩니다.

 

TMR0ON: Timer0 Enable / Stop 설정

T08BIT: Timer0 8 bit / 16 bit 설정

T0CS : 클럭 소스 설정

T0SE: Timer0 Source Edge 설정 (T0CS = 1일때 유효)

PSA: 분주비 Enable / Disable 설정

T0PS: 분주비 설정

 

여기서 저는 클럭 소스를 Fosc/4로 설정하고, 16Bit Timer에 1:8의 분주비를 사용하겠습니다.

 

T0CON = 0b00000010;

 

 

2. Timer0 시간계산

Time = 4 / Fosc * Prescaler * Counter

 

 

저는 

16Bit Timer에 

Fosc = 64000000

Prescaler = 8

Counter = 2000

으로 설정하면 

 

4 / 64000000 * 8 * 2000 = 0.001 = 1ms가 됩니다.

 

즉 Timer0가 2000을 세면 1ms마다 인터럽트가 걸리도록 세팅합니다.

 

PIC18F45K20의 타이머는 기본적으로 0, 1, 2, ... 처럼 숫자를 올리는 UP Timer 입니다.

16Bit 모드에서 2000을 세면 인터럽트가 걸리기 위해서는 65535 - 2000  값으로 설정해 주어야 합니다.

 

65535 - 2000 = 63535 = 0xF82F

 

이 값을 TMR0H와 TMR0L 에 값을 써줍니다.

void Initialize_Timer0(void)
{
    T0CON = 0b00000010;
    TMR0H = 0xF8;
    TMR0L = 0x2F;
}

 

 

3. 인터럽트 설정

다음은 PIC18F45K20의 인터럽트 로직입니다.

 

위 TMR0 인터럽트가 걸리기 위한 조건은 다음과 같습니다.

 

TMR0IF == 1 && TMR0IE == 1 && TMR0IP  == 1

&&

GIEH / GIE == 1

 

PIC 18F45K20 은 인터럽트 벡터가 0x0008h, 0x0018h 두개가 있습니다.

높은 우선순위로 설정된 인터럽트 (xxIP == 1)는 0x0008h 인터럽트 벡터 번지에서 발생되고

낮은 우선순위로 설정된 인터럽트 (xxIP == 0)는 0x0018h 인터럽트 벡터 번지에서 발생됩니다.

 

 

저는 TMR0 인터럽트를 사용하기 위해서 다음과 같이 설정합니다.

 

void Initialize_Interrupt(void)
{
    INTCON = 0b10100000;
    INTCON2 = 0b00000100;
}

 

이제 인터럽트 벡터 함수를 만들어 주어야 합니다.

MPLAB_XC8_C_Compiler_User_Guide_for_PIC.pdf 파일을 보면 인터럽트에 대한 내용이 있습니다.

XC8 User Guide 문서에 나와있는 interrupt 벡터 함수 예제

 

위를 바탕으로 다음과 같이 함수를 만들어 줍니다.

volatile uint32_t tick = 0;

void TMR0_ISR(void)
{
    tick++;
}

void __interrupt(high_priority) InterruptManager (void)
{
    if(INTCONbits.TMR0IE == 1 && INTCONbits.TMR0IF == 1)
    {
        TMR0H = 0xF8;
        TMR0L = 0x2F;
        INTCONbits.TMR0IF = 0;
        TMR0_ISR();
    }
}

 

타이머0 인터럽트가 발생하면 TMR0H, TMR0L 값을 63535로 다시 설정하고 tick 변수 값을 1 증가시키도록 하였습니다.

 

또 TMR0IF 비트 설명을 보면 

TMR0 register has overflowed (must be cleared by software)

라고 software로 clear 시켜주어야 한다고 되어 있기 때문에 

INTCONbits.TMR0IF = 0;

코드도 넣어주었습니다.

 

이제 Timer0와 인터럽트 설정이 끝났습니다.

 

이제 초기화 함수를 부르는 코드와 1초마다 PORTD를 토글 시키는 코드를 작성합니다.

// PIC18F45K20 Configuration Bit Settings

// 'C' source line config statements

// CONFIG1H
#pragma config FOSC = INTIO67     // Oscillator Selection bits (HS oscillator, PLL enabled (Clock Frequency = 4 x FOSC1))
#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)

// 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 = 18        // Brown Out Reset Voltage bits (VBOR set to 1.8 V nominal)

// CONFIG2H
#pragma config WDTEN = OFF      // Watchdog Timer Enable bit (WDT is controlled by SWDTEN bit of the WDTCON register)
#pragma config WDTPS = 32768    // Watchdog Timer Postscale Select bits (1:32768)

// CONFIG3H
#pragma config CCP2MX = PORTC   // CCP2 MUX bit (CCP2 input/output is multiplexed with RC1)
#pragma config PBADEN = ON      // PORTB A/D Enable bit (PORTB<4:0> pins are configured as analog input channels on Reset)
#pragma config LPT1OSC = OFF    // Low-Power Timer1 Oscillator Enable bit (Timer1 configured for higher power operation)
#pragma config HFOFST = ON      // HFINTOSC Fast Start-up (HFINTOSC starts clocking the CPU without waiting for the oscillator to stablize.)
#pragma config MCLRE = ON       // MCLR Pin Enable bit (MCLR pin enabled; RE3 input pin disabled)

// CONFIG4L
#pragma config STVREN = ON      // Stack Full/Underflow Reset Enable bit (Stack full/underflow will cause Reset)
#pragma config LVP = ON         // Single-Supply ICSP Enable bit (Single-Supply ICSP enabled)
#pragma config XINST = OFF      // Extended Instruction Set Enable bit (Instruction set extension and Indexed Addressing mode disabled (Legacy mode))

// CONFIG5L
#pragma config CP0 = OFF        // Code Protection Block 0 (Block 0 (000800-001FFFh) not code-protected)
#pragma config CP1 = OFF        // Code Protection Block 1 (Block 1 (002000-003FFFh) not code-protected)
#pragma config CP2 = OFF        // Code Protection Block 2 (Block 2 (004000-005FFFh) not code-protected)
#pragma config CP3 = OFF        // Code Protection Block 3 (Block 3 (006000-007FFFh) not code-protected)

// 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)

// CONFIG6L
#pragma config WRT0 = OFF       // Write Protection Block 0 (Block 0 (000800-001FFFh) not write-protected)
#pragma config WRT1 = OFF       // Write Protection Block 1 (Block 1 (002000-003FFFh) not write-protected)
#pragma config WRT2 = OFF       // Write Protection Block 2 (Block 2 (004000-005FFFh) not write-protected)
#pragma config WRT3 = OFF       // Write Protection Block 3 (Block 3 (006000-007FFFh) not write-protected)

// 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)

// CONFIG7L
#pragma config EBTR0 = OFF      // Table Read Protection Block 0 (Block 0 (000800-001FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR1 = OFF      // Table Read Protection Block 1 (Block 1 (002000-003FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR2 = OFF      // Table Read Protection Block 2 (Block 2 (004000-005FFFh) not protected from table reads executed in other blocks)
#pragma config EBTR3 = OFF      // Table Read Protection Block 3 (Block 3 (006000-007FFFh) not protected from table reads executed in other blocks)

// CONFIG7H
#pragma config EBTRB = OFF      // Boot Block Table Read Protection bit (Boot Block (000000-0007FFh) not protected from table reads executed in other blocks)

// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.


#include <xc.h>
#define _XTAL_FREQ (64000000UL)

volatile uint32_t tick = 0;

void Initialize_SystemClock(void)
{
    OSCCONbits.IRCF = 0b111;
    OSCCONbits.SCS = 0b00;
    OSCTUNEbits.PLLEN = 1;
}

void Initialize_Port(void)
{
    TRISD = 0x00;
}

void Initialize_Timer0(void)
{
    T0CON = 0b00000010;
    TMR0H = 0xF8;
    TMR0L = 0x2F;
}

void Run_Timer0(void)
{
    T0CONbits.TMR0ON = 1;
}

void Stop_Timer0(void)
{
    T0CONbits.TMR0ON = 0;
}

void Initialize_Interrupt(void)
{
    INTCON = 0b10100000;
    INTCON2 = 0b00000100;
}

void TMR0_ISR(void)
{
    tick++;
}

void __interrupt(high_priority) InterruptManager (void)
{
    if(INTCONbits.TMR0IE == 1 && INTCONbits.TMR0IF == 1)
    {
        TMR0H = 0xF8;
        TMR0L = 0x2F;
        INTCONbits.TMR0IF = 0;
        TMR0_ISR();
    }
}

void main(void)
{
    uint32_t time = 0;
    
    Initialize_SystemClock();
    Initialize_Port();
    
    Initialize_Timer0();
    Initialize_Interrupt();
    
    Run_Timer0();
    
    while (1) {
        if (tick - time > 1000) {
            time = tick;
            PORTD ^= 0xFF;
        }
    }
    return;
}

 

반응형

'MCU > PIC' 카테고리의 다른 글

Microchip Programmer & Debugger  (0) 2022.06.15
[PIC][MPLABX][XC8][MCC]TIMER0 + 인터럽트  (0) 2022.06.15
[PIC][MPLABX][XC8] GPIO  (0) 2022.06.14
[PIC][MPLABX][XC8] 개발환경 구축  (0) 2022.06.11
[PIC][XC8][MPLAB X][MCC] GPIO  (0) 2022.06.11
[XC8] 컴파일 Warning 메세지 띄우지 않기  (0) 2022.03.28

+ Recent posts