基于STM32楼梯层控制系统

news2025/1/11 23:57:08

1、项目需求分析

项目目标意义:
随着社会的发展、 科技的进步以及人们生活水平的逐步提高, 各种方便于生活的遥控系统开始进入了人们的生活。 电梯的发展是由于需要从山坡上运输包括煤和材在内的原材料而引发的,而到了今日,电梯的已经遍布于各种写字楼,住宅,工厂,医院等。其操作简单。使用者坐好后按下按钮即可运作,到达自己想到的楼层后松开按钮即可停止; 舒适安全。楼道电梯可以让使用者在坐着的状态下到达高楼层。楼道电梯上有安全带,使用者可以系上安全带确保安全。如果楼道电梯在运行时遇上障碍物的话,便会自动停止运行。除此之外,楼道电梯在停电时仍可运行10个往返,使用者无需担心突然停电的风险。占地面积小。楼道电梯有可折叠的设计,根据款式楼道电梯折叠后离墙距离为28-44cm不等,展开后离墙距离53-66cm不等。

功能需求分析:
本项目主要应用了STM32F103R6单片机作为核心,综合应用了STM32中断系统、定时器、计数器等知识,用按键控制楼梯的上下走向,用四位的共阴极的数码管来显示楼梯层层数和变化。
系统开发环境需求分析:
本项目主要应用kell5来编写代码,proteus设计仿真图,来模拟功能的实现。

非功能性需求分析(成本、社会意义、使用便利性能):
用软件仿真实现简单的楼梯层控制系统,.使用4位显示屏来显示要进行的操作(上,下,停止),电梯楼层使用人在某个楼层按下电梯号,电梯进行上下移动每一层可以选择上或者下。实现简单的电梯控制。

2、项目硬件系统设计

2.1、 系统方案原理图

Proteus仿真图:
在这里插入图片描述

如图所示,使用的芯片为STM32F103R6,PA0-PA7引脚接7SEG-MPX4-CA七段数码管的ABCDEFG和DP,2SC1162通用型高频中功率三极管连接了PB0到PB3引脚、直流发电机和七段数码管的1234,PA8到PA14连接图中左边的电梯运行状态显示LED。当开始运行时,电梯停在1层,状态为停止。当点击右侧2楼上按钮时,电梯先把停止状态改为上升状态,同时左侧的D2(2上)的LED状态灯点亮,之后再改变楼层数,到达二层后先点亮开门的LED灯,开门LED指示灯熄灭后再把电梯状态由上升改为停止。

在这里插入图片描述

当开始运行时,电梯停在1层,状态为停止。当点击右侧3楼下按钮时,电梯先把停止状态改为上升状态,同时左侧的D4(下)的LED状态灯点亮,之后再改变楼层数,到达三层后先点亮开门的LED灯,开门LED指示灯熄灭后再把电梯状态由上升改为停止。

2.2、STM32F10X原理介绍
1)内核架构–CM3内核架构:
在这里插入图片描述

