[STM32F439 EVM] 외부인터럽트 테스트


STM32F439 의 외부 인터럽트 소스는 각 포트0에서 15까지로 설정 가능하고 아래와 같이 그룹별로 관리 가능하다.

0에서 4번까지는 각각의 인터럽트 소스를 할당 할 수 있고 5~9, 10~15는 그룹으로되어 있어서 인터럽트 핸들러 내에서 구분해서 사용해야 한다.


EXTI0_IRQn

EXTI1_IRQn

EXTI2_IRQn

EXTI3_IRQn

EXTI4_IRQn

EXTI9_5_IRQn

EXTI15_10_IRQn



STM32F439 EVM 보드의 스위치 회로는 아래과 같고 PA8에 연결되어 있는 스위치를 이용하여 인터럽트 테스트 예제를 작성해 보았다.





STM32F439 외부 인터럽트 초기화 코드

static void EXTILine9_5_Config(void)

{

  GPIO_InitTypeDef   GPIO_InitStructure;


  /* Enable GPIOA clock */

  __GPIOA_CLK_ENABLE();

  

  /* Configure PA0 pin as input floating */

  GPIO_InitStructure.Mode = GPIO_MODE_IT_FALLING;

  GPIO_InitStructure.Pull = GPIO_PULLUP;

  GPIO_InitStructure.Pin = GPIO_PIN_8;

  HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);


  /* Enable and set EXTI Line0 Interrupt to the lowest priority */

  HAL_NVIC_SetPriority(EXTI9_5_IRQn, 2, 0);

  HAL_NVIC_EnableIRQ(EXTI9_5_IRQn);

}





STM32F439 외부 인터럽트 핸들러 함수

인터럽트 핸들러 함수 EXTI9_5_IRQHandler 내에서 HAL_GPIO_EXTI_Callback함수를 호출하는 구조로 되어 있다.


void EXTI9_5_IRQHandler(void)

{

  HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);

}


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

  if(GPIO_Pin == GPIO_PIN_8)

  {

        Led1Toggle();

  }

}


저작자 표시 비영리 변경 금지
신고

[STM32F439 EVM] I2C 테스트

[ST_MICRO]/STM32F43x | 2016.12.31 12:51
Posted by nexp

[STM32F439 EVM] I2C 테스트




[STM32F439 EVM] 에는 PB8(SCL), PB9(SDA)에 I2C가 할당되어 있다.




STM32F439 I2C 초기화 코드

I2C_HandleTypeDef I2cHandle;


#define I2Cx                             I2C1

#define I2Cx_CLK_ENABLE()                __I2C1_CLK_ENABLE()

#define I2Cx_SDA_GPIO_CLK_ENABLE()       __GPIOB_CLK_ENABLE()

#define I2Cx_SCL_GPIO_CLK_ENABLE()       __GPIOB_CLK_ENABLE() 


#define I2Cx_FORCE_RESET()               __I2C1_FORCE_RESET()

#define I2Cx_RELEASE_RESET()             __I2C1_RELEASE_RESET()


/* Definition for I2Cx Pins */

#define I2Cx_SCL_PIN                    GPIO_PIN_8

#define I2Cx_SCL_GPIO_PORT              GPIOB

#define I2Cx_SCL_AF                     GPIO_AF4_I2C1

#define I2Cx_SDA_PIN                    GPIO_PIN_7

#define I2Cx_SDA_GPIO_PORT              GPIOB

#define I2Cx_SDA_AF                     GPIO_AF4_I2C1


void I2CMaster_Init(void)

