首先看硬件原理图
GPIO的C13和E0是两个按键,平时是高电平,当按键下去的时候就接地变成低电平。(所以中断是下降沿触发)
<随着经验的丰富 这个也并不准确 按键按下是下降沿 按键松开时上升沿 所以中断双触发都可以>
开始软件配置:
宏定义两个按键
(仔细看是有必要的,因为你看 GPIO_Pin_13和GPIO_PinSource13的排序是不同的)
#define TSKEY1GPIO GPIOC
#define TSKEY1GPIOPIN GPIO_Pin_13
#define TSKEY1IRQ EXTI15_10_IRQn
#define TSKEY1_ExtiPortsource GPIO_PortSourceGPIOC
#define TSKEY1_ExtiPin GPIO_PinSource13
#define TSKEY1_Line EXTI_Line13
#define TSKEY2GPIO GPIOE
#define TSKEY2GPIOPIN GPIO_Pin_0
#define TSKEY2IRQ EXTI0_IRQn
#define TSKEY2_ExtiPortsource GPIO_PortSourceGPIOE
#define TSKEY2_ExtiPin GPIO_PinSource0
#define TSKEY2_Line EXTI_Line0
初始化函数:
void TS_Key_init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC|RCC_APB2Periph_GPIOE| RCC_APB2Periph_AFIO,ENABLE ) ;
//RCC_APB2Periph_AFIO不能没有!!
GPIO_InitStructure.GPIO_Pin = TSKEY1GPIOPIN ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//MUST 如果是GPIO_Mode_IN_FLOATING则失败;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(TSKEY1GPIO, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TSKEY1IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
GPIO_EXTILineConfig(TSKEY1_ExtiPortsource, TSKEY1_ExtiPin);
EXTI_InitStructure.EXTI_Line = TSKEY1_Line;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
GPIO_InitStructure.GPIO_Pin = TSKEY2GPIOPIN ;
GPIO_Init(TSKEY2GPIO, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = TSKEY2IRQ;
NVIC_Init(&NVIC_InitStructure);
GPIO_EXTILineConfig(TSKEY2_ExtiPortsource, TSKEY2_ExtiPin);
EXTI_InitStructure.EXTI_Line = TSKEY2_Line;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling ;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}
现在就可以用中断了,到it.c去写服务程序吧。
int it=100;//Test
u8 EXit_Delay(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)//消抖 延时以后去读 如果还是低电平 那就是中断!
{
OSTimeDlyHMSM(0, 0, 0, 100);
if(GPIO_ReadInputDataBit(GPIOx,GPIO_Pin)==RESET)
return 1;
else
return 0;
}
这里主要是因为init的时候是下降沿是中断,所以去读,如果是0那就真的是中断。
void EXTI0_IRQHandler(void)
{
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL();
OSIntNesting++;
OS_EXIT_CRITICAL();
if(EXTI_GetITStatus(TSKEY2_Line) != RESET)
{
if( EXit_Delay(TSKEY2GPIO,TSKEY2GPIOPIN))
{
it+=10;
}
EXTI_ClearITPendingBit(TSKEY2_Line);
}
OSIntExit();
}
void EXTI15_10_IRQHandler(void)
{
OS_CPU_SR cpu_sr;
OS_ENTER_CRITICAL();
OSIntNesting++;
OS_EXIT_CRITICAL();
if(EXTI_GetITStatus(TSKEY1_Line) != RESET)
{
if( EXit_Delay(TSKEY1GPIO,TSKEY1GPIOPIN))
{
it-=5;
}
EXTI_ClearITPendingBit(TSKEY1_Line);
}
OSIntExit();
}
思考:
1对比文章:https://blog.csdn.net/tianshi_1988/article/details/52175434
为什么 GPIO_Mode_IPU成功 GPIO_Mode_IN_FLOATING失败;
回答:http://www.stmcu.org/module/forum/thread-616140-1-1.html
2复用不能丢
3消抖是软件写的,如果你是上升沿触发的话,那就是延时一会再去读,是高电平,1
++++++++++++++++++++++补充HAL库++++++++++++++++++++++++
HAL库写的话非常简单,无脑写。
上传工程。https://pan.baidu.com/s/1BDr4Z-0nOq8lgv5kW2-m9Q
按键下去,就是低电平,灯就翻转。(没有消抖 你 会理解的)
外接一个声控开关,3.3v+GND 连接,OUT连接到D9,有声音的时候就OUT出1,所以STM32是IN
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_Delay(100);
sound=HAL_GPIO_ReadPin(SOUNDIN_GPIO_Port, SOUNDIN_Pin);
key =!HAL_GPIO_ReadPin(KEY_GPIO_Port, KEY_Pin);
if(sound)
{
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
sound=0;
}
if(key)
{
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
key=0;
}
}
+++++++++20180626补充中断知识+++++++
视频 :http://www.moore8.com/courses/trainning_playback/1679
没想到NVIC中断也说了一节课。有必要的
https://blog.csdn.net/jdsnpgxj/article/details/54573855
STM32的NVIC:https://blog.csdn.net/ABAP_Brave/article/details/52457175