STM32F103是一个ARM单片机,内嵌有一个Cortex-M3(简称CM3)处理器作为核心。
CM3的三条总线通过总线矩阵与STM32F103主要部件及外设相连。
STM32F103的架构包括CM3的内核架构和除内核以外的其他架构。
2)DMA(Direct Memory Access,直接存储器访问):早期用来提供高速外设和存储器之间或者存储器和存储器之间的高速数据传输的一种技术。(不需执行指令,硬件控制传输)
因此DMA可以在高速数据采集,数据移动和周期性数据处理等方面有效地降低CPU负荷,使系统运行更加高效。STM32 系列MCP的外设(不管高速、中低速都提供了DMA数据传输方式)
3)GPIO:(General Purpose Input Output,通用输入输出接口)是MCU与外部电路和设备连接的基本外设。也就是常说的端口或管脚。
GPIO8种工作方式,可由软件配置:
1、浮空输入:上下拉电阻断开,用于不确定高低电平的输入。(复位后处于此状态
2、上拉输入:上拉电阻接通,默认高电平输入。
3、下拉输入:下拉电阻接通,默认低电平输入。
4、模拟输入:施密特触发器截止,模拟量输入常用于AD转换
5、开漏输出:上部MOS管不工作,只能输出低电平,不能输出高电平。如果要输出高电平则需要外接上拉。用于实现电平转换和线与功能的输出。
6、推挽式输出:上下MOS管交替导通,用于较大功率驱动的输出。
7、推挽式复用输出功能:复用功能情况下的推挽输出。
8、开漏复用输出功能:复用功能情况下的开漏输出。
4)重映射:STM32F103有80个GPIO端口,其中的一些还可以把复用功能重新映射到其他引脚,以实现优化管脚数目和配置目的。(重映射是系统做好的,不能随便映射)
5)NVIC中断控制器:(Nested Vectored Interrupt Controller,NVIC)位于CM3内核,是中断系统硬件设施,用来管理和配置中断。
NVIV的功能:(硬件+控制寄存器组成)
1、管理中断源2、保存中断申请信号3、优先级判断,中断嵌套4、屏蔽中断5、中断优先级设置
6)EXTI控制器:主要用来管理片外引脚中断 和事件控制。
EXTI控制器是片上外设,可以管理 16路外部引脚中断 和 4路事件 的控制, 共20 路输入。
EXTI --外部中断/事件线路映像:
80个通用I/O端口:均可做外部中断或事件输入线,连接到16个外部中断/事件线上。使用时,须设置AFIO功能,并使能其时钟。(可以是中断也可以是事件)
四个专用的线: 1、EXTI线16连接到PVD输出(中断)。 2、EXTI线17连接到RTC闹钟事件。 3、EXTI线18连接到USB唤醒事件。 4、EXTI线19连接到以太网唤醒事件
注释:PVD(可编程电压监控器),可管理上电复位和掉电中断

2.3、 LED灯模块原理
由于该设计时一个模拟电梯控制系统的开门关门状态难以直接描述,故用LED灯的亮和灭两张状态来表示门的开于关。同时每一个按键分别用一个小灯来指示按键是否按下,使得电梯运行过程中乘客更清楚了解电梯运行状态。本系统共有7个LED灯,正极接电源,负极接stm32的GPIO引脚。其中一个LED用用来表示开门关门的状态,灯亮时为开门。其余六个灯用来表示电梯要进行的操作,如2楼上等。当系统查询到由按键被按下时
系统立刻使stm32相应GPIO口为低电平,点亮相应小灯。系统保持LED灯的状态直到电梯完成相应的操作。
在这里插入图片描述

2.4、按键模块原理
按键由一组独立按键构成,由于弹性按键结构简单,价格低廉,故选用弹性按键。同时,每个按键单独连接芯片的对应引脚,简化了电路的设计。本设计共有12个独立的弹性小键来控制电梯升降,其均与相对应的GPIO口直接相连。所有GPIO口设置为上拉输入电平触发方式。一旦小键按下,相应的引脚与地接通成低电平,当程序进入按键查询时为低电平,表示键被按下,按键弹起后为高电平。系统根据小灯的状态立即或等待执行相应的操作。
在这里插入图片描述

2.5、数码管模块原理
数码管功耗虽然比液晶显示器大而且显示09及AF,但其驱动电路简单,使用方法简单且价格便宜。本设计电梯只有四层,因此只需要显示电梯层数再1到4。综合考虑数码管比较合适。无论几位的数码管,其原理均为点亮内部的二极管来发亮。故当需要显示数字0到9时,首先对其进行编码,当要显示的某个数字式像数码管送入相应的编码即可显示该数字。

在这里插入图片描述

3、系统软件体系设计

3.1 项目软件系统总架构图

***见文档 ***
电梯在运行中,先判断是否需要电梯,需要时判断电梯运行方向,接着判断当前是否为目标楼层,目标楼层时停下开门,不是时看上方时候需要电梯,需要时上移,不需要时反向、
程序先进行按键的定义和初始化,按键也就是某层楼梯控制信号发出的定义,信号接收定义在PC0到PC11引脚,信号输出定义在PC0到PC14引脚,设置中断函数,判断程序是否需要改变楼梯层状态和开门关门状态。
然后进行进行GPIO的初始化,即7SEG-MPX4-CA接芯片的PA0PA7和PB0PB3,PA8~PA14接指示灯,初始化状态:指示灯不亮,继电器不闭合。

3.2 重要子模块流程图