{

  GPIO_InitTypeDef  GPIO_InitStruct;

  

  /*##-1- Enable peripherals and GPIO Clocks #################################*/

  /* Enable GPIO TX/RX clock */

  I2Cx_SCL_GPIO_CLK_ENABLE();

  I2Cx_SDA_GPIO_CLK_ENABLE();

  /* Enable I2C1 clock */

  I2Cx_CLK_ENABLE(); 

  

  /*##-2- Configure peripheral GPIO ##########################################*/  

  /* I2C TX GPIO pin configuration  */

  GPIO_InitStruct.Pin       = I2Cx_SCL_PIN;

  GPIO_InitStruct.Mode      = GPIO_MODE_AF_OD;

  GPIO_InitStruct.Pull      = GPIO_PULLUP;

  GPIO_InitStruct.Speed     = GPIO_SPEED_FAST;

  GPIO_InitStruct.Alternate = I2Cx_SCL_AF;

  

  HAL_GPIO_Init(I2Cx_SCL_GPIO_PORT, &GPIO_InitStruct);

    

  /* I2C RX GPIO pin configuration  */

  GPIO_InitStruct.Pin = I2Cx_SDA_PIN;

  GPIO_InitStruct.Alternate = I2Cx_SDA_AF;

    

  HAL_GPIO_Init(I2Cx_SDA_GPIO_PORT, &GPIO_InitStruct);

  

  

  I2cHandle.Instance             = I2Cx;

  

  I2cHandle.Init.AddressingMode  = I2C_ADDRESSINGMODE_7BIT;

  I2cHandle.Init.ClockSpeed      = 100000;

  I2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLED;

  I2cHandle.Init.DutyCycle       = I2C_DUTYCYCLE_2;

  I2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_ENABLED;

  I2cHandle.Init.NoStretchMode   = I2C_NOSTRETCH_DISABLED;

  I2cHandle.Init.OwnAddress1     = 0xFE;//I2C_ADDRESS<<1;

  I2cHandle.Init.OwnAddress2     = 0xFE;    

  

  

  HAL_I2C_Init(&I2cHandle);

}




STM32F439 I2C Read/Write 함수

HAL_I2C_Master_Transmit(),  HAL_I2C_Master_Receive() 함수를 사용하면 쉽게 I2C제어가 가능하다.

unsigned char read8(unsigned char addr, unsigned char data)

{

    unsigned char result;


    unsigned char tx_buf[2];

    unsigned char rx_buf[4];

    tx_buf[0] = data;

    

    

    //gTimerTick6 = 0;

    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)addr, (uint8_t*)tx_buf, 1, 10000)!= HAL_OK)

    {

        //if(gTimerTick6>200)break;

    }

    

    //gTimerTick6 = 0;


    while(HAL_I2C_Master_Receive(&I2cHandle, (uint16_t)addr, (uint8_t *)rx_buf, 1, 10000) != HAL_OK)

    {

//if(gTimerTick6>200)break;

    }

  


    result = rx_buf[0];



    return result;


}


void write8(unsigned char addr, unsigned char reg, unsigned char data)

{

    unsigned char result;


    unsigned char tx_buf[2];

    unsigned char rx_buf[4];

    tx_buf[0] = reg;

tx_buf[1] = data;

    

    

    //gTimerTick6 = 0;

    while(HAL_I2C_Master_Transmit(&I2cHandle, (uint16_t)addr, (uint8_t*)tx_buf, 2, 10000)!= HAL_OK)

    {

        //if(gTimerTick6>200)break;

    }

}


저작자 표시 비영리 변경 금지
신고

[PIC32MZ EVM] 타이머 인터럽트 테스트


PIC32MZ 시리즈의 타이머/카운터는 9개가 있고 MPLAB 코드 생성 툴을 이용하면 쉽게 사용 할 수 있다.

한가지 아쉬운점은 기본 16비트 타이머 이고 32비트 타이머를 사용하려면 16비트 타이머2개를 조합해서 사용해야 되는것 같다.

STM32의 경우 별도의 32비트 타이머가 존재해서 편리 했는데...



MPLAB Harmony Configurator  를 이용하여 타이머드라이버 생성 할 수 있고 각종 파라미터를 설정하면 쉽게 초기화 할 수 있다.



