본문으로 바로가기

[28335] DSP 28335 GPIO 기초 확인하기

category Hardware/MCU 2016.05.04 08:00

최근 DSP의 좋은 MCU인 TMS320F28335를 가지고 즐겁게 지내고 있는데요^^. 지난번에 Code Composer Studio (CCS)에서 프로젝트를 세팅하는 이야기[바로가기]를 하고 난 후, 제조사인 TI의 공식 예제를 받아서 설치하는 이야기[바로가기]도 했지요. 이제~ 항상 MCU를 학습하다 보면 나타나는 이야기입니다만, 항상~~ 시작은 GPIO를 다루는 부분이죠^^ 그걸 이야기하겠습니다. controlSUITE를 다운받아 설치하고 난 후, Project를 Import하면 되는데요... 

오늘 설명은 Example_2833xGpioToggle이라는 프로젝트를 import 하시면 됩니다. 아.. controlSUITE에서 import하는 프로젝트 과정은 지난 번 이야기[바로가기]로 다루었으니 오늘은 무사히 improt되었다고 보고 시작하죠^^

프로젝트 이름과 같은 C파일인 Example_2833xGpioToggle.c를 열어서 위에 표시된 것 처럼 제가 테스트할 코드를 삽입하면서 이야기를 하죠~~ 원래 이 예제에는 EXAMPLE이 3번까지 있는데 제가 테스트할 대상 보드를 위해서 EXAMPLE 4번을 추가하는 겁니다. 하드코딩에 익숙한 분들은 #define EXAMPLE4 1이라는 구문이 익숙하시겠죠^^

그리고 #if ~~ #endif도 추가합니다.

그리고... Gpio_select(void)라는 함수가 있는데요. 이 함수에 위에 표시된 두 줄을 추가 합니다. 여기서 살짝 설명을 보태면~

28335는 GPIO를 A, B, C에 각각 MUX1/2를 가지고 있습니다. 단, 모두다 16비트인데.. GPCMUX2만 8비트입니다. 뭐 이렇게 많은 GPIO를 가지고 있는것도 28335의 장점이겠죠^^ 아차.. 아무튼 제가 이번 예제에 사용하는 대상 보드가 GPIO C MUX1을 사용해야 합니다. 그래서 위 코드 처럼 GpioCtrlRegs.GPCMUX1이라는 명령으로 설정을 합니다. 이 명령을 통해 해당 비트를 0으로 하면 GPIO로 사용하는 거고, 1로 하면 각 GPIO에 할당되어 있는 특수 기능을 사용하는 것입니다. 처음 예제[바로가기]처럼 해당 비트를 직접 지정해도 되고, 위 예제처럼 all옵션으로 한 번에 지정해도 됩니다. 아무튼 저는 GPCMUX1을 모두 GPIO로 선언했지요^^ 그리고 제가 지금 예제로 사용하는 28335 보드는 [바로가기]에 나와있는 SyncWorks의 28335 초소형 버스 모듈인데요. 거기에 모터 실습용 킷인 SMC150[바로가기]을 사용하고 있습니다. 제조사가 제공하는 회로에 보면 

제가 GPIO 실습으로 사용할려는 LED8개가 위에 표시된 41-48번 연결핀에 물리는데요.. 해당 커넥터의 MCU 보드쪽 연결을 보면

GPIO64부터 71번까지 연결되어 있네요.. 그리고 그 설정이 GPIO C라서 이렇게 작업을 하고 있는거지요^^ 그리고 다시 바로 위 코드 220번행을 보면 나타나는 GpioCtrlRegs.GPCDIR이라는  설정을 만져줘야 합니다. 거기를 1로 하면 출력이 high, 0으로 하면 출력이 low가 됩니다. 그리고 이 두 설정은 28335의 보호영역으로 되어 있는 레지스터이기 때문에 EALLOW로 보호영역을 풀고 설정하고 EDIS로 다시 잠궈줘야 하는거구요. 그러면 이제 설정은 끝났습니다. 토글은 처음 예제에서 했던 것과 같은데요.

이제 빌드하기 전에 혹시 뭔가 느낌표하나가 뜨면서 실행은 되는듯 한데 찜찜하면 위 path를 지우시면 됩니다.

// add for example
void Gpio_example4(void)
{
      GpioDataRegs.GPCSET.all    =0xAAAAAAAA;
      GpioDataRegs.GPCCLEAR.all  =0x55555555;

   for(;;)
   {
      GpioDataRegs.GPCTOGGLE.all =0xFFFFFFFF;
      delay_loop();
    }
}

이제 위의 example4를 넣어 주면 되죠... 처음 시작할 때 0xAAAAAAAA이고, 0x55555555을 각각 set하고 clear하면 LED들이 하나는 켜지고, 하나는 꺼지고 번갈아 동작합니다. 이 상태에서 무한 루프인 for( ; ; )안에서 GpioDataRegs.GPCTOGGLE.all = 0xFFFFFFFF을 통해 토글되니까 번갈아 꺼졌다 켜졌다를 반복하는 거죠^^... 전체 코드는

