华大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获取中断标志位,做出相应的动作即可。

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

### 移植 FreeRTOS 至华大 HC32F030 微控制器 #### 准备工作 为了成功移植FreeRTOS至HC32F030微控制器,需准备如下材料: - **开发环境**:推荐使用IAR Embedded Workbench 或 MDK-ARM Plus作为集成开发环境。 - **硬件平台**:目标设备为华大半导体生产的HC32F030系列MCU。 - **软件资源**: - 获取适用于Cortex-M0架构的FreeRTOS版本。可以从官方网站下载对应版本的源码包[^1]。 - 安装并配置好相应的编译工具链以及调试器。 #### 配置项目结构 创建一个新的工程文件,在此过程中需要注意的是要将必要的头文件路径加入到项目的预处理器设置当中。对于FreeRTOS而言,主要涉及以下几个部分: - `include` 文件夹下的所有公共接口定义; - `portable/IAR/ARM_CM0` 中特定于ARM Cortex-M0内核的支持函数实现; 这些目录应当被正确地链接入当前工程项目之中以便后续操作能够顺利进行[^4]。 #### 修改启动代码 针对不同厂商提供的标准外设库(DDL),可能需要调整初始化过程中的某些参数来适应具体的应用场景需求。比如时钟树配置、中断优先级分组设定等方面可能会有所差异。确保Systick定时器正常运作是十分重要的一步,这关系着系统的滴答计数能否稳定输出给操作系统调度器使用[^5]。 #### 编写应用程序框架 编写简单的测试程序验证基本功能是否可用是一个良好的开端。这里给出一段用于点亮LED灯泡的小例子供参考: ```c #include "FreeRTOS.h" #include "task.h" void vTaskFunction(void *pvParameters); int main(void){ /* 初始化系统 */ /* 创建任务 */ xTaskCreate(vTaskFunction,"Blink",configMINIMAL_STACK_SIZE,NULL,tskIDLE_PRIORITY,&pxCreatedTask); /* 启动多线程机制 */ vTaskStartScheduler(); } /* LED闪烁任务 */ void vTaskFunction(void *pvParameters){ TickType_t xLastWakeTime; const TickType_t xFrequency = pdMS_TO_TICKS(500UL); //每半秒触发一次 xLastWakeTime = xTaskGetTickCount(); for (;;){ led_toggle(); //切换LED状态 vTaskDelayUntil(&xLastWakeTime,xFrequency); } } ``` 上述代码展示了如何基于FreeRTOS构建一个多任务处理应用实例,并通过调用API实现了周期性的延时等待效果[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值