如果开始时电梯在第二层,那么电梯由两种运行状态,即上行和下行,系统会通过if语句先行判断是否由下行要求,即if是否查询到LED_2(2上)==0||LED_3(2下)0;如是系统会下行。否则,系统会通过if语句再次判断是否由下行要求,即if查询到的LED_4(3上).0||LED_5(3下)==0,若是系统则上行。

3.3 重要的数据结构、参数和函数分析
3.3.1 KEY_Init
设置STM32的GPIO口为输入模式时,通过读取IO口状态,判断是否有按键按下。为避免干扰产生一些误操作,在检测到电平变化后延时一段时间,再重新读取IO口状态。
代码如下:


void KEY_Init(void)
	// 在使用I/O前,首先 开时钟->设置I/O工作模式
	RCC->APB2ENR |= (1 << 4); //开时钟
	// 上拉输入:区别在于没有输入信号的时候默认输入高电平(因为有弱上拉)
	// 下拉输入:区别在于没有输入信号的时候默认输入低电平(因为有弱下拉)
	//  对于上下拉输入,在设置I/O模式位 1000 
	//                  还应设置上拉下拉类型 GPIOx->ODR相应位
	// 浮空输入:输入什么信号才是什么信号,对于浮空输入要保证有明确的输入信号
	
	//开GPIOC时钟
	RCC->APB2ENR |= (1 << 4);
	GPIOC->CRL &=0x00000000; // 
	GPIOC->CRL |=0x11111111; // 设置C组I/O 0-9 为0011 最大速度通用推挽输出
	GPIOC->CRH &=0x00000000; 
	GPIOC->CRH |=0x00001111; //上拉
	GPIOC->ODR |=0xFFFFFFFF ;
	/*
	// PC9
	GPIOC->CRH&=0XFFFFFF0F;      
  GPIOC->CRH|=0X00000080;  
	GPIOC->ODR|=1<<9;           // 上
	// PC8
	GPIOC->CRH&=0XFFFFFFF0;      
  GPIOC->CRH|=0X00000008;  
	GPIOC->ODR|=1<<8;           // 上
	// PC7
	GPIOC->CRL &=0x0FFFFFFF;//清空
	GPIOC->CRL |= 0X80000000;//上/下拉输入
	GPIOC->ODR|=1<<7; 
	// PC6
	GPIOC->CRL &=0xF0FFFFFF;//清空
	GPIOC->CRL |= 0X08000000;//上/下拉输入
	GPIOC->ODR|=1<<6;           // 上
	// PC5
	GPIOC->CRL &=0xFF0FFFFF;//清空
	GPIOC->CRL |= 0X00800000;;//上/下拉输入
	GPIOC->ODR|=1<<5;            // 上
	// PC4
	GPIOC->CRL &=0xFFF0FFFF;//清空
	GPIOC->CRL |= (0x8 << 4 * 4);//上/下拉输入
	GPIOC->ODR|=1<<4; 
	// PC3
	GPIOC->CRL &=0xFFFF0FFF;//清空
	GPIOC->CRL |= (0x8 << 4 * 3);//上/下拉输入
  GPIOC->ODR|=1<<3;  
	// PC2
	GPIOC->CRL &=0xFFFFF0FF;//清空
	GPIOC->CRL |= (0x8 << 4 * 2);//上/下拉输入
  GPIOC->ODR|=1<<2;  
	// PC1
	GPIOC->CRL &=0xFFFFFF0F;//清空
	GPIOC->CRL |= (0x8 << 4 * 1);//上/下拉输入
  GPIOC->ODR|=1<<1;  
	// PC0
	GPIOC->CRL &=0xFFFFFFF0;//清空
	GPIOC->CRL |= (0x8 << 4 * 0);//上/下拉输入
  GPIOC->ODR|=1<<0;  
	*/
} 

3.3.2 NVIC
向量中断控制器(NVIC)与Cortex-M3内核的逻辑紧密耦合、相互交融,共同完成对中断的控制。STM32有两个优先级概念—抢占式优先级和响应优先级,响应优先级又被称为亚优先级或副优先级,STM32的每个中断源都需要指定这两种优先级。


//Ex_NVIC_Config专用定义
#define GPIO_A 0
#define GPIO_B 1
#define GPIO_C 2
#define GPIO_D 3
#define GPIO_E 4
#define GPIO_F 5
#define GPIO_G 6 
#define FTIR   1  //下降沿触发
#define RTIR   2  //上升沿触发
								   
