华大HC32F448中断的使用方法

该文章已生成可运行项目,

这里给出两种写法,可以根据需求自行判断需要哪种写法,本文使用华大官方库,软件使用keil5。

方法1

方法1是华大官方库的例程写法。

下面以官方串口例程分析为例程分析

先贴源码

/* Peripheral register WE/WP selection */
#define LL_PERIPH_SEL                   (LL_PERIPH_GPIO | LL_PERIPH_FCG | LL_PERIPH_PWC_CLK_RMU | \
                                         LL_PERIPH_EFM)

/* USART RX/TX pin definition */
#define USART_RX_PORT                   (GPIO_PORT_C)   /* PC11: USART2_RX */
#define USART_RX_PIN                    (GPIO_PIN_11)
#define USART_RX_GPIO_FUNC              (GPIO_FUNC_37)

#define USART_TX_PORT                   (GPIO_PORT_C)   /* PC10: USART2_TX */
#define USART_TX_PIN                    (GPIO_PIN_10)
#define USART_TX_GPIO_FUNC              (GPIO_FUNC_36)

/* USART unit definition */
#define USART_UNIT                      (CM_USART2)
#define USART_FCG_ENABLE()              (FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_USART2, ENABLE))

/* USART Tx complete flag select: USART_INT_TX_CPLT or USART_INT_TX_END */
#define USART_TX_CPLT_FLAG              (USART_INT_TX_CPLT)

/* USART interrupt definition */
#define USART_RX_ERR_IRQn               (INT000_IRQn)
#define USART_RX_ERR_INT_SRC            (INT_SRC_USART2_EI)

#define USART_RX_FULL_IRQn              (INT001_IRQn)
#define USART_RX_FULL_INT_SRC           (INT_SRC_USART2_RI)

#define USART_TX_EMPTY_IRQn             (INT002_IRQn)
#define USART_TX_EMPTY_INT_SRC          (INT_SRC_USART2_TI)

#define USART_TX_CPLT_IRQn              (INT003_IRQn)
#if (USART_INT_TX_CPLT == USART_TX_CPLT_FLAG)
#define USART_TX_CPLT_INT_SRC           (INT_SRC_USART2_TCI)
#elif (USART_INT_TX_END == USART_TX_CPLT_FLAG)
#define USART_TX_CPLT_INT_SRC           (INT_SRC_USART2_TENDI)
#else
#error "USART_TX_CPLT_FLAG defined error"
#endif

/* Ring buffer size */
#define RING_BUF_SIZE                   (500UL)
static uint8_t m_au8DataBuf[RING_BUF_SIZE];
static stc_ring_buf_t m_stcRingBuf;
static __IO en_flag_status_t m_enTxCompleteFlag = SET;

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/

/**
 * @brief  USART transmit data register empty IRQ callback.
 * @param  None
 * @retval None
 */
static void USART_TxEmpty_IrqCallback(void)
{
    uint8_t u8Data;

    if (!BUF_Empty(&m_stcRingBuf)) {
        (void)BUF_Read(&m_stcRingBuf, &u8Data, 1UL);
        USART_WriteData(USART_UNIT, (uint16_t)u8Data);
    } else {
#if (USART_INT_TX_CPLT == USART_TX_CPLT_FLAG)
        USART_FuncCmd(USART_UNIT, USART_INT_TX_CPLT, ENABLE);
#elif (USART_INT_TX_END == USART_TX_CPLT_FLAG)
        USART_FuncCmd(USART_UNIT, USART_INT_TX_END, ENABLE);
#endif
    }
}

/**
 * @brief  USART transmit complete IRQ callback.
 * @param  None
 * @retval None
 */
static void USART_TxComplete_IrqCallback(void)
{
    m_enTxCompleteFlag = SET;
#if (USART_INT_TX_CPLT == USART_TX_CPLT_FLAG)
    USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_CPLT | USART_INT_TX_EMPTY), DISABLE);
#elif (USART_INT_TX_END == USART_TX_CPLT_FLAG)
    USART_ClearStatus(USART_UNIT, USART_FLAG_TX_END);
    USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_EMPTY), DISABLE);
#endif
}

/**
 * @brief  USART RX IRQ callback
 * @param  None
 * @retval None
 */
static void USART_RxFull_IrqCallback(void)
{
    uint8_t u8Data = (uint8_t)USART_ReadData(USART_UNIT);

    (void)BUF_Write(&m_stcRingBuf, &u8Data, 1UL);
}

/**
 * @brief  USART error IRQ callback.
 * @param  None
 * @retval None
 */