자동으로 생성된 코드를 보면 아래와 같이 PIC32MZ의 타이머 설정부분의 코드가 생성된다.

void SYS_Initialize ( void* data )

{

    /* Core Processor Initialization */

    SYS_CLK_Initialize( NULL );

    sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);

    SYS_DEVCON_PerformanceConfig(SYS_CLK_SystemFrequencyGet());

    SYS_PORTS_Initialize();


    /* Initialize Drivers */


    sysObj.drvTmr0 = DRV_TMR_Initialize(DRV_TMR_INDEX_0, (SYS_MODULE_INIT *)&drvTmr0InitData);


    SYS_INT_VectorPrioritySet(INT_VECTOR_T1, INT_PRIORITY_LEVEL1);

    SYS_INT_VectorSubprioritySet(INT_VECTOR_T1, INT_SUBPRIORITY_LEVEL0);

 

 

     sysObj.drvUsart0 = DRV_USART_Initialize(DRV_USART_INDEX_0, (SYS_MODULE_INIT *)&drvUsart0InitData);

    SYS_INT_VectorPrioritySet(INT_VECTOR_UART1_TX, INT_DISABLE_INTERRUPT);

    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART1_TX, INT_SUBPRIORITY_LEVEL0);

    SYS_INT_VectorPrioritySet(INT_VECTOR_UART1_RX, INT_PRIORITY_LEVEL1);

    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART1_RX, INT_SUBPRIORITY_LEVEL0);

    SYS_INT_VectorPrioritySet(INT_VECTOR_UART1_FAULT, INT_PRIORITY_LEVEL1);

    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART1_FAULT, INT_SUBPRIORITY_LEVEL0);


    /* Initialize System Services */


    /*** Interrupt Service Initialization Code ***/

    SYS_INT_Initialize();

  

    /* Initialize Middleware */


    /* Enable Global Interrupts */

    SYS_INT_Enable();


    /* Initialize the Application */

    APP_Initialize();

}





PIC32MZ 타이머 기본 설정 이외 인터럽터 핸들러 생성 및  등록은 초기화 코드에서 해 주어야 한다.


SYS_MODULE_OBJ T0Handle ;


void APP_Initialize ( void )

{

    /* Place the App state machine in its initial state. */

    appData.state = APP_STATE_INIT;


    printf("PIC32MZ EVM Timer Test\r\n");


    

   T0Handle = DRV_TMR_Open( DRV_TMR_INDEX_0, DRV_IO_INTENT_EXCLUSIVE );

 

   // calculate the divider value and register the ISR

   uint32_t desiredFrequency = 1000 ; // 1 khertz

   uint32_t actualFrequency = DRV_TMR_CounterFrequencyGet(T0Handle) ;

   uint32_t divider = actualFrequency/desiredFrequency; // cacluate divider value

  

   DRV_TMR_AlarmRegister(T0Handle, divider, true, 0 , T0_ISRHandler);

 

   // Starting the Timer   

   DRV_TMR_Start(T0Handle);    

}





PIC32MZ  타이머 인터럽트 핸들러 함수


void T0_ISRHandler(uintptr_t context, uint32_t alarmCount)

{

   PLIB_PORTS_PinToggle(PORTS_ID_0, PORT_CHANNEL_H, 10 );

}






저작자 표시 비영리 변경 금지
신고

[PIC32MZ EVM] UART 테스트

[Microchip]/PIC32MZ | 2016.12.25 01:21
Posted by nexp

[PIC32MZ EVM] UART 테스트




PIC32MZ에서 UART를 사용하려면 MPLAB Harmony Configurator 를 실행해서 UART를 활성화 하고 설정해 주면 쉽게 사용가능하다.






[PIC32MZ EVM] 보드의 UART는 RD14->TXD, RD15-RXD에 할당되어 있다.

