[CH32V003]GPIO EXTERNAL Interrupt

GPIOによるインターラプト。
サンプルはネットで見つける事ができるのですが、

GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource3);
 

この1行がよくわからないので調査。インターラプトに設定するピンを素直にPC3とかPD1とか指定させてくれれば良いのに、GPIO_PinSource3???

https://www.wch-ic.com/downloads/CH32V003RM_PDF.html


EXTI0~EXTI7の8個の外部インタラプトが用意されている
GPIO(Px0~Px7(x=A/B/C/D))に設定ができる
ただし、EXTI0ならPx0と数字の部分が一致していないといけない。
EXTI0にPA0を割り当てると他のPB0,PC0,PD0に設定する事ができない。

という事か。

さっそくテストをしてみる。

//CH32V003 * 5V tolerant pins
//    -----------------------
//1 - PD4                                   PD3 - 20
//2 - PD5(UTX)                        PD2 - 19
//3 - PD6(URX)          (SWIO)PD1 - 18
//4 - PD7                      (MISO)PC7 - 17
//5 - PA1                     (MOSI)*PC6 - 16
//6 - PA2                      (SCK)*PC5 - 15
//7 - VSS (GNG)                      PC4 - 14
//8 - PD0                                    PC3 - 13
//9 - VDD                                   *PC2 - 12
//10- PC0                                   *PC1 - 11
//    -----------------------
#include "debug.h"


/* Global define */


/* Global Variable */
vu8 val;

/*********************************************************************
 * @fn      USARTx_CFG
 *
 * @brief   Initializes the USART2 & USART3 peripheral.
 *
 * @return  none
 */
void USARTx_CFG(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure = {0};
    USART_InitTypeDef USART_InitStructure = {0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1, ENABLE);

    /* USART1 TX-->D.5   RX-->D.6 */
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_30MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = 115200;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;

    USART_Init(USART1, &USART_InitStructure);
    USART_Cmd(USART1, ENABLE);
}
void GPIO_INIT(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure={0};

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD,ENABLE);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
    GPIO_Init(GPIOD, &GPIO_InitStructure);
}
void EXTI0_INT_INIT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};
    EXTI_InitTypeDef EXTI_InitStructure = {0};
    NVIC_InitTypeDef NVIC_InitStructure = {0};

    /* GPIO PD3 setting */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD, ENABLE);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOD, &GPIO_InitStructure);

    /*EXTernal Interrupt(EXTI)
    /* GPIOD ----> EXTI_Line3 */
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOD, GPIO_PinSource3);
    EXTI_InitStructure.EXTI_Line = EXTI_Line3;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    /* ベクタ割込みコントローラ(NVIC)を設定する*/
    NVIC_InitStructure.NVIC_IRQChannel = EXTI7_0_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}
void EXTI7_0_IRQHandler(void) __attribute__((interrupt("WCH-Interrupt-fast")));
void EXTI7_0_IRQHandler(void)
{
    EXTI_ClearFlag(EXTI_Line3); // 割り込みフラグをリセット
    GPIO_SetBits(GPIOD, GPIO_Pin_2); // CS HIGH
    Delay_Us(10);
    GPIO_ResetBits(GPIOD, GPIO_Pin_2); // CS LOW

}
/*********************************************************************
 * @fn      main
 *
 * @brief   Main program.
 *
 * @return  none
 */
int main(void)
{
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
    SystemCoreClockUpdate();
    Delay_Init();
#if (SDI_PRINT == SDI_PR_OPEN)
    SDI_Printf_Enable();
#else
    USART_Printf_Init(115200);
#endif
    printf("SystemClk:%d\r\n",SystemCoreClock);
    printf( "ChipID:%08x\r\n", DBGMCU_GetCHIPID() );

    USARTx_CFG();

    GPIO_INIT();
    EXTI0_INT_INIT();

    GPIO_ResetBits(GPIOD, GPIO_Pin_2); // CS LOW
    GPIO_ResetBits(GPIOD, GPIO_Pin_4); // CS LOW

    while(1)
    {
        GPIO_SetBits(GPIOD, GPIO_Pin_4); // CS HIGH
        Delay_Us(5);
        GPIO_ResetBits(GPIOD, GPIO_Pin_4); // CS LOW
        Delay_Ms(150);

//        while(USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET)
//        {
//            /* waiting for receiving finish */
//        }
//        val = (USART_ReceiveData(USART1));
//        USART_SendData(USART1, ~val);
//        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET)
//        {
//            /* waiting for sending finish */
//        }
    }
}

【動作】
・PD4を出力設定して、150msec毎に5usecのパルスを出力
・PD3を入力設定し、PD4のパルスを受ける。
・PD3が立下りを検出したら、PD2に10usecのパルスを出力する。
・クロックは、48MHzに設定

【検証の結果】


PD4黄色のパルスの立下りを検出、0.92usec程度遅れて、PD2緑のパルスが立ち上がる。

多少のブレはあり1usecになっている時もあるが、ロジアナの性能によるものともいえてEXTIのインターラプトとしてパルスが出るまでの時間が1usecかかるで問題ないかと。

5usecのパルスは7.65~7.75usecとロジアナでは見えて、10uパルスは、12.83~12.92 



コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

CH9329で日本語キーボード109で正しく表示する方法