static void USART_RxError_IrqCallback(void)
{
    (void)USART_ReadData(USART_UNIT);

    USART_ClearStatus(USART_UNIT, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
}

/**
 * @brief  Instal IRQ handler.
 * @param  [in] pstcConfig      Pointer to struct @ref stc_irq_signin_config_t
 * @param  [in] u32Priority     Interrupt priority
 * @retval None
 */
static void INTC_IrqInstalHandler(const stc_irq_signin_config_t *pstcConfig, uint32_t u32Priority)
{
    if (NULL != pstcConfig) {
        (void)INTC_IrqSignIn(pstcConfig);
        NVIC_ClearPendingIRQ(pstcConfig->enIRQn);
        NVIC_SetPriority(pstcConfig->enIRQn, u32Priority);
        NVIC_EnableIRQ(pstcConfig->enIRQn);
    }
}

/**
 * @brief  Main function of UART interrupt project
 * @param  None
 * @retval int32_t return value, if needed
 */
int32_t main(void)
{
    stc_usart_uart_init_t stcUartInit;
    stc_irq_signin_config_t stcIrqSigninConfig;

    /* MCU Peripheral registers write unprotected */
    LL_PERIPH_WE(LL_PERIPH_SEL);

    /* Initialize BSP system clock. */
    BSP_CLK_Init();

    /* Initialize BSP expand IO. */
    BSP_IO_Init();

    /* Initialize BSP LED. */
    BSP_LED_Init();

    /* Configure USART RX/TX pin. */
    GPIO_SetFunc(USART_RX_PORT, USART_RX_PIN, USART_RX_GPIO_FUNC);
    GPIO_SetFunc(USART_TX_PORT, USART_TX_PIN, USART_TX_GPIO_FUNC);

    /* Enable peripheral clock */
    USART_FCG_ENABLE();

    /* Initialize ring buffer function. */
    (void)BUF_Init(&m_stcRingBuf, m_au8DataBuf, sizeof(m_au8DataBuf));

    /* Initialize UART. */
    (void)USART_UART_StructInit(&stcUartInit);
    stcUartInit.u32ClockDiv = USART_CLK_DIV64;
    stcUartInit.u32Baudrate = 115200UL;
    stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
    if (LL_OK != USART_UART_Init(USART_UNIT, &stcUartInit, NULL)) {
        BSP_LED_On(LED_RED);
        for (;;) {
        }
    }

    /* Register RX error IRQ handler && configure NVIC. */
    stcIrqSigninConfig.enIRQn = USART_RX_ERR_IRQn;
    stcIrqSigninConfig.enIntSrc = USART_RX_ERR_INT_SRC;
    stcIrqSigninConfig.pfnCallback = &USART_RxError_IrqCallback;
    INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);

    /* Register RX full IRQ handler && configure NVIC. */
    stcIrqSigninConfig.enIRQn = USART_RX_FULL_IRQn;
    stcIrqSigninConfig.enIntSrc = USART_RX_FULL_INT_SRC;
    stcIrqSigninConfig.pfnCallback = &USART_RxFull_IrqCallback;
    INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);

    /* Register TX empty IRQ handler && configure NVIC. */
    stcIrqSigninConfig.enIRQn = USART_TX_EMPTY_IRQn;
    stcIrqSigninConfig.enIntSrc = USART_TX_EMPTY_INT_SRC;
    stcIrqSigninConfig.pfnCallback = &USART_TxEmpty_IrqCallback;
    INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);

    /* Register TX complete IRQ handler && configure NVIC. */
    stcIrqSigninConfig.enIRQn = USART_TX_CPLT_IRQn;
    stcIrqSigninConfig.enIntSrc = USART_TX_CPLT_INT_SRC;
    stcIrqSigninConfig.pfnCallback = &USART_TxComplete_IrqCallback;
    INTC_IrqInstalHandler(&stcIrqSigninConfig, DDL_IRQ_PRIO_DEFAULT);

    /* MCU Peripheral registers write protected */
    LL_PERIPH_WP(LL_PERIPH_SEL);

    /* Enable RX function */
    USART_FuncCmd(USART_UNIT, (USART_RX | USART_INT_RX), ENABLE);

    for (;;) {
        if ((SET == m_enTxCompleteFlag) && !BUF_Empty(&m_stcRingBuf)) {
            m_enTxCompleteFlag = RESET;
#if (USART_INT_TX_END == USART_TX_CPLT_FLAG)
            USART_FuncCmd(USART_UNIT, USART_INT_TX_END, DISABLE);
#endif
            USART_FuncCmd(USART_UNIT, (USART_TX | USART_INT_TX_EMPTY), ENABLE);
        }
    }
}

由源码可知,该例程为串口申请了四个中断,每个中断都有一个自己的对应的回调函数,也就是四个中断号,四个回调函数。

中断初始化部分,申请了四个中断类型,分别对应了四个中断号以及中断回调函数。其中这四个中断号分别是INT000_IRQn、INT001_IRQn、INT002_IRQn、INT003_IRQn。从官方文档的下表可知,官方例程用的是类型A,写入的中断请求编号映射,但是这个中断号资源有限只有16个,且不能重复,也就是说用这个方法申请中断只能申请16个中断编号,对于小项目可以这么写,但是稍微大一点的项目这样写就中断号就有点不够用了。下面引出第二种方法。