핀 다이어그램 에서 원하는 핀을 클릭해서 설정 할 수 있다.



그러면 아래와 같은 코드들을 자동으로 생성해 준다.

void SYS_Initialize ( void* data )

{

    /* Core Processor Initialization */

    SYS_CLK_Initialize( NULL );

    sysObj.sysDevcon = SYS_DEVCON_Initialize(SYS_DEVCON_INDEX_0, (SYS_MODULE_INIT*)&sysDevconInit);

    SYS_DEVCON_PerformanceConfig(SYS_CLK_SystemFrequencyGet());

    SYS_PORTS_Initialize();


    /* Initialize Drivers */

    sysObj.drvUsart0 = DRV_USART_Initialize(DRV_USART_INDEX_0, (SYS_MODULE_INIT *)&drvUsart0InitData);

    SYS_INT_VectorPrioritySet(INT_VECTOR_UART1_TX, INT_DISABLE_INTERRUPT);

    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART1_TX, INT_SUBPRIORITY_LEVEL0);

    SYS_INT_VectorPrioritySet(INT_VECTOR_UART1_RX, INT_PRIORITY_LEVEL1);

    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART1_RX, INT_SUBPRIORITY_LEVEL0);

    SYS_INT_VectorPrioritySet(INT_VECTOR_UART1_FAULT, INT_PRIORITY_LEVEL1);

    SYS_INT_VectorSubprioritySet(INT_VECTOR_UART1_FAULT, INT_SUBPRIORITY_LEVEL0);


    /* Initialize System Services */


    /*** Interrupt Service Initialization Code ***/

    SYS_INT_Initialize();

  

    /* Initialize Middleware */


    /* Enable Global Interrupts */

    SYS_INT_Enable();


    /* Initialize the Application */

    APP_Initialize();

}




void SYS_PORTS_Initialize(void)

{

    /* PORT D Initialization */

    PLIB_PORTS_OpenDrainEnable(PORTS_ID_0, PORT_CHANNEL_D, SYS_PORT_D_ODC);

    PLIB_PORTS_Write( PORTS_ID_0, PORT_CHANNEL_D,  SYS_PORT_D_LAT);

    PLIB_PORTS_DirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_D,  SYS_PORT_D_TRIS ^ 0xFFFF);

    PLIB_PORTS_ChangeNoticePerPortTurnOn(PORTS_ID_0, PORT_CHANNEL_D);

    PLIB_PORTS_ChannelModeSelect(PORTS_ID_0, PORT_CHANNEL_D, SYS_PORT_D_ANSEL ^ 0xFFFF, PORTS_PIN_MODE_DIGITAL);

    PLIB_PORTS_ChannelChangeNoticeEnable(PORTS_ID_0, PORT_CHANNEL_D, SYS_PORT_D_CNEN);

    PLIB_PORTS_ChannelChangeNoticePullUpEnable(PORTS_ID_0, PORT_CHANNEL_D, SYS_PORT_D_CNPU);

    PLIB_PORTS_ChannelChangeNoticePullDownEnable(PORTS_ID_0, PORT_CHANNEL_D, SYS_PORT_D_CNPD);

    

    /* PORT H Initialization */

    PLIB_PORTS_OpenDrainEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_ODC);

    PLIB_PORTS_Write( PORTS_ID_0, PORT_CHANNEL_H,  SYS_PORT_H_LAT);

    PLIB_PORTS_DirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_H,  SYS_PORT_H_TRIS ^ 0xFFFF);

    PLIB_PORTS_ChangeNoticePerPortTurnOn(PORTS_ID_0, PORT_CHANNEL_H);

    PLIB_PORTS_ChannelModeSelect(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_ANSEL ^ 0xFFFF, PORTS_PIN_MODE_DIGITAL);

    PLIB_PORTS_ChannelChangeNoticeEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_CNEN);

    PLIB_PORTS_ChannelChangeNoticePullUpEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_CNPU);

    PLIB_PORTS_ChannelChangeNoticePullDownEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_CNPD);



    /* PPS Input Remapping */

    PLIB_PORTS_RemapInput(PORTS_ID_0, INPUT_FUNC_U1RX, INPUT_PIN_RPD14 );


    /* PPS Output Remapping */

    PLIB_PORTS_RemapOutput(PORTS_ID_0, OUTPUT_FUNC_U1TX, OUTPUT_PIN_RPD15 );

}