//JTAG模式设置定义
#define JTAG_SWD_DISABLE   0X02
#define SWD_ENABLE         0X01
#define JTAG_SWD_ENABLE    0X00	
/  
void Stm32_Clock_Init(u8 PLL);  //时钟初始化  
void Sys_Soft_Reset(void);      //系统软复位
void Sys_Standby(void);         //待机模式 	
void MY_NVIC_SetVectorTable(u32 NVIC_VectTab, u32 Offset);//设置偏移地址
void MY_NVIC_PriorityGroupConfig(u8 NVIC_Group);//设置NVIC分组
void MY_NVIC_Init(u8 NVIC_PreemptionPriority,u8 NVIC_SubPriority,u8 NVIC_Channel,u8 NVIC_Group);//设置中断
void Ex_NVIC_Config(u8 GPIOx,u8 BITx,u8 TRIM);//外部中断配置函数(只对GPIOA~G)
void JTAG_Set(u8 mode);
//
//以下为汇编函数
void WFI_SET(void);		//执行WFI指令
void INTX_DISABLE(void);//关闭所有中断
void INTX_ENABLE(void);	//开启所有中断
void MSR_MSP(u32 addr);	//设置堆栈地址
#endif

4、项目运行效果展示
程序运行初态(没有按键按下):显示屏显示2 1,指示灯不亮。
按下2上按键,
显示屏:1 1(表示电梯当前再1层,状态为上升)
指示灯: 2上指示灯点亮

显示屏:1 2(表示电梯当前再2层,状态为上升)
指示灯:开门指示灯点亮,开门指示灯灭

显示屏:2 2(表示电梯当前再2层,状态为停止)
指示灯:2上指示灯灭

其余按键同理

5、总结与心得体会
总结:通过基于STM32芯片,七段数码管,三极管等原件,用proteus模拟仿真了电梯的升降,实现了用按键实现电梯的楼梯层控制的操作。
心得体会:在知识方面,学习到了楼梯层控制和7SEG-MPX4-CA七段数码管的一点浅显知识,加深了接口这门课程所学习到的芯片内核结构、GPIO、中断等知识,充分的练习了单片机c语言的编程规则,也对一些基本的数理逻辑问题和事理逻辑问题有了更深入的体会。但这次课程设计对于我来说最重要的是,让我明白了理论与实际动手的差距。我以为之前做了很多的练习,现在做起来应该很容易,在整个过程中还是遇到了许多问题,虽然整个过程很累,感受到了在遇到问题时的无助和绝望,但当自己通过各种方法把问题一件件的解决后,那种快乐是无以言表的。让我明白也学会了,知识要动手实践才能真正的转换为自己的。
局限性:当短时间内先后按下按键时,本系统以最后一次按下的楼梯层为准,无法实现多楼梯层同时需要电梯时的情景。

6、附录


#include "main.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "timer.h"

 char flag1;		//定时时间到标志
 u8 counter;		//计数器
u8 state;		//当前电梯状态
u8 statepre;	//之前电梯状态
u8 flag;		//电梯上下标志,0下,1上
u8  i;
char in1=0, in2=0, in3=0, in4=0, up1=0, up2=0, up3=0, down2=0, down3=0, down4=0;	//KEY
u8 table[]={0xf9, 0xa4,0xb0,0x99,  0xa1, 0xc1, 0xff};        //楼层显示码表,一共是四层
void keyscan(void);
void elvator(void);

void display()
	{
	GPIOB->ODR &=0xFFFFFFF0 ;
	set_DigitalNum(state);  //楼乘标号	
	GPIOB->ODR |=0x00000002 ;
  Delay_ms(2);
		
	GPIOB->ODR &=0xFFFFFFF0 ;	
  set_DigitalNum(flag);
  GPIOB->ODR |=0x00000008 ;
  Delay_ms(2);
}
void iniclock()      //start clock
{
TIM3->CR1|=0x01; 
}	
void run()
{
	for(i=0;i<50;i++)//100ms
	{
			keyscan();
			display();
	}
}
int main()
{
//NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2	
	Delay_Init(); // 延时程序初始化
	Led_Init();   // LED灯初始化
	MultDigitalNum_Init(); // 数码管初始化
	KEY_Init();            // 按键初始化
//TIM3_Int_Init(499,7199);//50ms进入一次中断
	
   	state=1;
		statepre=1;
		flag=1;//上
		flag1=0;
	while(1)
	 {
		 elvator();
	}
}

