225 lines
8.5 KiB
C
225 lines
8.5 KiB
C
#include "../main/SystemInclude.h"
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 配置 GPIO 引脚为外部中断输入
|
||
* @param EXTI_GPIOx: GPIO 端口 (pGPIO0/pGPIO1/pGPIO2)
|
||
* @param EXTI_PINx: GPIO 引脚掩码,如 GPIO_PIN_3
|
||
* @param EXTI_LINEx: EXTI 线号,如 EXTI_LINE_3
|
||
* @param EXTI_IRQx: 对应的中断 IRQ 号,如 EXTI2_3_IRQn
|
||
* @note 该函数将指定引脚配置为输入模式,并使能施密特触发器,
|
||
* 连接到 EXTI 线,并配置为上升沿触发中断(触发边沿可修改代码)。
|
||
* 注意:中断的 NVIC 使能和优先级需在外部处理,函数内已注释。
|
||
* @example
|
||
* GPIO_EXTI_Init(pGPIO0, GPIO_PIN_3, EXTI_LINE_3, EXTI2_3_IRQn);
|
||
**/
|
||
void GPIO_EXTI_Init(GPIO_TypeDef* EXTI_GPIOx ,uint16_t EXTI_PINx ,EXTI_LINE_t EXTI_LINEx,IRQn_Type EXTI_IRQx)
|
||
{
|
||
GPIO_InitTypeDef GPIO_InitStructure;// GPIO配置结构体
|
||
EXTI_InitTypeDef EXTI_InitStructure;// EXTI配置结构体
|
||
/* 1. 配置引脚参数 */
|
||
GPIO_InitStructure.Pin = EXTI_PINx; // Pinx
|
||
GPIO_InitStructure.Mode = GPIO_MODE_INPUT; // 输入模式
|
||
// GPIO_InitStructure.Pull = GPIO_NOPULL; // 无上拉/下拉电阻 GPIO_NOPULL
|
||
GPIO_InitStructure.Pull = GPIO_PULLUP;
|
||
GPIO_InitStructure.SchmittTrigger = ENABLE; // 开启施密特触发器输入
|
||
GPIO_InitStructure.Alternate = GPIOx_AF_GPIO;
|
||
LHL_GPIO_Init(EXTI_GPIOx, &GPIO_InitStructure); // 初始化Pin为输入
|
||
|
||
LHL_GPIO_SetEXTILine(EXTI_GPIOx, EXTI_PINx); // 设置Pin为EXTI0
|
||
|
||
/* 2. 配置EXTI参数 */
|
||
EXTI_InitStructure.Line = EXTI_LINEx;
|
||
EXTI_InitStructure.Mode = EXTI_MODE_INTERRUPT; // EXTI中断模式
|
||
EXTI_InitStructure.Trigger = EXTI_TRIGGER_RISING; // 上升下降沿触发 EXTI_TRIGGER_RISING EXTI_TRIGGER_FALLING EXTI_TRIGGER_RISING_FALLING
|
||
EXTI_InitStructure.LineCmd = ENABLE; // 使能EXTI
|
||
LHL_EXTI_Init(&EXTI_InitStructure); // 设置EXTI
|
||
|
||
// NVIC_EnableIRQ(EXTI_IRQx); // 开启NVIC中断
|
||
// NVIC_SetPriority(EXTI_IRQx, 0); // 设置EXIT优先级
|
||
}
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 配置 LPTIM 输出事件为 EXTI 中断源
|
||
* @param lptimer: LPTIM1 或 LPTIM2
|
||
* @note LPTIM1 对应 EXTI_LINE_10,LPTIM2 对应 EXTI_LINE_11,
|
||
* 配置为上升沿触发中断模式。可用于将 LPTIM 事件作为唤醒源。
|
||
* @example LPTIM_EXTI_Init(LPTIM2);
|
||
**/
|
||
void LPTIM_EXTI_Init(LPTIM_TypeDef *lptimer)
|
||
{
|
||
EXTI_InitTypeDef EXTI_InitStructure;
|
||
|
||
if(lptimer == pLPTIM1) EXTI_InitStructure.Line = EXTI_LINE_10;
|
||
else EXTI_InitStructure.Line = EXTI_LINE_11;
|
||
EXTI_InitStructure.Mode = EXTI_MODE_INTERRUPT;
|
||
EXTI_InitStructure.Trigger = EXTI_TRIGGER_RISING;
|
||
EXTI_InitStructure.LineCmd = ENABLE;
|
||
LHL_EXTI_Init(&EXTI_InitStructure);
|
||
}
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 配置 ADC 错误/数据就绪输出为 EXTI 中断源
|
||
* @note ADC0 和 ADC1 的共用 EXTI_LINE_12,配置为上升沿触发中断模式。
|
||
* 可用于在 ADC 转换完成或错误时产生中断。
|
||
* @example ADC_EXTI_Init();
|
||
**/
|
||
void ADC_EXTI_Init(void)
|
||
{
|
||
|
||
EXTI_InitTypeDef EXTI_InitStructure;
|
||
|
||
EXTI_InitStructure.Line = EXTI_LINE_12;
|
||
EXTI_InitStructure.Mode = EXTI_MODE_INTERRUPT; // EXTI_MODE_EVENT
|
||
EXTI_InitStructure.Trigger = EXTI_TRIGGER_RISING;
|
||
EXTI_InitStructure.LineCmd = ENABLE;
|
||
LHL_EXTI_Init(&EXTI_InitStructure);
|
||
}
|
||
|
||
|
||
/* (PVD、RTC、DMA 的 EXTI 初始化函数可根据需要自行实现) */
|
||
// EXTI_LINE_8 = 0x0100u, /*!< External interrupt line 8 PVD(电压低于阈值标记)输出 */
|
||
// EXTI_LINE_9 = 0x0200u, /*!< External interrupt line 9 RTC闹钟事件 */
|
||
// EXTI_LINE_13 = 0x2000u, /*!< External interrupt line 13 DMA所有通道中断的或 */
|
||
|
||
//(void)PVD_EXTI_Init(void)
|
||
//(void)RTC_EXTI_Init(void)
|
||
//(void)DMA_EXTI_Init(void)
|
||
|
||
|
||
|
||
/*-=====================================================================================================
|
||
//外部中断回调
|
||
-=====================================================================================================*/
|
||
|
||
static exti_irq_callback_t exti_callbacks[EXTI_MAX_LINES] = {NULL};
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief 注册 EXTI 中断线的回调函数
|
||
* @param exti_linex: EXTI 线号,如 EXTI_LINE_3
|
||
* @param exti_irq_callback: 用户回调函数指针(无参数无返回值)
|
||
* @note 同一 EXTI 线只能注册一个回调,重复注册将被忽略。
|
||
* 根据线号自动使能对应的 NVIC 中断(分组关系见代码) 。
|
||
* @example
|
||
* void my_exti_callback(void) { ... }
|
||
* Exti_register_irq_callback(EXTI_LINE_3, my_exti_callback);
|
||
**/
|
||
void Exti_register_irq_callback(EXTI_LINE_t exti_linex, exti_irq_callback_t exti_irq_callback)
|
||
{
|
||
if (exti_linex == 0) return;//防止传0 或者不是EXTI_LINE_t的参数
|
||
uint8_t index = (uint8_t)__builtin_ctz((unsigned int)exti_linex); //获取exti_linex 索引编号
|
||
if(index >= EXTI_MAX_LINES) return;
|
||
if(exti_callbacks[index] != NULL) return;
|
||
|
||
exti_callbacks[index] = exti_irq_callback;
|
||
|
||
switch (index) { //获取 EXTI 线对应的 IRQ 号
|
||
case 0:
|
||
case 1:
|
||
NVIC_EnableIRQ(EXTI0_1_IRQn); NVIC_SetPriority(EXTI0_1_IRQn,0);
|
||
|
||
break;
|
||
case 2:
|
||
case 3:
|
||
NVIC_EnableIRQ(EXTI2_3_IRQn); NVIC_SetPriority(EXTI2_3_IRQn,0);
|
||
break;
|
||
case 4:
|
||
case 5:
|
||
case 6:
|
||
case 7:
|
||
NVIC_EnableIRQ(EXTI4_7_IRQn); NVIC_SetPriority(EXTI4_7_IRQn,0);
|
||
break;
|
||
|
||
case 10:
|
||
case 11:
|
||
NVIC_EnableIRQ(EXTI10_11_IRQn); NVIC_SetPriority(EXTI10_11_IRQn,0);
|
||
break;
|
||
|
||
case 12:
|
||
case 13:
|
||
NVIC_EnableIRQ(EXTI12_13_IRQn); NVIC_SetPriority(EXTI12_13_IRQn,0);
|
||
break;
|
||
default:
|
||
// 不支持的线 比如 8 9
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**------------------------------------------------------------------------
|
||
* @brief EXTI0 和 EXTI1 共享中断服务函数
|
||
* @note 分别检查 EXTI0 和 EXTI1 的中断标志,清除后调用对应线已注册的回调函数。
|
||
**/
|
||
void EXTI0_1_IRQHandler(void)
|
||
{
|
||
// 检查 EXTI0 和 EXTI1
|
||
if (LHL_EXTI_GetPending(EXTI_LINE_0) == SET) {
|
||
LHL_EXTI_ClearPending(EXTI_LINE_0);
|
||
if (exti_callbacks[0]) exti_callbacks[0]();
|
||
}
|
||
if (LHL_EXTI_GetPending(EXTI_LINE_1) == SET) {
|
||
LHL_EXTI_ClearPending(EXTI_LINE_1);
|
||
if (exti_callbacks[1]) exti_callbacks[1]();
|
||
}
|
||
}
|
||
/**------------------------------------------------------------------------
|
||
* @brief EXTI2 和 EXTI3 共享中断服务函数
|
||
* @note 分别检查 EXTI2 和 EXTI3 的中断标志,清除后调用对应线已注册的回调函数。
|
||
**/
|
||
void EXTI2_3_IRQHandler(void)
|
||
{
|
||
if (LHL_EXTI_GetPending(EXTI_LINE_2) == SET) {
|
||
LHL_EXTI_ClearPending(EXTI_LINE_2);
|
||
if (exti_callbacks[2]) exti_callbacks[2]();
|
||
}
|
||
if (LHL_EXTI_GetPending(EXTI_LINE_3) == SET) {
|
||
LHL_EXTI_ClearPending(EXTI_LINE_3);
|
||
if (exti_callbacks[3]) exti_callbacks[3]();
|
||
}
|
||
}
|
||
/**------------------------------------------------------------------------
|
||
* @brief EXTI4 至 EXTI7 共享中断服务函数
|
||
* @note 循环检查 EXTI4~7 的中断标志,清除后调用对应线已注册的回调函数。
|
||
**/
|
||
void EXTI4_7_IRQHandler(void)
|
||
{
|
||
for (int i = 4; i <= 7; i++) {
|
||
EXTI_LINE_t line = (EXTI_LINE_t)(1U << i);
|
||
if (LHL_EXTI_GetPending(line) == SET) {
|
||
LHL_EXTI_ClearPending(line);
|
||
if (exti_callbacks[i]) exti_callbacks[i]();
|
||
}
|
||
}
|
||
}
|
||
/**------------------------------------------------------------------------
|
||
* @brief EXTI10 和 EXTI11 共享中断服务函数
|
||
* @note 分别检查 EXTI10 和 EXTI11 的中断标志,清除后调用对应线已注册的回调函数。
|
||
**/
|
||
void EXTI10_11_IRQHandler(void)
|
||
{
|
||
// 检查 EXTI0 和 EXTI1
|
||
if (LHL_EXTI_GetPending(EXTI_LINE_10) == SET) {
|
||
LHL_EXTI_ClearPending(EXTI_LINE_10);
|
||
if (exti_callbacks[10]) exti_callbacks[10]();
|
||
}
|
||
if (LHL_EXTI_GetPending(EXTI_LINE_11) == SET) {
|
||
LHL_EXTI_ClearPending(EXTI_LINE_11);
|
||
if (exti_callbacks[11]) exti_callbacks[11]();
|
||
}
|
||
|
||
}
|
||
/**------------------------------------------------------------------------
|
||
* @brief EXTI12 和 EXTI13 共享中断服务函数
|
||
* @note 分别检查 EXTI12 和 EXTI13 的中断标志,清除后调用对应线已注册的回调函数。
|
||
**/
|
||
void EXTI12_13_IRQHandler(void)
|
||
{
|
||
// 检查 EXTI0 和 EXTI1
|
||
if (LHL_EXTI_GetPending(EXTI_LINE_12) == SET) {
|
||
if (exti_callbacks[12]) exti_callbacks[12]();
|
||
LHL_EXTI_ClearPending(EXTI_LINE_12);
|
||
}
|
||
else if (LHL_EXTI_GetPending(EXTI_LINE_13) == SET) {
|
||
LHL_EXTI_ClearPending(EXTI_LINE_13);
|
||
if (exti_callbacks[13]) exti_callbacks[13]();
|
||
}
|
||
|
||
}
|