Microprocessor/DSP (TMS320F28x) TR28335 개발 KIT Switch GPIO Input
  • 728x90
    반응형


    GPIO Input 외부 인터럽트로 SWITCH 제어 


    SOURCE TR28835_Switch.h

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    /*===================================================
     *
     * FILE  : TR28335_Switch.h .2017
     * TITLE : TR28335 Switch External Interrupt Control
     *
     *===================================================*/ 
    #ifndef __TR28335_SWITCH_H__
    #define __TR28335_SWITCH_H__
    #ifdef _cplusplus
    extern "C" {
    #endif
    #include <main.h>
     
    /* Switch Pin Number */
    #define PIN12       12
    #define PIN27       27
     
     
    /* Switch Number     */
    #define SWITCH1     0
    #define SWITCH2     1
     
    /* Switch Push State */
    #define UP          0
    #define PUSH        1
     
    void InitSwitch(void);
    int16 SetSwitchEdge(int16 swNum, int16 edge);
     
    #ifdef _cplusplus
    }
    #endif  /* extern "C"           */
    #endif  /* __TR28335_SWITCH_H__ */
    cs


    SOURCE TR28835_Switch.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    /*===================================================
     *
     * FILE  : TR28335_Switch.c .2017
     * TITLE : TR28335 Switch External Interrupt Control
     *
     *===================================================*/ 
    #include <TR28335_Switch.h>
    #include <TR28335_Led.h>
     
    static interrupt void xint1_Isr(void);
    static interrupt void xint2_Isr(void);
     
    static Uint16 gSw1Cnt, gSw2Cnt;
    /*====================================
    *
    * Name        : InitSwitch
    * Type        : Fucntion
    * Description : GPIO12 - SWITCH1
    *               GPIO27 - SWITCH2
    *
    =====================================*/
    void InitSwitch(void)
    {
        gSw1Cnt = 0;
        gSw2Cnt = 0;   
        
        /* Vector Remapping */
        EALLOW;
        /* PIE     : Interrupt Enable and Control Registers Plus PIE Vetor Table  
         * XINT1~2 : External Interrupt Control Register                                   */
        PieVectTable.XINT1 = &xint1_Isr;            /* External Inturrupts service routine */
        PieVectTable.XINT2 = &xint2_Isr;            /* External Inturrupts service routine */
        EDIS;
     
        /* GPIO 초기화 */
        EALLOW;
        GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0;        /* 핀 기능선택: GPIO12                 */
        GpioCtrlRegs.GPAMUX2.bit.GPIO27 = 0;        /* 핀 기능선택: GPIO27                 */
        GpioCtrlRegs.GPADIR.bit.GPIO12  = 0;        /* GPIO12 입출력 선택: Input           */
        GpioCtrlRegs.GPADIR.bit.GPIO27  = 0;        /* GPIO27 입출력 선택: Input           */
        EDIS;
     
        /* Qualification 초기화 */
        EALLOW;
        GpioCtrlRegs.GPACTRL.bit.QUALPRD1 = 0xFF;    /* (GPIO8~GPIO15) Qual period 설정     */
        GpioCtrlRegs.GPACTRL.bit.QUALPRD3 = 0xFF;    /* (GPIO24~GPIO31) Qual period 설정    */
        GpioCtrlRegs.GPAQSEL1.bit.GPIO12  = 2;       /* Qualification using 6 samples       */
        GpioCtrlRegs.GPAQSEL2.bit.GPIO27  = 2;       /* Qualification using 6 samples       */
           EDIS;
     
        /* XINT 초기화 */
        EALLOW;
        GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = PIN12;    /* 외부 인터럽트 XINT1로 사용할 핀 선택: GPIO12   */
        GpioIntRegs.GPIOXINT2SEL.bit.GPIOSEL = PIN27;    /* 외부 인터럽트 XINT2로 사용할 핀 선택: GPIO27   */
        EDIS;
     
        XIntruptRegs.XINT1CR.bit.POLARITY = 1;      /* XINT1 인터럽트 발생 조건 설정: 입력 신호의 상승 엣지 */
        XIntruptRegs.XINT2CR.bit.POLARITY = 1;      /* XINT2 인터럽트 발생 조건 설정: 입력 신호의 상승 엣지 */
     
        XIntruptRegs.XINT1CR.bit.ENABLE = 1;        /* XINT1 인터럽트 : Enable                           */
        XIntruptRegs.XINT2CR.bit.ENABLE = 1;        /* XINT2 인터럽트 : Enable                           */
     
        /* 외부 인터터럽트가 포합된 백터 활성화 */
        PieCtrlRegs.PIEIER1.bit.INTx4 = 1;            /* PIE 인터럽트(XINT1) : Enable */
        PieCtrlRegs.PIEIER1.bit.INTx5 = 1;            /* PIE 인터럽트(XINT2) : Enable */
        IER |= M_INT1;                                /* CPU 인터럽트(INT1)  : Enable */
        
        return ;
    }
     
    /*====================================
    *
    * Name        : SetSwitchEdge
    * Type        : Fucntion
    * Description : Switch Edge Setting
    *
    =====================================*/
    int16 SetSwitchEdge(int16 swNum, int16 edge)
    {
        int16 ret = 0;
        
        if(swNum == SWITCH1 && edge >= UP && edge <= PUSH)     
            XIntruptRegs.XINT1CR.bit.POLARITY = edge;      /* XINT1 인터럽트 발생 조건 설정: 입력 신호의 하강 엣지 */
        else if(swNum == SWITCH2 && edge >= UP && edge <= PUSH)
            XIntruptRegs.XINT2CR.bit.POLARITY = edge;      /* XINT2 인터럽트 발생 조건 설정: 입력 신호의 상승 엣지 */
        else
            ret = ERROR;
        
        return ret;
    }
     
    /*=========================================================
    *
    * Name        : cpu_Timer0_Isr
    * Type        : Interrupt
    * Description : SWITCH1 External Interrupt Service Routine 
    *
    ===========================================================*/
    static interrupt void xint1_Isr(void)
    {
        gSw1Cnt++;    
        CtrlLed(LED6, LED_TOGGLE);
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;        
        
        return ;
    }
     
    /*=========================================================
    *
    * Name        : cpu_Timer0_Isr
    * Type        : Interrupt
    * Description : SWITCH2 External Interrupt Service Routine 
    *
    ===========================================================*/
    static interrupt void xint2_Isr(void)
    {
        gSw2Cnt++;
        CtrlLed(LED1, LED_TOGGLE);
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;    
     
        return ;
    }
    cs


    코드 분석 

    Step .1 External Interrupts XINT1/XINT2 : PIE Vector Table 에 외부 인터럽트 XINT1, XINT2 에 각각 인터럽트 서비스 루틴을 등록한다.


    Step .2 Switch Schematic : SW1 은 GPIO12, SW2 는 GPIO27에 각각 연결되어 있다. 위 회로도 참고.


    Step .3 GPIO Port A MUX1, 2 Register : 스위치에 연결되어 있는 GPIO12, GPIO27에 각각 GPAMUX1, 2 레지스터에 0을 설정하여 GPIO로 사용할 수 있게 활성화 한다.


    Step .4 GPIO Port A Direction Register : 스위치에 연결되어 있는 GPIO12, GPIO27에 각각 GPADIR 레지스터에 0을 설정하여 Input 으로 사용할 수 있게 활성화 한다.


    Qualification ?

    신호에는 노이즈가 섞여있다. 아날로그 신호라면 여러 가지 필터로 노이즈를 걸러낼 수도 있겠다. 디지털 신호에서도 아날로그 필터를 사용하기도 하고, 비교기를 사용해서 디지털 신호를 재생하기도 한다. 디지털 신호에서는 노이즈가 아무리 섞여있어도 0인지 1인지만 정확히 파악하면 그걸로 끝이다 아날로그 신호에 비해서, 노이즈 대응이 매우 쉽다.

    하지만, 다음 그림과 같은 노이즈가 인가되면 디지털 시스템에서는 속수 무책이다.

    위 그림에서 보는 A와 같은 노이즈는 아날로그 필터로는 걸러내기가 어렵다. 엣지 성분이 고스란히 살아있어서, 디지털 시스템은 반응을 한다. 엣지 성분을 없애기 위해서 Low Pass Filter를 사용한다면, 신호 고유의 엣지 성분도 차단되어 신호를 잃어버리게 된다. 에러 컨트롤 코드를 이용하여, 소프트웨어적으로 원신호를 복원할 수도 있지만, 시간 지연과 연산 자원 소비로 실시간 시스템에는 부접합한 경우가 많다.

    이런 경우에 Input Qualifier 라는 회로가 유용하다. 'Qualify' 란, 자격 심사를 의미한다. 입력되는 신호의 자격이 유효한가를 판정하는 것이 곧 Input Qualifier가 된다. 따라서, 디지털 회로로 구현하는 것도 매우 간단하다.

    입력신호릐 규격, 즉 펄스의 길이를 감지하여 펄스 길이가 기준에 미치지 못한다면, 무시해버리는 회로를 구현하는  것이다. 이것이 Input Qualifier다. 이처럼 동작원리는 간단하다. 이런 회로가 각 포트에 핀마다 탑재되어 있다.

    위 그림을 통해서 동작 과정을 살펴보자. Pin에 신호가 들어오면 버퍼를 거쳐서 SYNC 회로에 입력된다. 외부에서 인가되는 신호는 DSP 내부 시스템 클럭과 동기가 맞지 않기에, SYNC 회로를 거쳐서 동기화가 이루어진다.


    Step .5 GPIO Port A Qualification Control (GPACTRL) Register : GPIO12, GPIO27 에 해당하는 QUALPRD1, 3 비트에 0xFF를 설정하여 510개의 SYSTEM COLOCK 길이까지의 자격 기준으로 샘플링한다. 


    Step .6 GPIO Port A Qualification Select (GPAQSEL1, 2) Register : GPIO12, GPIO27에 해당하는 GPAQSEL1, 2 레지스터에 각각 0x02를 설정하여 Qualification 샘플링 주기를 6으로 활성화 한다.


    Step .7 GPIOXINTnSEL : 외부 인터럽트 XINT1, XINT2 에 사용할 핀을 GPIOXINT1SEL, GPIOXIT2SEL에 각각 등록한다.


    Step .8 XINTnCR - Polarity : XINT1CR, XINT2CR 레지스터의 Polarity 비트 설정에서 Edge를 각각 설정한다. 스위치를 눌렀을때 인터럽트가 발생하거나, 스위치 눌렀다 땠을때 인터럽트가 발생하도록 Edge를 설정할 수 있다.

    PS. TR28335_Switch.c 파일의 int16 SetSwitchEdge(int16 swNum, int16 edge) 함수는 위와 같은 내용으로 Edge를 설정할 수 있도록 설계되었다.

    Step .9 XINTnCR - Enable : XINT1 , XINT2 인터럽트를 Enable 하여 활성화 시킨다.


    Step .10 PIEIER1 : 마지막으로 PIE에 XINT1, XINT2 가 포함되어있는 INTx.4, INTx.5 Vector Table에 인터럽트를 활성화 시킨다.


    Step .11 PIEACK : Interrupt Service Routine 의 내용에 PIEACK 는 해석하자면 주변 인터럽트 확장을 인정하는 레지스터이다. 0번 비트에서 11번 비트까지 각각 INT1~12를 가리킨다. 일단 인터럽트가 걸리면 같은 그룹에서 오는 인터럽트를 막기 위해 인터럽트 요청이 들어오면 1로 만들어 다른 인터럽트가 오는 것을 막는다. 그리고 인터럽트 수행이 끝났을 경우에 1을 써서 0으로 클리어 시킨다.


    결과 

    gSw1Cnt, gSw2Cnt 변수는 스위치를 누를때마다 카운팅 된다.



    728x90
    반응형
상단으로