void keyscan(void)
{
//内一按下动作	
	if(!(GPIOC->IDR & (1 << 0)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 0)))
		{
			in1=1;			//被按下后标记,亮灯,下同
			while(!(GPIOC->IDR & (1 << 0)));
		}
	}
//内二按下动作		
	if(!(GPIOC->IDR & (1 << 1)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 1)))
		{
			in2=1;			//被按下后标记,亮灯,下同
			while(!(GPIOC->IDR & (1 << 1)));
		}
	}	
//内三按下动作		
	if(!(GPIOC->IDR & (1 << 2)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 2)))
		{
			in3=1;			//被按下后标记,亮灯,下同
			while(!(GPIOC->IDR & (1 << 2)));
		}
	}	
//内四按下动作	
	if(!(GPIOC->IDR & (1 << 3)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 3)))
		{
			in4=1;			//被按下后标记,亮灯,下同
			while(!(GPIOC->IDR & (1 << 3)));

		}
	}	
//1上按下动作	
	if(!(GPIOC->IDR & (1 << 4)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 4)))
		{	
			   up1=1;
				lup1(1);
			while(!(GPIOC->IDR & (1 << 4)));
		}
	}
//2上按下动作	
	if(!(GPIOC->IDR & (1 << 5)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 5)))
		{
			up2=1;
			lup2(1);
			while(!(GPIOC->IDR & (1 << 5)));
		}
	}		
//3上按下动作	
	if(!(GPIOC->IDR & (1 << 6)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 6)))
		{
			up3=1;
			lup3(1);
			
			while(!(GPIOC->IDR & (1 << 6)));
		}
	}	
//2下按下动作	
	if(!(GPIOC->IDR & (1 << 7)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 7)))
		{
		     down2=1;
				ldown2(1);
			while(!(GPIOC->IDR & (1 << 7)));
		}
	}		
//3下按下动作	
	if(!(GPIOC->IDR & (1 << 8)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 8)))
		{
				
		     down3=1;
				ldown3(1);
			
			while(!(GPIOC->IDR & (1 << 8)));

		}
	}			
	
//4下按下动作	
	if(!(GPIOC->IDR & (1 << 9)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 9)))
		{
		     down4=1;
				ldown4(1);
			while(!(GPIOC->IDR & (1 << 9)));
		}
	}		
//4下按下动作	
	if(!(GPIOC->IDR & (1 << 10)))
	{
		Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 10)))
		{	   lopen(1);
			while(!(GPIOC->IDR & (1 << 10)));
		}
	}		
//4下按下动作	
	if(!(GPIOC->IDR & (1 << 11)))
	{	Delay_ms(1); //消抖
		if(!(GPIOC->IDR & (1 << 11)))
		{
	   lopen(0);
			while(!(GPIOC->IDR & (1 << 11)));}}		}
