文章目录
- 一、原理
- 二、硬件
- 三、接口说明
- 四、源代码
- 五、中断配置
- 六、完整代码
一、原理
需要一个震动感应器来感应是否产生震动,然后把这个震动感应器作为GPIO输入,单片机来读取这个输入是否产生震动。如果产生震动,我们就可以把一个GPIO作为输出口,将它连接到一个灯上,然后输出高低电平。
后续根据情况再优化这个设计。
二、硬件
1、一个震动感应器
2、一个单片机
3、继电器
4、led灯
三、接口说明
我用的霸道的板子,这里我把PB6作为输入,PB7作为输出。
查找PB6、PB7挂载的总线:
四、源代码
bsp_ganying.h
#ifndef _BSP_GANYING_H
#define _BSP_GANYING_H#include "stm32f10x.h"void lightIn(void);
void lightOut(void);
#define GPIO_LIGHT_CLK RCC_APB2Periph_GPIOB
#define GPIO_IN_RORT GPIOB
#define GPIO_OUT_RORT GPIOB
#define GPIO_LIGHT_PIN_IN GPIO_Pin_6
#define GPIO_LIGHT_PIN_OUT GPIO_Pin_7#endif /*_BSP_GANYING_H*/
bsp_ganying.c
#include "bsp_ganying.h"void lightIn(void)
{GPIO_InitTypeDef gpioConfig_IN;RCC_APB2PeriphClockCmd(GPIO_LIGHT_CLK, ENABLE);gpioConfig_IN.GPIO_Pin = GPIO_LIGHT_PIN_IN;gpioConfig_IN.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIO_IN_RORT, &gpioConfig_IN);
}
void lightOut(void)
{GPIO_InitTypeDef gpioConfig_OUT;RCC_APB2PeriphClockCmd(GPIO_LIGHT_CLK,ENABLE);gpioConfig_OUT.GPIO_Pin = GPIO_LIGHT_PIN_OUT;gpioConfig_OUT.GPIO_Mode = GPIO_Mode_Out_PP;gpioConfig_OUT.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIO_OUT_RORT, &gpioConfig_OUT);
}
main.c
#include "bsp_ganying.h"
#include "stm32f10x.h"void delay(uint16_t nCount)
{uint16_t nTime = 0;while(nCount--){nTime= 12000;while(nTime--);}
}
int main(void)
{lightIn();lightOut();GPIO_SetBits(GPIO_OUT_RORT,GPIO_LIGHT_PIN_OUT);while(1){if(GPIO_ReadInputDataBit(GPIO_IN_RORT, GPIO_LIGHT_PIN_IN) == 0){GPIO_ResetBits(GPIO_OUT_RORT,GPIO_LIGHT_PIN_OUT);delay(1000);GPIO_SetBits(GPIO_OUT_RORT,GPIO_LIGHT_PIN_OUT);}else{GPIO_SetBits(GPIO_OUT_RORT,GPIO_LIGHT_PIN_OUT);}}
}
这样就能看到一个现象,我们下载到班子以后。当我们触碰这个震动感应器的时候,我们作为输出的GPIO口连接的灯,就会亮一秒,然后熄灭,我们继续触碰这个震动感应器,又会亮一秒。
但是这个程序是不是while有一大堆循环,比较消耗cpu,所以我们可以优化改为中断模式,在产生中断的时候进行输出。
五、中断配置
因为我们GPIOB使我们的输入也是我们的输出端口,所以我们配置外部中断的时候要选择复用端口。
因为之前说过,5-9共用一个EXTI,所以这里要注意一下。
bsp_exti.h
#ifndef _BSP_GANYING_H
#define _BSP_GANYING_H
#include "stm32f10x.h"
#include "bsp_ganying.h"#define GPIO_IN_RORT GPIOB
#define GPIO_LIGHT_CLK RCC_APB2Periph_GPIOB
#define GPIO_LIGHT_PIN_IN GPIO_Pin_6void extiConfig(void);#endif /*_BSP_GANYING_H*/
bsp_exti.c
#include "bsp_exti.h"
#include "bsp_ganying.h"void extiConfig()
{EXTI_InitTypeDef extiConfig;GPIO_InitTypeDef gpioConfig_IN;NVIC_InitTypeDef nvicConfig;RCC_APB2PeriphClockCmd(GPIO_LIGHT_CLK, ENABLE);//选择复用端口,因GPIOB是输入也是输出RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource6);//配置GPIO gpioConfig_IN.GPIO_Pin = GPIO_LIGHT_PIN_IN;gpioConfig_IN.GPIO_Mode = GPIO_Mode_IN_FLOATING;GPIO_Init(GPIO_IN_RORT, &gpioConfig_IN);//配置EXTIextiConfig.EXTI_Line = EXTI_Line6;extiConfig.EXTI_Mode = EXTI_Mode_Interrupt;extiConfig.EXTI_Trigger = EXTI_Trigger_Falling;extiConfig.EXTI_LineCmd = ENABLE;EXTI_Init(&extiConfig);//配置嵌套NVIC函数NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); //优先级组nvicConfig.NVIC_IRQChannel = EXTI9_5_IRQn; //配置中断源,共用5-9nvicConfig.NVIC_IRQChannelPreemptionPriority = 1;nvicConfig.NVIC_IRQChannelSubPriority = 1;nvicConfig.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&nvicConfig);
}
配置中断函数
void EXTI9_5_IRQHandler(void)
{/*确保是否产生了 EXTI Line0 中断*/if( EXTI_GetITStatus(EXTI_Line6) != RESET){GPIO_ResetBits(GPIO_OUT_RORT,GPIO_LIGHT_PIN_OUT);delay(1000);GPIO_SetBits(GPIO_OUT_RORT,GPIO_LIGHT_PIN_OUT);}/*清除中断标志*/EXTI_ClearITPendingBit(EXTI_Line6);
}
六、完整代码
链接:https://pan.baidu.com/s/1PIHp4xLzLwlMv4zkvLP_kA
提取码:e4lr
项目主要是让自己熟悉调库的步骤,中断的基本原理,和一些坑。