PIC32MZ UART 송수신 함수


void U0_PutByte (char chr)

{

   PLIB_USART_TransmitterByteSend (DRV_USART_INDEX_0, chr); 

   //U4TXREG = chr;


   while (! PLIB_USART_TransmitterIsEmpty (DRV_USART_INDEX_0));

  //while (! U4STAbits.TRMT); 

}



unsigned char U0_GetByte (char chr)

{

    while(!PLIB_USART_ReceiverDataIsAvailable(DRV_USART_INDEX_0));

    //while(U1STAbits.URXDA == 0);

    

    return PLIB_USART_ReceiverByteReceive(DRV_USART_INDEX_0);

}







XC32 컴파일러에서 printf 함수를 사용하고 싶다면 _mon_putc() 함수를 재정의 해 주면 사용할 수 있다.


void _mon_putc(char c)

{

     U0_PutByte(c);






저작자 표시 비영리 변경 금지
신고
TAG PIC32MZ, UART

PIC32MZ 개발 환경 설정

[Microchip]/PIC32MZ | 2016.12.25 01:20
Posted by nexp

PIC32MZ 개발 환경 설정




PIC32MZ 개발을 위해서는  MCU펌웨어 개발 프레임워크인 MPLAB® Harmony 라는 툴이 필요하다.

이거 언제 또 공부하나?


그런데 막상 사용해 보니 상당히 간단하고 편리한것 같다.


우선 프로그램을 다운로드 하고 설치 해보자

MPLAB

http://www.microchip.com/mplab/mplab-ide-home


하모니 페키지

http://www.microchip.com/mplab/mplab-harmony




MPLABX 프로그램 실행하고 새로운 프로젝트롤 생성한다.

하모니 프로젝트를 선택하고 위자드로 클릭 몇번하면 쉽게 새로운 프로젝트 생성이 가능하다.






디바이스 선택

[PIC32MZ EVM] 보드는 PIC32MZ 시리즈 PIC32MZ2048EFM144 이므로 이 장치를 선택한다.





생성이 되면 기본으로 MPLAB Harmony Configurator 가 실행되고 다양한 페리 설정을 간편하게 할수 있다.




PIC32MZ 구동에 기본이 되는 클럭 설정을 해 보면 아래 그림과 같이 클럭 소스나, 속도 및 다양한 설정을 쉽게 설정 할 수 있다.





이렇게 해서 코드를 생성하면 자동으로 아래와 같은 파일들을 생성해 준다.




생성된 파일중 app.c 파일을 수정하면 원하는 기능을 수행 할 수 있다.

초기화 함수

void APP_Initialize ( void )

{

    /* Place the App state machine in its initial state. */

    appData.state = APP_STATE_INIT;


    /* TODO: Initialize your application's state machine and other

     * parameters.

    */

}





그리고 APP_Tasks() 함수에서 사용자 코드를 작성해 주면 된다. RTOS 같은 구조 인데 실제는 RTOS는 아니고 추후 RTOS를 사용 하더라고 동일한 구조를 사용하기 위해 이런 형태의 코드가 생성되는것 같다.

코드의 호환성은 좋아지겠지만 성능 측면은 양보를 해야 할것 같다. 물론 PIC32MZ 속도가 200Mhz로 구동되기 때문에 큰 차이는 없어 보인다.


간단한 예제로 [PIC32MZ EVM] 보드의 LED를 깜박이는 예제를 작성해 보면 아래와 같다.

void APP_Tasks ( void )

{


    /* Check the application's current state. */

    switch ( appData.state )

    {

        /* Application's initial state. */

        case APP_STATE_INIT:

        {

            bool appInitialized = true;

       

            if (appInitialized)

            {

            

                appData.state = APP_STATE_SERVICE_TASKS;

            }

            break;

        }


        case APP_STATE_SERVICE_TASKS:

        {

            //사용자 코드 작성 부분

            PLIB_PORTS_PinToggle(PORTS_ID_0, PORT_CHANNEL_H, 10 );

            Delay(100);

            break;

        }


        /* TODO: implement your application state machine.*/

        


        /* The default state should never be executed. */

        default:

        {

            /* TODO: Handle error in application's state machine. */

            break;

        }

    }

}




참고로 MPLAB Harmony Configurator에서 GPIO설정을 해 주면 초기화 코드를 생성해 준다.





MPLAB Harmony Configurator 는 Tools 메뉴에서 실행 할 수 있다. (처음에 이창이 사라져서 찾기 힘들었다.)




sys_ports_static.c 파일을 보면 GPIO관련 초기화된 코드가 생성된것을 확인 할 수 있다.


void SYS_PORTS_Initialize(void)

{

    /* PORT H Initialization */

    PLIB_PORTS_OpenDrainEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_ODC);

    PLIB_PORTS_Write( PORTS_ID_0, PORT_CHANNEL_H,  SYS_PORT_H_LAT);

    PLIB_PORTS_DirectionOutputSet( PORTS_ID_0, PORT_CHANNEL_H,  SYS_PORT_H_TRIS ^ 0xFFFF);

    PLIB_PORTS_ChangeNoticePerPortTurnOn(PORTS_ID_0, PORT_CHANNEL_H);

    PLIB_PORTS_ChannelModeSelect(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_ANSEL ^ 0xFFFF, PORTS_PIN_MODE_DIGITAL);

    PLIB_PORTS_ChannelChangeNoticeEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_CNEN);

    PLIB_PORTS_ChannelChangeNoticePullUpEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_CNPU);

    PLIB_PORTS_ChannelChangeNoticePullDownEnable(PORTS_ID_0, PORT_CHANNEL_H, SYS_PORT_H_CNPD);






