통상적인 절차인지는 몰르지만, 저는 하드웨어 엔지니어는 아니지만, 아~주 예전에 80196이라는 MCU를 가지고 역진자 시스템(inverted pendulum)을 제어[바로가기]했었죠. 그 후에는 AVR를 살짝 하다가 그 다음에는 Cortex M3도 살짝 하다가.. 뭐 지금은 하드웨어를 제공받을 때 왠만한 지원은 받으니까 속칭 때와 장소를 가리지 않고 그냥 제어기를 구현했던 것 같습니다.ㅠㅠ.
그러다가 최근에는 출시된진 좀 되었지만 TI의 TMS320F28335를 가지고 놀고 있는 중이지요... 속칭 28335~~ 얼마전에 GPIO의 몹시 기초적 부분을 건드렸구요~~~ 이번에는 타이머 인터럽트라는 걸 이야기할까 합니다. 뭐 언제나 그렇듯.. 아~~~주 기초적인 이야기지요~~^^ 사실 어차피 제조사인 TI가 배포하는 공식 예제[바로가기]를 들여다 보면 다 있습니다.^^ 여전히 사용하는 보드는 SyncWorks의 28335 초소형 모듈[바로가기]이구요. 어차피 예제가 꽤 자세히 잘 나와 있지만... 그 예제 마저도 좀 분량을 줄여서 이야기할려구요.. 왜냐구요?? 기초니까요~~^^
// Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2833x_SysCtrl.c file. InitSysCtrl(); // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize the PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the DSP2833x_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in DSP2833x_DefaultIsr.c. // This function is found in DSP2833x_PieVect.c. InitPieVectTable();
이번에는 코드부터 들이밀어야죠... 보드 제조사에서 강좌를 잘 진행해주기도 하지만, 아주 복잡하게 흘러가는 경우가 아니라면 통상 요런 설정들은 파워서플리이 전원을 넣고, 스위치를 켜고 .. 등등 처럼 절차일때가 많아서 말이죠~~^^ TI가 제공하는 예제의 첫 부분은 위와 같네요. 특이할 만한 부분은 없습니다. 단지.. Step대로 따라가면 되겠어요. 단.. InitPieCtrl()이라는 함수를 실행하는데.. 그 이름에 있는 PIE가
출처 : TI가 배포하는 28335문서
위 그림에 보면 인터럽트를 배분하는 역할을 하는 군요. 문서를 읽어보면 정말 많은 수의 인터럽트를 28335가 가지고 있어서 저렇게 확장해주는 역할이 필요한 모양입니다.
// Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.TINT0 = &cpu_timer0_isr; GpioCtrlRegs.GPBMUX1.bit.GPIO36 = 0; GpioCtrlRegs.GPBDIR.bit.GPIO36 = 1; EDIS; // This is needed to disable write to EALLOW protected registers
그리고 저는 이번 예제에서 LED를 키고 끌거라 위와 같이 살짝 Gpio를 초기화하는 코드도 넣어 두었습니다.. 저 부분은 첫 예제[바로가기]에서도 이야기했고, 그다음 GPIO를 다룰 때[바로가기]도 이야기를 했습니다. 제가 사용하는 보드에 있는 LED를 일반 GPIO로 설정(GpioCtrlRegs.GPBMUX1.bit.GPIO36 = 0)하고 해당 핀을 출력으로 설정(GpioGtrlRegs.GPBDIR.bit.GPIO36 = 1)한다는 내용입니다.^^
더 중요한 부분은 바로 PieVectTable.TINT0 = &cpu_timer0_isr이라는 구문입니다. TINT0를 cpu_timer0_isr이라는 함수에 연결해둔 겁니다. 즉, 타이머 인터럽트가 발생하면 실행할 함수를 알려주는 거죠~
// Step 4. Initialize the Device Peripheral. This function can be // found in DSP2833x_CpuTimers.c InitCpuTimers(); // For this example, only initialize the Cpu Timers // Configure CPU-Timer 0, 1, and 2 to interrupt every second: // 150MHz CPU Freq, 1 second Period (in uSeconds) ConfigCpuTimer(&CpuTimer0, 150, 1000000); // To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any // of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in DSP2833x_CpuTimers.h), the // below settings must also be updated. CpuTimer0Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0 // Step 5. User specific code, enable interrupts: // Enable CPU int1 which is connected to CPU-Timer 0 IER |= M_INT1; // Enable TINT0 in the PIE: Group 1 interrupt 7 PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // Enable global Interrupts and higher priority real-time debug events: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM
이제 위에 있는 설정 중에 ConfigCpuTimer는 현재 사용하는 클럭 주파수 (저는 150MHz)를 설정하고, us단위의 타이머 인터럽트 간격(1,000,000us = 1,000ms = 1sec)을 설정하는 겁니다. 그리고 나서 CpuTimerRegs.TCR.all = 0x4000이라고 설정합니다. 이 것의 의미는
출처 : TI 28335 문서
각 비트별로 의미가 있습니다. 0x4000은 14번 비트만 1이 되는데... 바로 타이머를 enable한다는 거죠. 또 중요한건 4번 비티를 0으로 둔 것인데요. 그건 타이머를 런닝한다는 것입니다.
출처 : SyncWorks의 인터럽트 설명 문서
뭐 그러나 영어가 짜증난다면 저렇게 한글로도 배포를 해주고 계시네요~~^^. 그리고 PieCtrlRegs.PIEIER1.bit.INTx7 = 1라는 구문이 보이네요.. 이것은
출처 : TI의 28335 문서
위 PIE 벡터 테이블에 보면 INTx.7의 INT1이 TINT0라는 것을 알 수 있죠... 그걸 1로 셋해서 타이머를 인에이블 시키는 것입니다.^^
그리고.. 저런 보드에 위 코드를 실행해 보는거죠.. ㅋㅋ. 뭐 다시 한 번 말씀드리지만... TI가 배포하는 예제를 그냥 실행한 것 뿐입니다. 아~주 살짝 편집만 하구요.. 아참.. 그전에 하나 더있네요... 타이머 인터럽트가 실행되면 처리할 루틴 말이죠...
__interrupt void cpu_timer0_isr(void) { CpuTimer0.InterruptCount++; GpioDataRegs.GPBTOGGLE.bit.GPIO36 = 1; // Acknowledge this interrupt to receive more interrupts from group 1 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; }
위 코드입니다. GPIO36번을 토글하는 거죠... 원래 의도는 1초에 한 번 깜빡거리는 건데.. 멍청하게 아무 생각없이 예제를 편집했더니 깜빡이는 주기가 2초가 되어 버렸네요. ㅎㅎ^^
//########################################################################### // Description //! \addtogroup f2833x_example_list //! <h1>Cpu Timer (cpu_timer)</h1> //! //! This example configures CPU Timer0, 1, and 2 and increments //! a counter each time the timers asserts an interrupt. //! //! \b Watch \b Variables \n //! - CputTimer0.InterruptCount //! - CpuTimer1.InterruptCount //! - CpuTimer2.InterruptCount // //########################################################################### // $TI Release: F2833x/F2823x Header Files and Peripheral Examples V141 $ // $Release Date: November 6, 2015 $ // $Copyright: Copyright (C) 2007-2015 Texas Instruments Incorporated - // http://www.ti.com/ ALL RIGHTS RESERVED $ //########################################################################### #include "DSP28x_Project.h" // Device Headerfile and Examples Include File // Prototype statements for functions found within this file. __interrupt void cpu_timer0_isr(void); void main(void) { // Step 1. Initialize System Control: // PLL, WatchDog, enable Peripheral Clocks // This example function is found in the DSP2833x_SysCtrl.c file. InitSysCtrl(); // Step 3. Clear all interrupts and initialize PIE vector table: // Disable CPU interrupts DINT; // Initialize the PIE control registers to their default state. // The default state is all PIE interrupts disabled and flags // are cleared. // This function is found in the DSP2833x_PieCtrl.c file. InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // This will populate the entire table, even if the interrupt // is not used in this example. This is useful for debug purposes. // The shell ISR routines are found in DSP2833x_DefaultIsr.c. // This function is found in DSP2833x_PieVect.c. InitPieVectTable(); // Interrupts that are used in this example are re-mapped to // ISR functions found within this file. EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.TINT0 = &cpu_timer0_isr; GpioCtrlRegs.GPBMUX1.bit.GPIO36 = 0; GpioCtrlRegs.GPBDIR.bit.GPIO36 = 1; EDIS; // This is needed to disable write to EALLOW protected registers // Step 4. Initialize the Device Peripheral. This function can be // found in DSP2833x_CpuTimers.c InitCpuTimers(); // For this example, only initialize the Cpu Timers // Configure CPU-Timer 0, 1, and 2 to interrupt every second: // 150MHz CPU Freq, 1 second Period (in uSeconds) ConfigCpuTimer(&CpuTimer0, 150, 1000000); // To ensure precise timing, use write-only instructions to write to the entire register. Therefore, if any // of the configuration bits are changed in ConfigCpuTimer and InitCpuTimers (in DSP2833x_CpuTimers.h), the // below settings must also be updated. CpuTimer0Regs.TCR.all = 0x4000; // Use write-only instruction to set TSS bit = 0 // Step 5. User specific code, enable interrupts: // Enable CPU int1 which is connected to CPU-Timer 0 IER |= M_INT1; // Enable TINT0 in the PIE: Group 1 interrupt 7 PieCtrlRegs.PIEIER1.bit.INTx7 = 1; // Enable global Interrupts and higher priority real-time debug events: EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM // Step 6. IDLE loop. Just sit and loop forever (optional): for(;;); } __interrupt void cpu_timer0_isr(void) { CpuTimer0.InterruptCount++; GpioDataRegs.GPBTOGGLE.bit.GPIO36 = 1; // Acknowledge this interrupt to receive more interrupts from group 1 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; } //=========================================================================== // No more. //===========================================================================
위 코드가 TI가 배포하는 전체 예제를 제 상황에 맞게 살~~~짝 바꾼겁니다. 뭐 허접하지만.. 동영상으로도 보시죠 ㅋㅋ.
이제 뭔가 283335로 재미있는 예제를 하나 다뤄봐야 할텐데 말이죠. 뭐 아직 ADC도 해야하고.. 간단하게 나마 시리얼 통신이라도 해야죠~^^
'Hardware > MCU' 카테고리의 다른 글
[28335] DSP 28335 시리얼 통신 SCI 예제 한 번 구동해 보기 (6) | 2016.08.10 |
---|---|
[28335] DSP 28335 GPIO 기초 확인하기 (9) | 2016.05.04 |
[28335] TI 공식 홈페이지에서 28335용 예제와 라이브러리를 다운받자 - controlSUITE - (6) | 2016.04.27 |
[28335] Code Composer Studio (CCS) V6에서 28335 프로젝트 시작해보기 (20) | 2016.04.22 |
DC 모터의 모션(서보)제어 (Servo Control - Motion Control) (68) | 2011.07.06 |
[Cortex M3] 엔코더해석 결과를 일정시간간격으로 시리얼통신으로 전송하기 (42) | 2009.06.04 |
[Cortex M3] 단순 시리얼통신 테스트 ComPortMaster (4) | 2009.06.04 |