//电梯执行程序	
void elvator(void)
{
switch(state){				//扫描电梯所在位置
				case(1):{

					if(state!=statepre){	//上次的状态和本次不一样说明电梯 需要开门
						lopen(1);
						run();			//按键扫描三秒钟
						lopen(0);
						in1=0;		//如果in1和up1被按下则无效
						up1=0;
						lup1(0);
					}
                    else{
                        if(up1){
                                up1=0;
                                lup1(0);
                                lopen(1);
                                run();
                                lopen(0);
                                }
                         }
                      in1=0;     
					if(up2|down2|up3|down3|down4|in2|in3|in4){
						flag=1;			//说明上行
						run();				//按键扫描三秒钟
						state=2;			//更新状态
						statepre=1;
					}
					else{
						statepre=state;
           flag=2;
						keyscan();
						display();
					}
					break;
				}
				case(2):{					  //电梯到2楼
					if(state!=statepre)
                    {                          //如果前后两次状态不一样则可能需要开门
                     	if(!(
							((flag==1)&&(in3|up3|down3)&&(~up2)&&(~in2))		   //去三楼
							||((flag==1)&&(in4|down4)&&(~up2)&&(~in2))		  
//去四楼
                            ||((flag==0)&&(in1||up1)&&(~down2)&&(~in2))		   
//去一楼
                            )
                          )
                           {			
								lopen(1);
								run();				//按键扫描三秒钟
								lopen(0);
								in2=0;				//如果in2被按下则无效
								if(flag==1){			//如果上行,电梯外上行指示灯按下无效
								up2=0;
								lup2(0);
								}
								else{				//如果下行,电梯外下行指示灯按下无效
								down2=0;
								ldown2(0);
								}
                         	}
					}
                                        else{									//在二楼停
                                        	if(down2|up2){
                                                	down2=0;
                                                        up2=0;
                                                        lopen(0);
                                                        run();
                                                        lopen(0);
                                                        ldown2(0);
                                                        lup2(0);
                                                	}
                                        	}
                                        in2=0;
                                       
                                        if(flag)
                                        	up2=0;
                                        else
                                        	down2=0;
					if(flag==1){
						if(down3|in3|up3|down4|in4){
							flag=1;
							run();
							state=3;
							statepre=2;
						}
						else if(in1|up1){
							flag=0;
							run();
							state=1;
							statepre=2;
						 }
						 else{
						 	statepre=state;
                                                        flag=2;
						 	keyscan();
						 	display();
						 }
					}
					else {
						if(up1|in1){
							flag=0;
							run();
							state=1;
							statepre=2;
						}
						else if(in3|down3|up3|in4|down4){
							flag=1;
							run();
							state=3;
							statepre=2;
						}
						else{

							statepre=state;
            flag=2;
							keyscan();
							display();
						}
					}
					break;
				}
				case(3):{				//电梯到3楼
	
					if(state!=statepre)
                    {                          //如果前后两次状态不一样则可能需要开门
                     	if(!(
							((flag==0)&&(in2|up2|down2)&&(~up3)&&(~in3))		   //去二楼
							||((flag==1)&&(in4|down4)&&(~up3)&&(~in3))		   //去四楼
                            ||((flag==0)&&(in1||up1)&&(~down3)&&(~in2))		   //去一楼
                            )
                          )
                           {			
								lopen(0);
								run();				//按键扫描三秒钟
								lopen(0);
								in3=0;				//如果in3被按下则无效
						
								if(flag==1){			//如果上行,电梯外上行指示灯按下无效
								up3=0;
								lup3(0);
								}
								else{				//如果下行,电梯外下行指示灯按下无效
								down3=0;
								ldown2(0);
								}
                         	}
					}
                                        else{									//在三楼停
                                        	if(down3|up3){
                                                	down3=0;
                                                        up3=0;
                                                        lopen(1);
                                                        run();
                                                        lopen(0);
                                                        ldown3(0);
                                                        lup3(0);
                                                	}
                                        	}
                                        in3=0;
                                       
                                        if(flag)
                                        	up3=0;
                                        else
                                        	down3=0;
					if(flag==1){
						if(down4|in4){
							flag=1;
							run();
							state=4;
							statepre=3;
						}
						else if(in1|up1|in2|up2|down2){
							flag=0;
							run();
							state=2;
							statepre=3;
						 }
						 else{
						 	statepre=state;
                                                        flag=2;
						 	keyscan();
						 	display();
						 }
					}
					else {
						if(up1|in1|up2|in2|down2){
							flag=0;
							run();
							state=2;
							statepre=3;
						}
						else if(in4|down4){
							flag=1;
							run();
							state=4;
							statepre=3;
						}
						else{

							statepre=state;
                                                        flag=2;
							keyscan();
							display();
						}
					}
					break;
				}
				case(4):{					//case4和case1类似
					keyscan();
					display();
					if(state!=statepre){
						lopen(1);
						run();
						lopen(0);
						in4=0;				//如果in4和down4被按下则无效
					
						down4=0;
						ldown4(0);
					}
           else{
       	if(down4){
										 down4=0;
										 ldown4(0);
										 lopen(1);
										 run();
										 lopen(0);
                }
              }
           in4=0;
                                      
					if(in1|up1|up2|down2|in2|in3|up3|down3){
						flag=0;				//说明下行
						run();
						state=3;			//更新状态
						statepre=4;
					}
					else{
						statepre=state;
              flag=2;
						keyscan();
						display();
					}
					break;
				}
				default: break;
			}
}