方法2

由上表可知,中断请求编号映射有两种方法,方法A是16个可编程的中断号,比如我串口1空闲中断可以用INT000_IRQn,串口2空闲中断INT001_IRQn,定时器溢出中断可以用INT002_IRQn,...

INT000_IRQn~NT015_IRQn这16个中断号可以随意分配给你想用的中断申请(同一个项目申请的中断号不能重复申请,比如我串口1空闲中断用INT000_IRQn,但是我串口2空闲中断也用INT000_IRQn。这是不可行的),但是资源有限,只有16个,遇到稍微大一点的项目就有点力不从心了。

我们再来观察此表类型B,我们以USART_2_EI这个中断举例。我们想用类型B的方法申请中断,就只用固定的就只能用IRQ[95]这个编号申请。

通过这个表查官方库95编号,对应的定义为USART2_IRQn

接下来我们通过代码进行整体中断实验。先贴代码

//中断服务函数
void USART2_Handler(void)
{
	
	if(USART_GetStatus(CM_USART2,(USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN)))
	{
		(void)USART_ReadData(CM_USART2);
		USART_ClearStatus(CM_USART2, (USART_FLAG_PARITY_ERR | USART_FLAG_FRAME_ERR | USART_FLAG_OVERRUN));
		return;	
	}
	
	if(USART_GetStatus(CM_USART2,USART_FLAG_RX_TIMEOUT))
	{
		//.....
		USART_ClearStatus(CM_USART2, USART_FLAG_RX_TIMEOUT);
		
		return;
	}
	NBRecevieMessageHadle(&nbATMessage,(uint8_t)USART_ReadData(CM_USART2));	
}
//c串口二初始化函数
void Usart02ConfingFunction(void)
{
	
	stc_usart_uart_init_t stcUartInit;
	stc_irq_signin_config_t stcIrqSigninConfig;
	GPIO_SetDebugPort(GPIO_PIN_TRST, DISABLE);
	GPIO_SetDebugPort(GPIO_PIN_SWO, DISABLE);
	GPIO_SetFunc(GPIO_PORT_A,GPIO_PIN_08,GPIO_FUNC_37);
    GPIO_SetFunc(GPIO_PORT_C,GPIO_PIN_09,GPIO_FUNC_36);
	
	FCG_Fcg3PeriphClockCmd(FCG3_PERIPH_USART2, ENABLE);
	USART_DeInit(CM_USART2);
    (void)USART_UART_StructInit(&stcUartInit);
    stcUartInit.u32ClockDiv = USART_CLK_DIV64;
    stcUartInit.u32Baudrate = 115200UL;
    stcUartInit.u32OverSampleBit = USART_OVER_SAMPLE_8BIT;
    USART_UART_Init(CM_USART2, &stcUartInit, NULL);
    /* Enable USART_TX | USART_RX | USART_INT_RX function */
	 /* Register RX error IRQ handler. */
    stcIrqSigninConfig.enIRQn = USART2_IRQn;
    stcIrqSigninConfig.enIntSrc = INT_SRC_USART1_EI;
    stcIrqSigninConfig.pfnCallback = NULL;
    (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);

    /* Register RX timeout IRQ handler. */
    stcIrqSigninConfig.enIRQn = USART2_IRQn;
    stcIrqSigninConfig.enIntSrc = INT_SRC_USART1_RTO;
    stcIrqSigninConfig.pfnCallback = NULL;
	(void)INTC_IrqSignIn(&stcIrqSigninConfig);
    NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
	
	/* Register RX error IRQ handler. */
    stcIrqSigninConfig.enIRQn = USART2_IRQn;
    stcIrqSigninConfig.enIntSrc = INT_SRC_USART1_RI;
    stcIrqSigninConfig.pfnCallback = NULL;
    (void)INTC_IrqSignIn(&stcIrqSigninConfig);
    NVIC_ClearPendingIRQ(stcIrqSigninConfig.enIRQn);
    NVIC_SetPriority(stcIrqSigninConfig.enIRQn, DDL_IRQ_PRIO_DEFAULT);
    NVIC_EnableIRQ(stcIrqSigninConfig.enIRQn);
    USART_FuncCmd(CM_USART2, (USART_RX|USART_TX| USART_INT_RX|USART_RX_TIMEOUT|USART_INT_RX_TIMEOUT), ENABLE);
}

我们这次实验用的依旧是USART2,申请了USART1_R2,USART2_RTO,USART2_EI,这三个中断,观察程序可知,这三个中断全都是用的一个中断编号。因为观察表可知,这三个中断事件全都是用的95这一个中断编号。中断回调函数这一项我全添NULL,这三个中断只要一发生就会直接跳到USART2_Handler这个中断服务函数,然后再根据if获取中断标志位,做出相应的动作即可。

这就是我分享的内容,如果有不对的地方欢迎大佬指出。

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值