//###########################################################################
// Description:
//! \addtogroup f2833x_example_list
//!
//! <h1>GPIO Toggle (gpio_toggle)</h1>
//!
//!  \note ALL OF THE I/O'S TOGGLE IN THIS PROGRAM.  MAKE SURE
//!  THIS WILL NOT DAMAGE YOUR HARDWARE BEFORE RUNNING THIS
//!  EXAMPLE.
//!
//!  Three different examples are included. Select the example
//!  (data, set/clear or toggle) to execute before compiling using
//!  the macros found at the top of the code.
//!
//!  Each example toggles all the GPIOs in a different way, the first
//!  through writing values to the GPIO DATA registers, the second through
//!  the SET/CLEAR registers and finally the last through the TOGGLE register
//!
//!  The pins can be observed using Oscilloscope.
//
//###########################################################################
// $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

// Select the example to compile in.  Only one example should be set as 1
// the rest should be set as 0.
#define EXAMPLE1 0  // Use DATA registers to toggle I/O's
#define EXAMPLE2 0  // Use SET/CLEAR registers to toggle I/O's
#define EXAMPLE3 0  // Use TOGGLE registers to toggle I/O's

// add for example
#define EXAMPLE4 1  // Example for SMC150 B/D

// Prototype statements for functions found within this file.
void delay_loop(void);
void Gpio_select(void);
void Gpio_example1(void);
void Gpio_example2(void);
void Gpio_example3(void);
void Gpio_example4(void); // add for example

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 2. Initialize GPIO:
// This example function is found in the DSP2833x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
// InitGpio();  // Skipped for this example

// For this example use the following configuration:
   Gpio_select();

// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
   DINT;

// Initialize 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();

// Step 4. Initialize all the Device Peripherals:
// This function is found in DSP2833x_InitPeripherals.c
// InitPeripherals(); // Not required for this example

// Step 5. User specific code:

#if EXAMPLE1

    // This example uses DATA registers to toggle I/O's
    Gpio_example1();

#endif  // - EXAMPLE1

#if EXAMPLE2

    // This example uses SET/CLEAR registers to toggle I/O's
    Gpio_example2();

#endif

#if EXAMPLE3

    // This example uses TOGGLE registers to toggle I/O's
    Gpio_example3();

#endif

// add for example
#if EXAMPLE4

    // This example uses TOGGLE registers to toggle I/O's
    Gpio_example4();

#endif
}

void delay_loop()
{
    volatile long i;
    for (i = 0; i < 1000000; i++) {}
}

void Gpio_example1(void)
{
   // Example 1:
   // Toggle I/Os using DATA registers

   for(;;)
   {
       GpioDataRegs.GPADAT.all    =0xAAAAAAAA;
       GpioDataRegs.GPBDAT.all    =0x0000000A;

       delay_loop();

       GpioDataRegs.GPADAT.all    =0x55555555;
       GpioDataRegs.GPBDAT.all    =0x00000005;

       delay_loop();
    }
}

void Gpio_example2(void)
{
   // Example 2:
   // Toggle I/Os using SET/CLEAR registers
   for(;;)
   {

       GpioDataRegs.GPASET.all    =0xAAAAAAAA;
       GpioDataRegs.GPACLEAR.all  =0x55555555;

       GpioDataRegs.GPBSET.all    =0x0000000A;
       GpioDataRegs.GPBCLEAR.all  =0x00000005;

       delay_loop();

       GpioDataRegs.GPACLEAR.all    =0xAAAAAAAA;
       GpioDataRegs.GPASET.all      =0x55555555;

       GpioDataRegs.GPBCLEAR.all    =0x0000000A;
       GpioDataRegs.GPBSET.all      =0x00000005;

       delay_loop();
    }
}

void Gpio_example3(void)
{
   // Example 2:
   // Toggle I/Os using TOGGLE registers

   // Set pins to a known state

      GpioDataRegs.GPASET.all    =0xAAAAAAAA;
      GpioDataRegs.GPACLEAR.all  =0x55555555;

      GpioDataRegs.GPBSET.all    =0x0000000A;
      GpioDataRegs.GPBCLEAR.all  =0x00000005;

   // Use TOGGLE registers to flip the state of
   // the pins.
   // Any bit set to a 1 will flip state (toggle)
   // Any bit set to a 0 will not toggle.

   for(;;)
   {
      GpioDataRegs.GPATOGGLE.all =0xFFFFFFFF;
      GpioDataRegs.GPBTOGGLE.all =0xFFFFFFFF; //0x0000000F;
      delay_loop();
    }
}

// add for example
void Gpio_example4(void)
{
      GpioDataRegs.GPCSET.all    =0xAAAAAAAA;
      GpioDataRegs.GPCCLEAR.all  =0x55555555;

   for(;;)
   {
      GpioDataRegs.GPCTOGGLE.all =0xFFFFFFFF;
      delay_loop();
    }
}

void Gpio_select(void)
{
    EALLOW;
	GpioCtrlRegs.GPAMUX1.all = 0x00000000;  // All GPIO
	GpioCtrlRegs.GPAMUX2.all = 0x00000000;  // All GPIO
	GpioCtrlRegs.GPAMUX1.all = 0x00000000;  // All GPIO
    GpioCtrlRegs.GPADIR.all = 0xFFFFFFFF;   // All outputs
    GpioCtrlRegs.GPBDIR.all = 0xFFFFFFFF;	// All outputs

    // add for example
    GpioCtrlRegs.GPCMUX1.all = 0x00000000;
    GpioCtrlRegs.GPCDIR.all = 0xFFFFFFFF;
    EDIS;
}
//===========================================================================
// No more.
//===========================================================================

입니다. 뭐 TI의 공식 예제를 따라하는 거니 어려울 건 없지요^^...

뭐.. 당연히 잘 동작하는 거지만.. 동영상도 하나 첨부합니다.~^^

신고