需要仿真图和keil源代码以及课设报告私聊我获取

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/146051.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript 注释

文章目录JavaScript 注释JavaScript 注释JavaScript 多行注释使用注释来阻止执行在行末使用注释JavaScript 注释 JavaScript 注释可用于提高代码的可读性。 JavaScript 注释 JavaScript 不会执行注释。 我们可以添加注释来对 JavaScript 进行解释&#xff0c;或者提高代码的可…

ArcGIS基础实验操作100例--实验59二维面转体模型

本实验专栏参考自汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a;请访问实验1&#xff08;传送门&#xff09; 高级编辑篇--实验59 二维面转体模型 目录 一、实验背景 二、实验数据 三、实验步骤 &#xff08;1&am…

PyTorch简易安装方法(100%成功)

PyTorch简易安装方法&#xff08;100%成功&#xff09; 一般我们习惯用pip install xxx&#xff0c;同时使用清华源用来加速&#xff0c;这种方法安装99%的库都没啥大问题&#xff0c;但是有时候安装pytorch的时候就会发现问题。笔者反正每次用该方法安装torch总会遇到刚开始下…

活动星投票争做新时代好少年网络评选

“争做新时代好少年”网络评选投票_图文投票的便利_免费小程序广泛应用手机互联网给所有人都带来不同程度的便利&#xff0c;而微信已经成为国民的系统级别的应用。现在很多人都会在微信群或朋友圈里转发投票&#xff0c;对于运营及推广来说找一个合适的投票小程序能够提高工作…

【模拟CMOS集成电路】电路噪声——基本电路噪声性能(2)

【笔记&#xff1a;模拟CMOS集成电路】电路噪声——基本电路噪声性能&#xff08;2&#xff09;前言1 噪声——分析基础2 噪声——基本电路噪声性能2.1 MOS管噪声模型(1)电阻RG热噪声和沟道热噪声(2)衬底电阻热噪声(3)源极寄生电阻RS热噪声2.2常见组态的单级放大器噪声分析2.2.…

C++11基于范围的for循环vector容器扩容详解迭代器失效

目录 C11基于范围for循环 vector容器扩容详解 迭代器失效 总结 C11基于范围for循环 对于一个有范围的集合来说&#xff0c;在程序代码中指定循环的范围有时候是多余的&#xff0c;还可能犯错误。 为此C11中引入了基于范围的for循环。 语法&#xff1a; 语法&#xff1a;…

一加11:新的赛场,“不温和”的答卷

《不要温和地走进那个良夜》是英国诗人狄兰托马斯创作于20世纪中期的一首享誉世界的诗歌&#xff0c;作者所表达出的在逆境中坚韧不屈、逆流而上的精神&#xff0c;激励了一代又一代人。1月4日&#xff0c;一加11发布会现场&#xff0c;一加中国区总裁李杰Louis借鉴了狄兰托马斯…

联合证券|近90亿大资金“跑步入场”,光伏板块掀涨停潮

早盘光伏板块掀起涨停潮&#xff0c;原因或是这些。 国产特斯拉全线降价 1月6日&#xff0c;据特斯拉我国官网&#xff0c;特斯拉国产车型大幅降价&#xff0c;对国产Model 3后驱版、高性能版&#xff0c;及Model Y后驱版、长续航版、高性能版等五款车型进行调价。Model 3起价…

DFMN 代码解读

目录 0. 环境配置 1. 运行程序 2. 读代码的思路 1&#xff09;model.py !! 关于继承 !! 关于网络结构组织 !! 关于 forward 2) 数据预处理 3&#xff09;train.py 0. 环境配置 很简单&#xff0c;提示缺包xxx&#xff0c;pip install xxx 就可以了 1. 运行程序 从…

NuxtJS服务器端入门

一、搜索引擎优化 1、什么是SEO 总结&#xff1a;seo是网站为了提高自已的网站排名&#xff0c;获得更多的流量&#xff0c;对网站的结构及内容进行调整和优化&#xff0c;以便搜索引擎 &#xff08;百度&#xff0c;google等&#xff09;更好抓取到优质网站的内容&#xff0c…

