本次主要是使用按键触发外部中断,打印按下的按键,同时操作led灯。
外部中断操作流程参考《HC32F460系列的中断控制器INTC Rev1.1.pdf》中的使用方法。
1. 首先是介绍硬件电路的接法
1.1 按键电路
按键对应管脚 端口号:
按键 |
端口号 |
管脚 |
备注 |
KEY1 |
PortA |
Pin04 |
低电平触发 |
KEY2 |
PortA |
Pin05 |
低电平触发 |
KEY3 |
PortA |
Pin06 |
低电平触发 |
1.2 led对应电路图:
LED对应管脚 端口号:
按键 |
端口号 |
管脚 |
备注 |
LED1 |
PortD |
Pin02 |
输出模式 |
LED2 |
PortB |
Pin03 |
输出模式 |
LED3 |
PortB |
Pin04 |
输出模式(特殊脚需要处理) |
LED4 |
PortB |
Pin05 |
输出模式 |
2. 初始化GPIO
2.1 led 按键管脚定义
#define LED1_PORT PortD
#define LED1_Pin Pin02
#define LED2_PORT PortB
#define LED2_Pin Pin03
#define LED3_PORT PortB
#define LED3_Pin Pin04
#define LED4_PORT PortB
#define LED4_Pin Pin05
#define KEY1_PORT PortA
#define KEY1_Pin Pin04
#define KEY2_PORT PortA
#define KEY2_Pin Pin05
#define KEY3_PORT PortA
#define KEY3_Pin Pin06
#define ReadPort PortA
#define ReadPin Pin07
2.2 管脚配置
void User_Gpio_Init(void)
{
stc_port_init_t Port_CFG;
MEM_ZERO_STRUCT(Port_CFG);
Port_CFG.enPinMode = Pin_Mode_Out;
PORT_Init(LED1_PORT, LED1_Pin, &Port_CFG);
PORT_Init(LED2_PORT, LED2_Pin, &Port_CFG);
PORT_Init(LED3_PORT, LED3_Pin, &Port_CFG);
PORT_Init(LED4_PORT, LED4_Pin, &Port_CFG);
}
2.3 点亮 熄灭方法(led1为例):
PORT_SetBits(LED1_PORT,LED1_Pin);
PORT_ResetBits(LED1_PORT,LED1_Pin);
3. 中断配置
3.1 中断函数配置
stc_exint_config_t stcExtiConfig; /* 外部中断配置结构体 */
stc_irq_regi_conf_t stcIrqRegiConf; /*irq配置结构体 */
stc_port_init_t stcPortInit; /*管脚配置结构体 */
/* configuration structure initialization */
MEM_ZERO_STRUCT(stcExtiConfig);
MEM_ZERO_STRUCT(stcIrqRegiConf);
MEM_ZERO_STRUCT(stcPortInit);
/* Set PD06 as External Int Ch.6 input */
stcPortInit.enExInt = Enable;
PORT_Init(KEY1_PORT, KEY1_Pin, &stcPortInit);
PORT_Init(KEY2_PORT, KEY2_Pin, &stcPortInit);
PORT_Init(KEY3_PORT, KEY3_Pin, &stcPortInit);
stcExtiConfig.enExitCh = ExtiCh01;
/* 过滤器配置 */
stcExtiConfig.enFilterEn = Enable;
stcExtiConfig.enFltClk = Pclk3Div8;
/* 低电平触发(触发模式) */
stcExtiConfig.enExtiLvl = ExIntLowLevel;
EXINT_Init(&stcExtiConfig);
/* 选择外部中断通道 Ch.1 */
stcIrqRegiConf.enIntSrc = INT_PORT_EIRQ1;
/*注册外部中断 to Vect.No.000 */
stcIrqRegiConf.enIRQn = Int000_IRQn;
/* 绑定回调函数 */
stcIrqRegiConf.pfnCallback = &key_1_callback;
enIrqRegistration(&stcIrqRegiConf);
/* Clear Pending */
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
/* 配置优先级 */
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_15);
/* 使能 NVIC */
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
3.2 回调函数配置
自己定义了两个结构体测试用
typedef struct{
uint8_t key1:1;
uint8_t key2:1;
uint8_t key3:1;
uint8_t key4:1;
uint8_t key5:1;
uint8_t key6:1;
uint8_t key7:1;
uint8_t key8:1;
}Key_IO_bit_t;
typedef union{
Key_IO_bit_t keys;
uint8_t status;
}KEY_status_t;
回调函数:
static void key_1_callback(void){
static int i = 0;
KEY_status_t keyGroup = {0};
if(i == 65534){
i = 0;
}
if(Set == EXINT_IrqFlgGet(ExtiCh01)){
do{
keyGroup.keys.key1 = PORT_GetBit(KEY1_PORT, KEY1_Pin);
keyGroup.keys.key2 = PORT_GetBit(KEY2_PORT, KEY2_Pin);
keyGroup.keys.key3 = PORT_GetBit(KEY3_PORT, KEY3_Pin);
if(keyGroup.status != 7) break;
}while(1);
Ddl_Delay1ms(40);
if((keyGroup.keys.key1 == Reset) && (Reset == PORT_GetBit(KEY1_PORT, KEY1_Pin))){
if(i%2== 1){
PORT_ResetBits(LED1_PORT,LED1_Pin);
}else{
PORT_SetBits(LED1_PORT,LED1_Pin);
}
logDebug("key1Press! cnt:%d\n",i);
i++;
}else if((keyGroup.keys.key2 == Reset) && (Reset == PORT_GetBit(KEY2_PORT, KEY2_Pin))){
if(i%2== 1){
PORT_ResetBits(LED2_PORT,LED2_Pin);
}else{
PORT_SetBits(LED2_PORT,LED2_Pin);
}
logDebug("key2Press! cnt:%d\n",i);
i++;
}else if((keyGroup.keys.key3 == Reset) && (Reset == PORT_GetBit(KEY3_PORT, KEY3_Pin))){
if(i%2== 1){
PORT_ResetBits(LED3_PORT,LED3_Pin);
}else{
PORT_SetBits(LED3_PORT,LED3_Pin);
}
logDebug("key3Press! cnt:%d\n",i);
i++;
}
/* clear int request flag */
EXINT_IrqFlgClr(ExtiCh01);
}
}
剩下的就是编译,烧录测试!
备注:
关于部分io 比如swd下载的部分管脚默认上电以后是swd功能如果需要使用io功能则需要屏蔽对应的swd功能, 参考之前的帖子或者使用代码:
PORT_DebugPortSetting(TDO_SWO | TDI | TRST, Disable);
版权声明:本文为CSDN博主「smaller_maple」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u011624093/article/details/120132308
暂无评论