提示:朋友们需要源代码可以后台私信我哈,喜欢的话可以点赞收藏哦
一、项目需求
1. 医生按键按下,提示对应号码病人进入(其中屏幕显示号码)
2. 病人进去后,状态灯表示里面有人(其他人看屏幕排队等候)
3. 问诊结束后,医生按下按键提示下一位病人进入
4. 依次循环,确保问诊过程有序进行
二、硬件清单
1. 按键
2. 蜂鸣器
3. stm32f103c8t6芯片
4. OLED显示屏
5. 两个对射式红外线传感器
6. LED红灯和LED绿灯各一个(这里也可以用双色灯)
7. 一个面包板和若干杜邦线
三、项目流程
1.项目框图
2.功能实现
该项目实现的功能是定时器扫描按键按下,绿灯变亮,OLED屏幕显示号码加一,然后蜂鸣器响两下提示病人进入。当两个对射式传感器判断出病人进入时,红灯亮绿灯灭表示里面有人。依次反复,直到下班。。。
四、程序代码
按键模块代码:
#include "stm32f10x.h" // Device header
#include "Delay.h"
unsigned char KeyKit;
/**
函 数:按键初始化
参 数:无
返回值:无
**/
void Key_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE); //开启GPIOB的时钟
GPIO_InitTypeDef GPIO_InitStructure; //GPIO结构体初始化
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置输入模式为上拉输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
/**
函 数:按键驱动函数,在中断中调用
参 数:无
返回值:无
**/
void Key_Loop(void)
{
static unsigned char NowState,LastState;
LastState = NowState; //更新按键状态
NowState = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1); //读取当前按键状态
//如果上个时间点按键按下,这个时间点未按下,则是松手瞬间,以此避免消抖和松手检测
if(LastState == 0 && NowState == 1)
{
KeyKit = 1; //如果按键按下置标志位
}
}
/**
函 数:获取当前按键状态
参 数:无
返回值:返回按键驱动函数所置标志位
**/
uint8_t Key(void)
{
unsigned char Temp=0;
Temp=KeyKit;
KeyKit = 0;
return Temp;
}
//如果想直接用延时来做,可以参考以下代码
//uint8_t Key_GetNum(void)
//{
// uint8_t KeyNum = 0;
// if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0)
// {
// Delay_ms(20);
// while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_1) == 0);
// Delay_ms(20);
// KeyNum = 1;
// }
//
// return KeyNum;
//}
定时器模块代码:
#include "stm32f10x.h" // Device header
#include "Key.h"
#include "Delay.h"
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); //开启TIM2的时钟
TIM_InternalClockConfig(TIM2); //选择内部时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
//这里根据公式 溢出 = 72MHZ/(PSC+1)/(ARR+1)配置定时中断为20ms
TIM_TimeBaseInitStructure.TIM_Period = 1000 - 1; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 1440 -1; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除定时器更新标志位,避免刚上电就进入中断加一
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //开开启TIM2的更新中断
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC为分组2
/*NVIC配置*/
NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //选择配置NVIC的TIM2线
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //指定NVIC线路的抢占优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE); //使能定时器
对射式红外线传感器模块代码:
#include "stm32f10x.h" // Device header
uint8_t Entering = 0,Entered = 0;
void Enter_Init(void)
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); //开启GPIOB和AFIO的时钟
GPIO_InitTypeDef GPIO_InitStructure; //配置两个GPIO口
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 ;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 ;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource11); //将外部中断的PB11号线映射到GPIOB,即选择PB11为外部中断引脚
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0); //将外部中断的PB0号线映射到GPIOB,即选择PB0为外部中断引脚
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_InitStructure.EXTI_Line = EXTI_Line11 ; // 使用 EXTI 11
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发中断
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line0;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_Init(&EXTI_InitStructure);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
}
/**
函 数:EXTI15_10外部中断函数
参 数:无
返 回 值:无
**/
void EXTI15_10_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line11) == SET) //判断是否是外部中断11号线触发的中断
{
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11) == 0) //为防止出现计数不准,这里继续判断电平状态
{
Entering = 1; //置标志位1,说明有人通过了第一个传感器
} //只有依次通过两个传感器才是进入
EXTI_ClearITPendingBit(EXTI_Line11); //清除中断标志位
}
}
/**
函 数:EXTI0外部中断函数
参 数:无
返 回 值:无
**/
void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) == SET) //判断是否是外部中断11号线触发的中断
{
if ((GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) == 0) && (Entering == 1)) //先触发第一个传感器再触发第二个传感器才能执行操作,里面的人出来是不执行操作的
{
Entered = 1; //当这个标志位置1时就表示有人进来了
}
EXTI_ClearITPendingBit(EXTI_Line0); //清除中断标志位
}
}
main函数模块代码:
#include "stm32f10x.h" // Device header
#include "Delay.h"
#include "Key.h"
#include "Timer.h"
#include "Buzzer.h"
#include "Light.h"
#include "OLED.h"
#include "Enter.h"
int main(void)
{
Buzzer_init();
Key_Init();
Light_init();
Timer_Init();
OLED_Init();
Enter_Init();
uint8_t KeyNum = 0;
uint8_t Num = 0;
OLED_ShowString(1, 1, "Number:");
while(1)
{
OLED_ShowNum(1, 8, Num, 3); //在OLED屏上显示号码
KeyNum = Key(); //获取按键信息,按键按下执行以下操作
if(KeyNum == 1)
{
GreenLight_ON();
Buzzer_ON();
Num++;
}
if(Entered == 1) //判断有人进入执行以下操作
{
RedLight_ON();
Entering = 0;
Entered = 0;
}
}
}
/**
函 数:定时器中断函数
参 数:无
返回值:无
**/
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET) //读取定时中断标志位为1
{
Key_Loop(); //不断执行该函数获取按键状态
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除标志位
}
}
注意:剩下的就是一些LED模块蜂鸣器模块的配置了,博主相信各位是完全能够搞定的哈。其中配置的时候要注意GPIO口输出输入的正确配置哦,还有就是OLED屏幕的配置不会的可以去网上查找资料学习一下哈,我这里一时半会也说不清哈哈。
该项目主要是记录一下个人的一个学习过程,项目比较简单,欢迎同学们在评论区交流学习,一起进步,欧里给!!!