GCN图神经网络和LSTM的介绍和使用场景 中英文

GCN-LSTM 可以学习参考 英文内容部分源自youtube的教学视频 自己跟着英文敲的 给定一辆出租车行驶时在某个时间段的速度&#xff0c;下一个时刻速度会是多少&#xff1f;这是一个时间序列回归预测问题。获得了若干时间点的速度&#xff0c;目标是预测出租车速度序列中的下一个…

线性模型:AR、MA、ARMA、ARMAX、ARX、ARARMAX、OE、BJ等

目录 1 AR 1 2 MA 1 3 ARMA 1 4 ARMAX 2 5 ARX 2 6 ARARX 3 7 ARARMAX 3 8 OE 3 9 BJ 3 各种线性模型&#xff0c;这些模型算数学基础模型&#xff0c;不仅在计量经济学&#xff0c;也在工业控制等各领域有应用。包括AR、MA、ARMA、ARMAX、ARX、ARARMAX、OE、BJ等。 1 AR 自…

【疑难攻关】——floor报错注入

作者名&#xff1a;Demo不是emo 主页面链接&#xff1a;主页传送门创作初心&#xff1a;舞台再大&#xff0c;你不上台&#xff0c;永远是观众&#xff0c;没人会关心你努不努力&#xff0c;摔的痛不痛&#xff0c;他们只会看你最后站在什么位置&#xff0c;然后羡慕或鄙夷座右…

mysql多表查询30个经典案例

mysql多表查询30个经典案例插入两张表一个dept一个emp插入dept表数据插入emp表数据1.列出每个部门里面有那些员工及部门名称;2.运维部门的收入总和&#xff1b;3.HR部入职员工的员工号4.财务部门收入超过5000元的员工姓名5.找出销售部收入最低的员工的入职时间&#xff1b;6.找…

5G NR标准: 第20章 5G的演进

第20章 5G的演进 NR 的第一个版本&#xff0c;第 15 版&#xff0c;侧重于对 eMBB 的基本支持&#xff0c;在某种程度上&#xff0c;URLLC.1 如前几章所述&#xff0c;第 15 版是为即将发布的 NR 未来发展构建的基础 . NR 演进将带来额外的功能并进一步提升性能。 附加功能不…

Netty原理示图

1. AWT事件驱动 2. Websocket协议 3. 基于多个反应器的多线程模式 4. Netty Reactor 工作架构图 5. Bootstrap引导过程 Channel Channel是Java NIO的基础。它表示一个开放的连接&#xff0c;进行IO操作。基本的 I/O 操作&#xff08; bind() 、 connect() 、 read() 和 write(…

什么是异常?异常可以看作你敲出来的bug

异常异常的体系抛异常try -catchfinally自定义异常作为初学者&#xff0c;在刚开始写代码的时候&#xff0c;差不多写一行代码都要见一行红吧异常的体系 这里我们首先需要知道的一点是&#xff0c;所有的异常其实都是类。我们所有的异常都是继承于Throwable这个大类的&#xff…

喜讯!神策分析 Android SDK 入选数据安全“星熠”案例

随着《数据安全法》和《个人信息保护法》的相继出台实施&#xff0c;标志着数据安全保护法治时代的真正到来&#xff0c;国家对数据安全的重视达到了前所未有的高度。在此背景下&#xff0c;神策数据全面落地数据开发利用和数据安全领域的技术推广与产业创新&#xff0c;神策分…

有哪些视频素材网站值得推荐?

高质量视频素材网站&#xff0c;免费、可商用&#xff0c;建议收藏&#xff01; 1、菜鸟图库 https://www.sucai999.com/video.html?vNTYwNDUx 网站有超多视频素材&#xff0c;全部都是高清无水印&#xff0c;各种类型都有&#xff0c;像自然、城市、动物、科技、商业等等都…

【算法】哈希表

&#x1f600;大家好&#xff0c;我是白晨&#xff0c;一个不是很能熬夜&#x1f62b;&#xff0c;但是也想日更的人✈。如果喜欢这篇文章&#xff0c;点个赞&#x1f44d;&#xff0c;关注一下&#x1f440;白晨吧&#xff01;你的支持就是我最大的动力&#xff01;&#x1f4…