마이크로 칩사의 새로운 IDE툴인 MPLABX와 하모니 툴을 이용하여 PIC32MZ 개발 환경을 테슽 해 보았는데...

결론적으로는 상당히 잘 만들어진 툴 같고 편리한것 같다.

특히 USB나 이더넷, TFT LCD같은 복잡한 페리를 사용하는데 있어서 자동 코드 생성툴이 상당히 편리 한것 같은데 마이크로 칩에서 제공하는 기본 구조를 지켜야 한다는 제약이 어떤 문제가 있을지 좀더 테스트 해 보아야 할것 같다.


쉽고 빠르게 기본 구조를 생성 할 수 있다는 점은 상당히 마음에 든다.





저작자 표시 비영리 변경 금지
신고

블로그 이미지

nexp

카테고리

분류 전체보기 (1536)
[MyProject] (42)
[TI] (75)
[NXP] (51)
[ST_MICRO] (128)
[FreeScale] (31)
[MSP430] (133)
[Microchip] (131)
Cortex-M (36)
[ATMEL] (29)
[AnalogDevice] (22)
ARM9 (24)
[AVR] (80)
[DSP] (111)
[8051] (21)
[MCU] (50)
[INTERFACE] (210)
[AppBoard] (23)
[ROBOT] (25)
[MODULE] (127)
[SENSOR] (41)
[DATA] (21)
[FPGA/PLD] (29)
[EVB] (1)
[Proramming] (38)
[MyLog] (6)
[IDEA] (0)
[Utility] (19)
[Book] (24)
취미생활 (4)
[Link] (2)

티스토리 툴바