智能电灯书架的设计

一、创意背景

你是否每次都在上课前因为记不住课表,不知道要拿什么书,教室在哪而每次打开智慧学工查询,我们这款智能书架能将课表与书架结合,快速找到当天的课程、所需书籍,以及教室。

二、创意内容及目的

用一个带隔栏的书架主体区分书的位置,书架在对应书本前设置小灯,用来指示是否为上课的书,并切由stm32来驱动灯泡亮灭,设置8个按键,七个按键用来输入星期几,第八个按键用来切换一天中的课程情况,并且用显示屏将课程名称和教室显示出来。由此来实现不用手机查课表的功能。

创意具体说明

以stm32为核心,使用了创新按键算法,检索算法,对随时可以改变的拟定数据进行操作后,就可以达到按键控制点灯的效果,因为io口较多,所以本书架硬件上采用了级联的74hc595移位寄存器操控16个位以spi通信协议作为通讯方式控制。然后是对于噪音的干扰,设计并搭建了滤波电路来进行处理,使得led灯接受信号波动平稳,然后是显示模块,由于考虑到字符显示对于使用者的重要性,故使用了lcd19264,创建了其初始化程序,最后是led健的设计,led前七个灯是操控星期一到星期天的对应课程的灯的点亮,使用按键算法使其相互独立,互不制约,而第八个按键是制约前七个按键,单机/双击具有切换课程的作用,长击具有关灯的作用,使用长击后,蜂鸣器会短暂提示,表示灯熄灭了,与此同时,显示屏熄灭。

以下是视频演示:

智能电灯书架


 

status_machine_key.h  :定时器初始化(其宏定义名字也以key开头)

#ifndef  _STATUS_MACHINE_KEY__H
#define  _STATUS_MACHINE_KEY__H
#include "stm32f10x.h"               
#include <stdio.h>
//以下是单个按键的长按和短按操作,状态机算法
typedef struct//结构体参数不需要初始化
{
	uint8_t press_short;
	uint8_t press_long;
	
}status_mode;

按键0:有效按键,1:无效按键;
//uint8_t key_flag=0;

#define   KEY_STATUS_RCC   RCC_APB2Periph_GPIOB
#define   KEY_GPIO         GPIOB
#define   KEY_PIN          GPIO_Pin_4
#define   KEY_TIMx         TIM4
#define   KEY_TIM_RCC      RCC_APB1Periph_TIM4
#define   KEY_STATUS       GPIO_ReadInputDataBit(KEY_GPIO,KEY_PIN)

extern status_mode status;

void Status_machine_key_GPIO(void);//引脚初始化PB4,IPU_MODE
void Status_machine_key_TIM(uint16_t ARR,uint16_t PSC);

#endif

通过定时器对按键的状态(multi_key();)进行扫描

#include "stm32f10x.h"                  
#include "status_machine_key.h"  

#include "NEW_Encoder.h"//一个按键的单机双击长击设置
#include "Multi_key.h"//多重按键的单击双击长击设置

#include "Tim_Key.h"//计时器的按键单机双击长击设置
#include "Exit_init.h"//计时器按键中断配置函数(含有计时器逻辑)

#include "doublekey_Exit.h"   //双按键的中断设计管理
#include "doublekey.h"

 uint8_t lock=0;//确保下轮进行判断
 uint8_t Cnt=0;//确保下轮进行判断
 uint16_t mode=1;//初始状态
 uint8_t timer=0;
 status_mode status;

//TIM4的使用

void Status_machine_key_GPIO(void)//引脚初始化PB4,IPU_MODE
{
		RCC_APB2PeriphClockCmd(KEY_STATUS_RCC,ENABLE);
  	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//开启exit的标志位
		GPIO_PinRemapConfig(GPIO_Remap_SWJ_NoJTRST, ENABLE);//恢复PB4的GPIO的功能
	  
		GPIO_InitTypeDef STATUS_GPIO;
		STATUS_GPIO.GPIO_Mode=GPIO_Mode_IPU;
		STATUS_GPIO.GPIO_Pin=KEY_PIN;
		STATUS_GPIO.GPIO_Speed=GPIO_Speed_50MHz;	  
	  GPIO_Init(KEY_GPIO,&STATUS_GPIO);  	
	}

 void Status_machine_key_TIM(uint16_t ARR,uint16_t PSC)//通用定时器TIM4定义,可以普遍用于需要计时的,模块,函数,需要外部调用
{
	RCC_APB1PeriphClockCmd(KEY_TIM_RCC,ENABLE);
	
	TIM_TimeBaseInitTypeDef STATUS_TIM;
	TIM_TimeBaseStructInit(&STATUS_TIM);
	STATUS_TIM.TIM_ClockDivision=TIM_CKD_DIV1;
	STATUS_TIM.TIM_CounterMode=TIM_CounterMode_Up;//向上计
  STATUS_TIM.TIM_Period=ARR;//该位最大在TIM1定时器中为16位
  STATUS_TIM.TIM_Prescaler=PSC;//同上
  STATUS_TIM.TIM_RepetitionCounter=0;//默认为零;
	TIM_TimeBaseInit(KEY_TIMx,&STATUS_TIM);
	
	TIM_ITConfig(KEY_TIMx,TIM_IT_Update, ENABLE);//开启定时中断;

	NVIC_PriorityGroupConfig(0);
	NVIC_InitTypeDef Status_Machine_TIMNVIC;
	Status_Machine_TIMNVIC.NVIC_IRQChannel=TIM4_IRQn;//定时器4的中断寄存器的配置
	Status_Machine_TIMNVIC.NVIC_IRQChannelCmd=ENABLE;
	Status_Machine_TIMNVIC.NVIC_IRQChannelPreemptionPriority=1; 
  Status_Machine_TIMNVIC.NVIC_IRQChannelSubPriority=1; 
  NVIC_Init(&Status_Machine_TIMNVIC); 
	
	TIM_Cmd(KEY_TIMx,ENABLE);//初始化开始定时器即时打开	
}

//the core code under:

void Status_machine_key_Scan(void)//长击实现结构体初始化为1,短击实现结构体初始化为1;
 {
	 switch(mode)
	 {
		 case 1:
			 if(!KEY_STATUS)
			 {
				 mode=2;//进阶触发状态
			 }
		    lock=0;
				 Cnt=0;			 
			 break;
		 case 2:
			 if(!KEY_STATUS)
			 {
				 if(!lock){lock=1;}
				 Cnt++;
				 if(Cnt>100)//如果在进入中断100次,也就是1s,则为长按,否则即为短按
				 {
					status.press_long=1; 
					status.press_short=0;
					lock=0;
					Cnt=0;
					mode=3;
				 }
			 }
			 else
			 {
				 if (lock==1)             
				 {
					 status.press_short=1; 
					 status.press_long=0;
					 lock=0;
				 }
				 else
				 {
					 mode=1;
				 }
			 } break;
		 case 3:
			 if(KEY_STATUS)
			 {
				 mode=1;			 
			 }
			break;	
		 default:break;			 
	 }
 }
 
volatile uint32_t base=0;
 
 
//以下是定时器4的设置,该定时中断包含了按键的单机双击长击刷新,时基为2ms 
 
 void  TIM4_IRQHandler(void)//定时器4的触发溢出中断,2ms触发一次
{ 
	if(TIM_GetITStatus(KEY_TIMx,TIM_IT_Update)!=RESET)//满了触发 
	{
		base++;
	  timer++; 
		if(timer>5)//短时间的10ms,每10ms进行一次判断,如果按下1s时间,则会判断100次,里面的Cnt会满足条件的加到100,否则就是短按
		{
			timer=0;
			Status_machine_key_Scan();
		}
		Encoder_Scan();//单个按键的设置
		Multi_key_Scan();//多重按键的设置
		tim_Multi_key_Scan();//计时器按键的设置
    TIMMING_Clock(base);		
	  Doublekey_Multi_key_Scan();//双重按键扫描函数
		DOUBEL_TIMMING_Clock(base);//双重按键计时器扫描
	}
	TIM_ClearITPendingBit(KEY_TIMx,TIM_IT_Update);
}

因为是8个按键故初始化了8个按键:

Multi_key.h

#ifndef  __MULTI_KEY_H
#define  __MULTI_KEY_H
#include "stm32f10x.h"                

//8个按键的单击双击长击设置

typedef struct
{
	uint8_t shortstick1;
	uint8_t longstick1;
	uint8_t dualstick1;
	
	uint8_t shortstick2;
	uint8_t longstick2;
	uint8_t dualstick2;
	
	uint8_t shortstick3;
	uint8_t longstick3;
	uint8_t dualstick3;
	
	uint8_t shortstick4;
	uint8_t longstick4;
	uint8_t dualstick4;
	
	uint8_t shortstick5;
	uint8_t longstick5;
	uint8_t dualstick5;
	 
	uint8_t shortstick6;
	uint8_t longstick6;
	uint8_t dualstick6;
	
	uint8_t shortstick7;
	uint8_t longstick7;
	uint8_t dualstick7;
	
	uint8_t shortstick8;
	uint8_t longstick8;
	uint8_t dualstick8;
	
}Multi_key;

#define   KEY_STATUS_RCC7   RCC_APB2Periph_GPIOA
#define   KEY_GPIO7         GPIOA
#define   KEY_PIN7          GPIO_Pin_7
#define   KEY_STATUS7       GPIO_ReadInputDataBit(KEY_GPIO7,KEY_PIN7)

#define   KEY_STATUS_RCC6   RCC_APB2Periph_GPIOA
#define   KEY_GPIO6         GPIOA
#define   KEY_PIN6          GPIO_Pin_6
#define   KEY_STATUS6       GPIO_ReadInputDataBit(KEY_GPIO6,KEY_PIN6)

#define   KEY_STATUS_RCC5   RCC_APB2Periph_GPIOA
#define   KEY_GPIO5         GPIOA
#define   KEY_PIN5          GPIO_Pin_5
#define   KEY_STATUS5       GPIO_ReadInputDataBit(KEY_GPIO5,KEY_PIN5)

#define   KEY_STATUS_RCC4   RCC_APB2Periph_GPIOA
#define   KEY_GPIO4         GPIOA
#define   KEY_PIN4          GPIO_Pin_4
#define   KEY_STATUS4       GPIO_ReadInputDataBit(KEY_GPIO4,KEY_PIN4)

#define   KEY_STATUS_RCC3   RCC_APB2Periph_GPIOA
#define   KEY_GPIO3         GPIOA
#define   KEY_PIN3          GPIO_Pin_3
#define   KEY_STATUS3       GPIO_ReadInputDataBit(KEY_GPIO3,KEY_PIN3)

#define   KEY_STATUS_RCC2   RCC_APB2Periph_GPIOA
#define   KEY_GPIO2         GPIOA
#define   KEY_PIN2          GPIO_Pin_2
#define   KEY_STATUS2       GPIO_ReadInputDataBit(KEY_GPIO2,KEY_PIN2)

#define   KEY_STATUS_RCC1   RCC_APB2Periph_GPIOA
#define   KEY_GPIO1         GPIOA
#define   KEY_PIN1          GPIO_Pin_1
#define   KEY_STATUS1       GPIO_ReadInputDataBit(KEY_GPIO1,KEY_PIN1)

#define   KEY_STATUS_RCC0   RCC_APB2Periph_GPIOA
#define   KEY_GPIO0         GPIOA
#define   KEY_PIN0          GPIO_Pin_0
#define   KEY_STATUS0       GPIO_ReadInputDataBit(KEY_GPIO0,KEY_PIN0)

#define  uint    1
#define  shaking_tim      (8/uint)//抖动时间16ms
#define  shortstick_tim   (200/uint)//0.4s
#define  doublestick_tim  (400/uint)//间隔时间为0.8s
#define  longtstick_tim   (600/uint)//超过1.2s为长击,持续时间<20s

extern Multi_key keystruct;//定义结构体的变量

void Multi_keyGPIOInit(void);//引脚的初始化

void Multi_key_Scan(void);//多按键的扫描


#endif

Multi_key.c

#include "stm32f10x.h"             
#include "Multi_key.h"
#include "status_machine_key.h"//调用单按键的TIM计时器功能,每2ms扫描按键一次;

Multi_key keystruct;//结构体变量的定义
uint16_t Multi_count;//按键总体计数位
uint16_t Multi_dual_count;//双击计数位
uint16_t Multi_short_stickflag;//短击标志位
uint16_t Multi_long_stickflag;//长击标志位
uint16_t Multi_dual_stickflag;//双击标志位
uint16_t position;//区别按键按下的标志位

void CLEAR_COUNT(void)
{
		  Multi_count=0;
		  Multi_short_stickflag=0;
		  Multi_dual_stickflag=0;
		  Multi_long_stickflag=0;
			position=0;
}

void Multi_keyGPIOInit(void)
{
	RCC_APB2PeriphClockCmd(KEY_STATUS_RCC7,ENABLE);
	
	GPIO_InitTypeDef Multi_keyGPIO;
	Multi_keyGPIO.GPIO_Mode=GPIO_Mode_IPU;//按键属于信号输入,默认上拉输入
	Multi_keyGPIO.GPIO_Pin=KEY_PIN7|KEY_PIN6|KEY_PIN5|KEY_PIN4|KEY_PIN3|KEY_PIN2|KEY_PIN1|KEY_PIN0;//八个按键初始化
	Multi_keyGPIO.GPIO_Speed=GPIO_Speed_50MHz;//速率50Ms
	GPIO_Init(GPIOA,&Multi_keyGPIO);
}


void Multi_key_Scan(void)
{

	if(!KEY_STATUS7&&KEY_STATUS6&&KEY_STATUS5&&KEY_STATUS4&&KEY_STATUS3&&KEY_STATUS2&&KEY_STATUS1&&KEY_STATUS0)//如果7按下且其余为高电平
	{
		 position=8;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}
	
	if(KEY_STATUS7&&!KEY_STATUS6&&KEY_STATUS5&&KEY_STATUS4&&KEY_STATUS3&&KEY_STATUS2&&KEY_STATUS1&&KEY_STATUS0)//如果6按下且其余为高电平
	{
		 position=7;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}	
	
	if(KEY_STATUS7&&KEY_STATUS6&&!KEY_STATUS5&&KEY_STATUS4&&KEY_STATUS3&&KEY_STATUS2&&KEY_STATUS1&&KEY_STATUS0)//如果7按下且其余为高电平
	{
		 position=6;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}	
	
	if(KEY_STATUS7&&KEY_STATUS6&&KEY_STATUS5&&!KEY_STATUS4&&KEY_STATUS3&&KEY_STATUS2&&KEY_STATUS1&&KEY_STATUS0)//如果7按下且其余为高电平
	{
		 position=5;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}	
	
	if(KEY_STATUS7&&KEY_STATUS6&&KEY_STATUS5&&KEY_STATUS4&&!KEY_STATUS3&&KEY_STATUS2&&KEY_STATUS1&&KEY_STATUS0)//如果7按下且其余为高电平
	{
		 position=4;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}	
	
	if(KEY_STATUS7&&KEY_STATUS6&&KEY_STATUS5&&KEY_STATUS4&&KEY_STATUS3&&!KEY_STATUS2&&KEY_STATUS1&&KEY_STATUS0)
	{
		 position=3;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}
	
	if(KEY_STATUS7&&KEY_STATUS6&&KEY_STATUS5&&KEY_STATUS4&&KEY_STATUS3&&KEY_STATUS2&&!KEY_STATUS1&&KEY_STATUS0)
	{
		 position=2;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}
	
	if(KEY_STATUS7&&KEY_STATUS6&&KEY_STATUS5&&KEY_STATUS4&&KEY_STATUS3&&KEY_STATUS2&&KEY_STATUS1&&!KEY_STATUS0)
	{
		 position=1;
		if(Multi_count<10000)//小于20s主要是为了预防长按导致的长时间停留,导致count被清零长按失去意义
     {
			 Multi_count++;
		 }
		if(Multi_count>shaking_tim)//不管想要按下什么状态,短击标志位始终需要置为1;
     {
			 Multi_short_stickflag=1;
		 }
		if(Multi_dual_stickflag==0&&Multi_dual_count>0)//双击位置为1,该行代码为第二次按下按键启动,第一次松开时Multi_dual_count开始自增;
    { 
		  Multi_dual_stickflag=1;
		}
		if(Multi_count>longtstick_tim)//长击位置为1;
    {
		  Multi_short_stickflag=0;Multi_long_stickflag=1;
		}
	}
	else
	if(KEY_STATUS7&&KEY_STATUS6&&KEY_STATUS5&&KEY_STATUS4&&KEY_STATUS3&&KEY_STATUS2&&KEY_STATUS1&&KEY_STATUS0)//如果松开且全部为松手
	{
		if(Multi_count<shaking_tim)//松下时未达到消抖时间
   {
			Multi_count=0;
			Multi_short_stickflag=0;
			Multi_dual_stickflag=0;
			Multi_long_stickflag=0;
			Multi_dual_count=0;
	 }
		if(Multi_short_stickflag==1)//也就是没有长击情况
		{
			if(Multi_dual_count>0||Multi_dual_count==0)//在前一次为短击的情况下,松开就自动计时
       {
			   Multi_dual_count++;
			 }
			if(Multi_dual_count<=doublestick_tim&&Multi_dual_stickflag==1)//双击按键成功,为两次
       {
			  Multi_dual_stickflag=2;Multi_dual_count=0;
			  }
			if(Multi_dual_stickflag==0&&Multi_dual_count>doublestick_tim)
       {
				 Multi_short_stickflag=2;
			 }
		 //如果第一次按下松开后,双机计数位递增但是超过时间间隔范围内且没有再次按键按下,即本次事件为单击
		}
		if(Multi_long_stickflag==1)
		{
			Multi_long_stickflag=2;
		}
	}
	//*******以下是按键的判断************//		
	if(Multi_count>shaking_tim&&Multi_count<10000)
	{
    //按键8
		if(Multi_short_stickflag==2&&position==8)
    {
			keystruct.shortstick8=1;
			keystruct.dualstick8=0;	
			keystruct.longstick8=0;
			CLEAR_COUNT();

		}
			
		if(Multi_long_stickflag==2&&position==8)//如果8按键长击按下,则清除所有的状态。
		{
			keystruct.longstick8=2;
			keystruct.dualstick8=0;		 	
			keystruct.shortstick8=0;	
			keystruct.shortstick1=0;
			keystruct.shortstick2=0;	
			keystruct.shortstick4=0;
			keystruct.shortstick5=0;
			keystruct.shortstick6=0;
			keystruct.shortstick3=0;
			keystruct.shortstick7=0;
			CLEAR_COUNT();			
		}
		
		if(Multi_dual_stickflag==2&&position==8) 
		{
			keystruct.dualstick8=3;
			keystruct.longstick8=0;
			keystruct.shortstick8=0;
			CLEAR_COUNT();		
		}	
    //按键7		
		if(Multi_short_stickflag==2&&position==7)
    {
			keystruct.shortstick7=1;
			keystruct.dualstick7=0;	
			keystruct.longstick7=0;
			keystruct.shortstick1=0;
			keystruct.shortstick2=0;	
			keystruct.shortstick4=0;
			keystruct.shortstick5=0;
			keystruct.shortstick6=0;
			keystruct.shortstick3=0;
			keystruct.shortstick8=0;
			CLEAR_COUNT();
		}
			
		if(Multi_long_stickflag==2&&position==7)
		{
			keystruct.longstick7=2;
			keystruct.dualstick7=0;			
			keystruct.shortstick7=0;	
			CLEAR_COUNT();		
		}
		
		if(Multi_dual_stickflag==2&&position==7) 
		{
			keystruct.dualstick7=3;
			keystruct.longstick7=0;
			keystruct.shortstick7=0;
			CLEAR_COUNT();		
		}			
		//按键6
		if(Multi_short_stickflag==2&&position==6)
    {
			keystruct.shortstick6=1;
			keystruct.dualstick6=0;	
			keystruct.longstick6=0;
			keystruct.shortstick1=0;
			keystruct.shortstick2=0;	
			keystruct.shortstick4=0;
			keystruct.shortstick5=0;
			keystruct.shortstick3=0;
			keystruct.shortstick7=0;
			keystruct.shortstick8=0;
			keystruct.longstick8=0;
			CLEAR_COUNT();
		}
			
		if(Multi_long_stickflag==2&&position==6)
		{
			keystruct.longstick6=2;
			keystruct.dualstick6=0;			
			keystruct.shortstick6=0;	
			CLEAR_COUNT();			
		}
		
		if(Multi_dual_stickflag==2&&position==6) 
		{
			keystruct.dualstick6=3;
			keystruct.longstick6=0;
			keystruct.shortstick6=0;
			CLEAR_COUNT();		
		}	
   //按键5
		if(Multi_short_stickflag==2&&position==5)
    {
			keystruct.shortstick5=1;
			keystruct.dualstick5=0;	
			keystruct.longstick5=0;
			keystruct.shortstick1=0;
			keystruct.shortstick2=0;	
			keystruct.shortstick4=0;
			keystruct.shortstick3=0;
			keystruct.shortstick6=0;
			keystruct.shortstick7=0;
			keystruct.shortstick8=0;
			keystruct.longstick8=0;
			CLEAR_COUNT();
		}
			
		if(Multi_long_stickflag==2&&position==5)
		{
			keystruct.longstick5=2;
			keystruct.dualstick5=0;			
			keystruct.shortstick5=0;	
			CLEAR_COUNT();		
		}
		
		if(Multi_dual_stickflag==2&&position==5) 
		{
			keystruct.dualstick5=3;
			keystruct.longstick5=0;
			keystruct.shortstick5=0;
			CLEAR_COUNT();		
		}
    //按键4
		if(Multi_short_stickflag==2&&position==4)
    {
			keystruct.shortstick4=1;
			keystruct.dualstick4=0;	
			keystruct.longstick4=0;
			keystruct.shortstick1=0;
			keystruct.shortstick2=0;	
			keystruct.shortstick3=0;
			keystruct.shortstick5=0;
			keystruct.shortstick6=0;
			keystruct.shortstick7=0;
			keystruct.shortstick8=0;
			keystruct.longstick8=0;
			CLEAR_COUNT();
		}
			
		if(Multi_long_stickflag==2&&position==4)
		{
			keystruct.longstick4=2;
			keystruct.dualstick4=0;			
			keystruct.shortstick4=0;	
			CLEAR_COUNT();		
		}
		
		if(Multi_dual_stickflag==2&&position==4) 
		{
			keystruct.dualstick4=3;
			keystruct.longstick4=0;
			keystruct.shortstick4=0;	
			CLEAR_COUNT();		
		}	
    //按键3
		if(Multi_short_stickflag==2&&position==3)
    {
			keystruct.shortstick3=1;
			keystruct.dualstick3=0;	
			keystruct.longstick3=0;
			keystruct.shortstick1=0;
			keystruct.shortstick2=0;	
			keystruct.shortstick4=0;
			keystruct.shortstick5=0;
			keystruct.shortstick6=0;
			keystruct.shortstick7=0;
			keystruct.shortstick8=0;
			keystruct.longstick8=0;
			CLEAR_COUNT();
		}
			
		if(Multi_long_stickflag==2&&position==3)
		{
			keystruct.longstick3=2;
			keystruct.dualstick3=0;			
			keystruct.shortstick3=0;	
			CLEAR_COUNT();		
		}
		
		if(Multi_dual_stickflag==2&&position==3) 
		{
			keystruct.dualstick3=3;
			keystruct.longstick3=0;
			keystruct.shortstick3=0;				
			CLEAR_COUNT();		
		}	
    //按键2
		if(Multi_short_stickflag==2&&position==2)
    {
			keystruct.shortstick2=1;
			keystruct.dualstick2=0;	
			keystruct.longstick2=0;
			keystruct.shortstick1=0;
			keystruct.shortstick3=0;	
			keystruct.shortstick4=0;
			keystruct.shortstick5=0;
			keystruct.shortstick6=0;
			keystruct.shortstick7=0;
			keystruct.shortstick8=0;
			keystruct.longstick8=0;
			CLEAR_COUNT();
		}
			
		if(Multi_long_stickflag==2&&position==2)
		{
			keystruct.longstick2=2;
			keystruct.dualstick2=0;			
			keystruct.shortstick2=0;	
			CLEAR_COUNT();		
		}
		
		if(Multi_dual_stickflag==2&&position==2) 
		{
			keystruct.dualstick2=3;
			keystruct.longstick2=0;
			keystruct.shortstick2=0;			
			CLEAR_COUNT();		
		}
    //按键1
		if(Multi_short_stickflag==2&&position==1)
    {
			keystruct.shortstick1=1;
			keystruct.dualstick1=0;		
			keystruct.longstick1=0;		
			keystruct.shortstick2=0;
			keystruct.shortstick3=0;	
			keystruct.shortstick4=0;
			keystruct.shortstick5=0;
			keystruct.shortstick6=0;
			keystruct.shortstick7=0;
			keystruct.shortstick8=0;
			keystruct.longstick8=0;
			
			CLEAR_COUNT();
		}
			
		if(Multi_long_stickflag==2&&position==1)
		{
			keystruct.longstick1=2;
			keystruct.dualstick1=0;			
			keystruct.shortstick1=0;			
			CLEAR_COUNT();	
      			
		}
		
		if(Multi_dual_stickflag==2&&position==1) 
		{
			keystruct.dualstick1=3;
			keystruct.longstick1=0;
			keystruct.shortstick1=0;
			CLEAR_COUNT();			
		}			
	}
}

采用spi的通讯协议的LCD19624,其初始化代码如下:

LCD19264.h

#ifndef  __LCD19264_H
#define  __LCD19264_H
#include "stm32f10x.h"                 
//spi通信协议
//以下引脚,为,需要AFIO复用功能来进行激活
#define  SCK_19264  GPIO_Pin_5//时钟的上下输入信号线
#define  SDA_19264  GPIO_Pin_3//数据输入端
#define  RST_19264  GPIO_Pin_15//复位端
#define  CD_19264   GPIO_Pin_12//指令的话:0;数据的话:1;
#define  CS_19264   GPIO_Pin_11//片选位
#define  LCD19264_SCK_RCC   RCC_APB2Periph_GPIOB
#define  LCD19264_SDA_RCC   RCC_APB2Periph_GPIOB
#define  LCD19264_RST_RCC   RCC_APB2Periph_GPIOA
#define  LCD19264_CD_RCC    RCC_APB2Periph_GPIOA
#define  LCD19264_CS_RCC    RCC_APB2Periph_GPIOA
#define  SCK_GPIO          GPIOB
#define  SDA_GPIO          GPIOB
#define  RST_GPIO          GPIOA
#define  CD_GPIO           GPIOA
#define  CS_GPIO           GPIOA

#define  SCK_HIGH    GPIO_SetBits(SCK_GPIO,SCK_19264)
#define  SCK_LOW     GPIO_ResetBits(SCK_GPIO,SCK_19264)

#define  SDA_HIGH    GPIO_SetBits(SDA_GPIO,SDA_19264)
#define  SDA_LOW     GPIO_ResetBits(SDA_GPIO,SDA_19264)

#define  RST_HIGH    GPIO_SetBits(RST_GPIO,RST_19264)
#define  RST_LOW     GPIO_ResetBits(RST_GPIO,RST_19264)

#define  CD_HIGH     GPIO_SetBits(CD_GPIO,CD_19264)
#define  CD_LOW      GPIO_ResetBits(CD_GPIO,CD_19264)

#define  CS_HIGH     GPIO_SetBits(CS_GPIO,CS_19264)
#define  CS_LOW      GPIO_ResetBits(CS_GPIO,CS_19264)

void LCD19264_Write_Byte(uint8_t byte);//数据的写入

void LCD19264_Chinese(uint8_t dir,uint8_t x,uint8_t y,uint8_t high,uint8_t wide,uint8_t *data);//字符数据的写入与位移操作

void LCD19264_GPIO_Init(void);//引脚初始化

void LCD19264_Init(void);//显示屏初始化操作

void LCD19264_Clear(void);//清屏操作,清除64行,192列的所有数据
#endif

LCD19264.c

#include "stm32f10x.h"               
#include "LCD19264.h"
#include "Delay.h"
//spi通信协议来对数据进行处理

#define CD_Cmd  0//CD线0代表写指令,1代表写数据
#define CD_Data 1


void LCD19264_GPIO_Init(void)
{
	RCC_APB2PeriphClockCmd(LCD19264_SCK_RCC|LCD19264_RST_RCC|RCC_APB2Periph_AFIO,ENABLE);//使能GPIOA,以及GPIOB,AFIO复用引脚
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);//取缔JTDI,JTDIO,NJRST,激活PB3,4,PA15
	
	GPIO_InitTypeDef LCD19264;
  LCD19264.GPIO_Mode=GPIO_Mode_Out_PP;//信号输出给LCD19264,所以用推挽输出
	LCD19264.GPIO_Pin=SCK_19264|SDA_19264;//都为GPIOB
	LCD19264.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_Init(SCK_GPIO, &LCD19264);
	
  LCD19264.GPIO_Mode=GPIO_Mode_Out_PP;//信号输出给LCD19264,所以用推挽输出
	LCD19264.GPIO_Pin=RST_19264|CD_19264|CS_19264;//都为GPIOA
	GPIO_Init(CD_GPIO, &LCD19264);
}

void LCD19264_Write_Byte(uint8_t byte)//数据的写入
{
	CS_LOW;//片选信号拉低,选择设备进行输入数据
	for(uint8_t i=0;i<8;i++)
	{
		((byte<<i)&0x80)?SDA_HIGH:SDA_LOW;
		
		SCK_LOW;//允许数据发生变化
		Delay_us(5);
		SCK_HIGH;//数据锁存
		Delay_us(5);
	}
	CS_HIGH;//片选信号拉高,回到未读取状态
}

void LCD19264_Write_cmd(uint8_t cmd,uint8_t data)//利用CD线对指令进行写入指令0(cmd)
{
	GPIO_WriteBit(CD_GPIO,CD_19264, (BitAction)(cmd));//对CD引脚进行位操作
	LCD19264_Write_Byte(data);//向总线写数据
}



void LCD19264_Init(void)//显示屏初始化操作
{
	//首先复位
	RST_LOW;
	Delay_ms(5);
	RST_HIGH;
	Delay_ms(5);	
	
	LCD19264_Write_cmd(CD_Cmd,0xe2);//屏复位指令
	LCD19264_Write_cmd(CD_Cmd,0xa3);//屏帧数率刷新控制
  LCD19264_Write_cmd(CD_Cmd,0xeb);//设置亮度对比度调节,建议eb
  LCD19264_Write_cmd(CD_Cmd,0x2f);//显示屏功耗设置	
  LCD19264_Write_cmd(CD_Cmd,0xc2);//设置LCD映射控制
  LCD19264_Write_cmd(CD_Cmd,0x81);//设置SEG偏置电压(对比度),双字节指令
	LCD19264_Write_cmd(CD_Cmd,0xaa);//0~255,背光度调节,a0:160
	LCD19264_Write_cmd(CD_Cmd,0xaf);//开机显示指令
}

void LCD19264_Clear(void)//清屏操作,清除64行,192列的所有数据
{
	for(uint8_t i=0;i<8;i++)
	{
		LCD19264_Write_cmd(CD_Cmd,0xb0|i);//按行line擦
    for(uint8_t j=0;j<192;j++)
	  {
		  LCD19264_Write_cmd(CD_Data,0X00);//按列row擦//0x00全屏幕熄灭(变成黑色)//0xff全屏点亮
		}
	}
}

/*
**@brief:展示汉字
**@program:dir:1正显示,0反转显示,x:64行方向,y:192列方向,high:显示的高度,单位为8的倍数,wide:字体移动的宽度,data:数据
**@retval:
*/
void LCD19264_Chinese(uint8_t dir,uint8_t x,uint8_t y,uint8_t high,uint8_t wide,uint8_t *data)
{
	(dir)? LCD19264_Write_cmd(CD_Cmd,0Xc2):LCD19264_Write_cmd(CD_Cmd,0Xc4);
	for(uint8_t i=0;i<high;i++)//high为2,wide为16,则一共要输入32次,所以对应的word字符数组,一行为32位,指针所以为8位的指针
	{
		LCD19264_Write_cmd(CD_Cmd,(0xb0|i)+x);
		LCD19264_Write_cmd(CD_Cmd,0X10+(y>>4&0x0f));		
		LCD19264_Write_cmd(CD_Cmd,y&0x0f);
		for(uint8_t j=0;j<wide;j++)
		{
		LCD19264_Write_cmd(CD_Data,*data++);
		}
	}
}

以下是课表的代码:

逻辑是调用LCD19264.h 以19624来实现对课表的显示

Show_string.h

#ifndef  __SHOW_STRING_H
#define  __SHOW_STRING_H
#include "stm32f10x.h"                  

void CLEAR_MONITOR(uint16_t select,uint8_t jugde);//num取line:1~4,judge如果等于1就清屏,否则不清屏
void WEEK_DAY(uint16_t week);           //管理范围:第1行,提示周,参数为1~7
void SELECT_CURRICULUM(uint16_t num);   //管理范围:第2行,参数1~9,因为书架有1-9个格子,展示课程,但是参数为1~10因为附加选修课
void Manage_Serial_Number(uint16_t num);//管理范围:第3行,课程序号范围
void LIGHT_UP(uint16_t num);            //管理范围:第4行,灯亮范围提示,参数为对应的天数,为:1~7
#endif

Show_string.c

#include "stm32f10x.h"     
#include "Show_string.h" 
#include "LCD19264.h"
#include <word1.c>//添加字符的c文件
//显示课程,及其星期,和序号
/*//目前为16*16的内容,4line,13row
**@brief:清除屏幕的内容,该黑膜屏幕原本底色为白色,内容填充后为黑色,所以,这个“清屏”其实相当于另一项填充设置,把全为白色的底色改为黑色
**@program:传入想改的行数,line:1~4
**@retval:无
*/
void CLEAR_MONITOR(uint16_t select,uint8_t jugde)//num取line:1~4,judge如果等于1就清屏,否则不清屏
{
	 uint8_t num=2*(select-1);
	 if(jugde)
	 {		 
		 LCD19264_Chinese(1,num,0,2,16,(u8*)&word1[12]);	
		 LCD19264_Chinese(1,num,1*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,2*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,3*16,2,16,(u8*)&word1[12]);	
		 LCD19264_Chinese(1,num,4*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,5*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,6*16,2,16,(u8*)&word1[12]);	
		 LCD19264_Chinese(1,num,7*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,8*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,9*16,2,16,(u8*)&word1[12]);	
		 LCD19264_Chinese(1,num,10*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,11*16,2,16,(u8*)&word1[12]);		 
		 LCD19264_Chinese(1,num,12*16,2,16,(u8*)&word1[12]);		 
	 }
}

void WEEK_DAY(uint16_t week)//管理范围:第1行,提示周,参数为1~7
{
	switch (week)
	{
		case 1://星期一
		 for(uint16_t i=0,j=0;i<=12&&j<=12;i++,j++)
		 {
			 LCD19264_Chinese(1,0,i*16,2,16,(u8*)&word3[j]);
		 }	
   break;   		 
		case 2://星期二
		 for(uint16_t i=0,j=13;i<=12&&j<=25;i++,j++)
		 {
			 LCD19264_Chinese(1,0,i*16,2,16,(u8*)&word3[j]);
		 }	
   break;
		case 3://星期三
		 for(uint16_t i=0,j=26;i<=12&&j<=38;i++,j++)
		 {
			 LCD19264_Chinese(1,0,i*16,2,16,(u8*)&word3[j]);
		 }	
   break;
		case 4://星期四
		 for(uint16_t i=0,j=38;i<=12&&j<=51;i++,j++)
		 {
			 LCD19264_Chinese(1,0,i*16,2,16,(u8*)&word3[j]);
		 }	
   break;
		case 5://星期五
		 for(uint16_t i=0,j=51;i<=12&&j<=64;i++,j++)
		 {
			 LCD19264_Chinese(1,0,i*16,2,16,(u8*)&word3[j]);
		 }	
   break;
		case 6://星期六
		 for(uint16_t i=0,j=63;i<=12&&j<=77;i++,j++)
		 {
			 LCD19264_Chinese(1,0,i*16,2,16,(u8*)&word3[j]);
		 }	
   break;	
		case 7://星期天
		 for(uint16_t i=0,j=76;i<=12&&j<=90;i++,j++)
		 {
			 LCD19264_Chinese(1,0,i*16,2,16,(u8*)&word3[j]);
		 }	
   break;		 
	}
}

void SELECT_CURRICULUM(uint16_t num)//管理范围:第2行,参数1~10,选择课程,因为书架有1-9个格子
{
	  switch(num)
	 {
	 case 1://液压气压传动@2-410(0-12)
	 //13-25
		 for(uint16_t i=0,j=0;i<=12&&j<=12;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	
		 
   break;
	 case 2://汽车拖拉机学@2-507
	//26-38
		 for(uint16_t i=0,j=13;i<=12&&j<=25;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }

   break;	
		 
	 case 3://工程材料基础@2-217
	//39-51
		 for(uint16_t i=0,j=26;i<=12&&j<=38;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	
	 
   break;		 
	 case 4://机械设计@2-217(52~64)	 
		 for(uint16_t i=0,j=39;i<=12&&j<=51;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;	
	 case 5://数控技术编程@5-313
		 for(uint16_t i=0,j=52;i<=12&&j<=64;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;	
	 case 6://生物学基础@5-433 
		 for(uint16_t i=0,j=65;i<=12&&j<=77;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;
	 case 7://信息检索与利用@5-228 
		 for(uint16_t i=0,j=78;i<=12&&j<=90;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;	
	 case 8://农业物料学@5-433	 
		 for(uint16_t i=0,j=91;i<=12&&j<=103;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;	
	 case 9://逆向工程设计@工学院实验室	 
		 for(uint16_t i=0,j=104;i<=12&&j<=116;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;	 
	 case 10://新媒体技术@2-209	 
		 for(uint16_t i=0,j=117;i<=12&&j<=129;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;	
	 case 11://没课提醒 
		 for(uint16_t i=0,j=130;i<=12&&j<=142;i++,j++)
		 {
			 LCD19264_Chinese(1,4,i*16,2,16,(u8*)&word1[j]);
		 }	

   break;	 		 
	 }
}


void Manage_Serial_Number(uint16_t num)//管理范围:第三行,课程序号范围
{
	switch(num)
	{
		case 1://①
			 for(uint16_t i=0,j=0;i<=12&&j<=12;i++,j++)
		 {
			 LCD19264_Chinese(1,6,i*16,2,16,(u8*)&word4[j]);
		 }

   break; 		 
		case 2:	//②
			 for(uint16_t i=0,j=13;i<=12&&j<=25;i++,j++)
		 {
			 LCD19264_Chinese(1,6,i*16,2,16,(u8*)&word4[j]);
		 }	
		 
   break;			
		case 3://③
			 for(uint16_t i=0,j=26;i<=12&&j<=38;i++,j++)
		 {
			 LCD19264_Chinese(1,6,i*16,2,16,(u8*)&word4[j]);
		 }	
		 
   break;			
		case 4://④
			 for(uint16_t i=0,j=39;i<=12&&j<=51;i++,j++)
		 {
			 LCD19264_Chinese(1,6,i*16,2,16,(u8*)&word4[j]);
		 }	
		 
   break;		
	 }		 
}

void LIGHT_UP(uint16_t num)//管理范围:第4行,灯亮范围提示,参数为对应的天数,为:1~7
{
	switch(num)
	{
		case 1://星期一
			 for(uint16_t i=0,j=0;i<=12&&j<=12;i++,j++)
		 {
			 LCD19264_Chinese(1,2,i*16,2,16,(u8*)&word2[j]);
		 }
   break; 		 
		case 2:	//星期二
			 for(uint16_t i=0,j=13;i<=12&&j<=25;i++,j++)
		 {
			 LCD19264_Chinese(1,2,i*16,2,16,(u8*)&word2[j]);
		 }			
   break;			
		case 3://星期三
			 for(uint16_t i=0,j=26;i<=12&&j<=38;i++,j++)
		 {
			 LCD19264_Chinese(1,2,i*16,2,16,(u8*)&word2[j]);
		 }				
   break;			
		case 4://星期四
			 for(uint16_t i=0,j=39;i<=12&&j<=51;i++,j++)
		 {
			 LCD19264_Chinese(1,2,i*16,2,16,(u8*)&word2[j]);
		 }				
   break;			
		case 5://星期五
			 for(uint16_t i=0,j=52;i<=12&&j<=64;i++,j++)
		 {
			 LCD19264_Chinese(1,2,i*16,2,16,(u8*)&word2[j]);
		 }				
   break;			
		case 6://星期六
			 for(uint16_t i=0,j=65;i<=12&&j<=77;i++,j++)
		 {
			 LCD19264_Chinese(1,2,i*16,2,16,(u8*)&word2[j]);
		 }				
   break;			
		case 7:	//星期天
			 for(uint16_t i=0,j=78;i<=12&&j<=90;i++,j++)
		 {
			 LCD19264_Chinese(1,2,i*16,2,16,(u8*)&word2[j]);
		 }				
   break;			
	}
}

Curriculum.h

课程代码头文件集合了显示模块19624代码和按键算法对其进行了整合

#ifndef  __CURRICULUM_H
#define  __CURRICULUM_H
#include "stm32f10x.h"                  

void totalheader_init(void);//功能函数的封装,书架程序调用时需要在主函数中调用此程序

void Final_Curriculum(void);//电灯操作,进行书架电灯操作,在前一个函数调用完后即可使用该函数直接开启书架的电灯功能

#endif

Curriculum.c

#include "Multi_key.h"//多重按键
#include "stm32f10x.h"           
#include "Show_string.h" //显示屏显示字符操作
#include "74HC595.h"//8位移位寄存器开灯
#include "string.h"
#include "LCD19264.h"//lcd19264的初始化
#include "Curriculum.h"
#include "led.h"
#include "delay.h"
#include "dz.h"
unsigned char str[7][7]={"11234","25","36347","484","592","6无课","7选修"};//参考课表,首数字代表星期,之后进行排课操作
uint16_t arr[16]={15,16,108,136,2,0,255};//数字对应以上的字符数对应的课程的灯的位置,0,0代表无课或者进行选修课
void total_init(void)//功能函数的封装
{
 Multi_keyGPIOInit();//多按键的点击初始化设置
 SET_74HC595_GPIO_Cascade();//级联引脚定义
 SET_74HC595_GPIO_Single();//第二块的74hc595的引脚的声明,ds2,shcp2,stcp2
 LCD19264_GPIO_Init();//显示屏引脚初始化
 LCD19264_Init();//显示屏初始化操作
 LCD19264_Clear();//清屏操作,清除64行,192列的所有数据
 led_drive8();
 Single_74hc595_ONE(*(arr+5));//单个74hc595的点灯操作
 light_off_pin_8();
 DZ_init();
}

void LIGHT_UP_AND_LIGHT_OFF(void)//1~7按键可以分别打开灯,8按键长击关掉所有的灯
{
		if(keystruct.shortstick1==1)//星期1
		{
			WEEK_DAY(1);//显示星期一

			LIGHT_UP(1);
			Single_74hc595_ONE(*(arr+0));//单个74hc595的点灯操作
		}
	if(keystruct.shortstick2==1)//星期2
		{
			WEEK_DAY(2);//显示星期二
	
			LIGHT_UP(2);
			Single_74hc595_ONE(*(arr+1));//单个74hc595的点灯操作
		}
	if(keystruct.shortstick3==1)//星期3
		{
			WEEK_DAY(3);//显示星期三
	
			LIGHT_UP(3);			
			Single_74hc595_ONE(*(arr+2));//单个74hc595的点灯操作
		}
	if(keystruct.shortstick4==1)//星期4
		{
			WEEK_DAY(4);//显示星期四

			LIGHT_UP(4);
			Single_74hc595_ONE(*(arr+3));//单个74hc595的点灯操作

		}
	if(keystruct.shortstick5==1)//星期5
		{
			WEEK_DAY(5);//显示星期五

			LIGHT_UP(5);
			Single_74hc595_ONE(*(arr+4));//单个74hc595的点灯操作
			light_up_pin_8();
		}
	if(keystruct.shortstick6==1)//星期6 ,29
		{
			WEEK_DAY(6);//显示星期六
			
			LIGHT_UP(6);
			Single_74hc595_ONE(*(arr+5));//单个74hc595的点灯操作
			light_off_pin_8();

		}
	if(keystruct.shortstick7==1)//星期天
		{
			WEEK_DAY(7);//显示星期七
	
			LIGHT_UP(7);
			Single_74hc595_ONE(*(arr+6));//单个74hc595的点灯操作
			light_up_pin_8();			

		}
	if(keystruct.longstick8==2)//按键8
		{
			Single_74hc595_ONE(*(arr+5));//单个74hc595的点灯操作
			light_off_pin_8();
			CLEAR_MONITOR(1,1);
			CLEAR_MONITOR(2,1);
			CLEAR_MONITOR(3,1);
			CLEAR_MONITOR(4,1);
      keystruct.longstick8=0;		
			LCD19264_Clear();		
			DZ_binging();
			Delay_ms(400);
			DZ_bingoff();
			Delay_ms(100);
      
		}
}

uint16_t timedown0=1;//上下移动的计次变量
uint16_t flagtime1=0;
uint16_t flagtime2=0;

uint16_t timedown1=1;//上下移动的计次变量
uint16_t flagtime3=0;
uint16_t flagtime4=0;

uint16_t timedown2=1;//上下移动的计次变量
uint16_t flagtime5=0;
uint16_t flagtime6=0;

uint16_t timedown3=1;//上下移动的计次变量
uint16_t flagtime7=0;
uint16_t flagtime8=0;
void Final_Curriculum(void)
{   
  LIGHT_UP_AND_LIGHT_OFF();
	//星期一:1234
	if(keystruct.shortstick1==1)
	{

		timedown1=1;
		flagtime3=0;
		flagtime4=0;
		
		timedown2=1;
		flagtime5=0;
		flagtime6=0;
		
		timedown3=1;
		flagtime7=0;
		flagtime8=0;

	if(keystruct.shortstick1==1&&keystruct.shortstick8==1)//如果按键1按下并且8短击按下,则进行上翻操作
		{
			if(flagtime2==1)
			{
				timedown0=1;
//				timedown+=1;
				flagtime2=0;
			}
			switch(timedown0)
			{
				//课程选则2,序号处理3,电灯范围4
				case 1: SELECT_CURRICULUM(1);Manage_Serial_Number(1);timedown0++;break;
				case 2: SELECT_CURRICULUM(2);Manage_Serial_Number(2);timedown0++;break;
				case 3: SELECT_CURRICULUM(3);Manage_Serial_Number(3);timedown0++;break;
				case 4: SELECT_CURRICULUM(4);Manage_Serial_Number(4);timedown0=1;flagtime1=1;break;
			}
			keystruct.shortstick8=0;	
		}
	else
	if(keystruct.shortstick1==1&&keystruct.dualstick8==3)
		{
				if(flagtime1==1)
				{
					timedown0=4;
//					timedown-=1;
					flagtime1=0;
				}
					switch(timedown0)
					 {
						case 1: SELECT_CURRICULUM(1);Manage_Serial_Number(1);timedown0=4;flagtime2=1;break;
						case 2: SELECT_CURRICULUM(2);Manage_Serial_Number(2);timedown0-=1;break;
						case 3: SELECT_CURRICULUM(3);Manage_Serial_Number(3);timedown0-=1;break;
						case 4: SELECT_CURRICULUM(4);Manage_Serial_Number(4);timedown0-=1;break;
					 }
					keystruct.dualstick8=0;				
				}			
	}
	//星期二:5
	if(keystruct.shortstick2==1)//如果按键2按下并且8短击按下,
		{

      timedown0=1;//上下移动的计次变量
		  flagtime1=0;
			flagtime2=0;
			
			timedown1=1;//上下移动的计次变量
			flagtime3=0;
			flagtime4=0;
			
			timedown2=1;//上下移动的计次变量
			flagtime5=0;
			flagtime6=0;
			
			timedown3=1;//上下移动的计次变量
			flagtime7=0;
			flagtime8=0;
			
			SELECT_CURRICULUM(5);
			Manage_Serial_Number(1);	
		}
		
  //星期三:3467
	if(keystruct.shortstick3==1)
	{

		  timedown0=1;//上下移动的计次变量
		  flagtime1=0;
			flagtime2=0;
		  
			timedown2=1;//上下移动的计次变量
			flagtime5=0;
			flagtime6=0;
			
			timedown3=1;//上下移动的计次变量
			flagtime7=0;
			flagtime8=0;		
	
 	if(keystruct.shortstick3==1&&keystruct.shortstick8==1)//如果按键1按下并且8短击按下,则进行上翻操作
		{
			if(flagtime4==1)
			{
				timedown1=1;
//				timedown+=1;
				flagtime4=0;
			}
			switch(timedown1)
			{
				//课程选则2,序号处理3,电灯范围4
				case 1: SELECT_CURRICULUM(6);Manage_Serial_Number(1);timedown1++;break;
				case 2: SELECT_CURRICULUM(3);Manage_Serial_Number(2);timedown1++;break;
				case 3: SELECT_CURRICULUM(4);Manage_Serial_Number(3);timedown1++;break;
				case 4: SELECT_CURRICULUM(7);Manage_Serial_Number(4);timedown1=1;flagtime3=1;break;
			}
			keystruct.shortstick8=0;	
		}
	else
	if(keystruct.shortstick3==1&&keystruct.dualstick8==3)
		{
				if(flagtime3==1)
				{
					timedown1=4;
//					timedown-=1;
					flagtime3=0;
				}
					switch(timedown1)
					 {
						case 1: SELECT_CURRICULUM(6);Manage_Serial_Number(1);timedown1=4;flagtime4=1;break;
						case 2: SELECT_CURRICULUM(3);Manage_Serial_Number(2);timedown1-=1;break;
						case 3: SELECT_CURRICULUM(4);Manage_Serial_Number(3);timedown1-=1;break;
						case 4: SELECT_CURRICULUM(7);Manage_Serial_Number(4);timedown1-=1;break;
					 }
					keystruct.dualstick8=0;				
				}
	}
	//星期四:48
  if(keystruct.shortstick4==1)
	{

			timedown0=1;//上下移动的计次变量
			flagtime1=0;
			flagtime2=0;	
		
			timedown1=1;//上下移动的计次变量
			flagtime3=0;
			flagtime4=0;

			timedown3=1;//上下移动的计次变量
			flagtime7=0;
			flagtime8=0;

 	if(keystruct.shortstick4==1&&keystruct.shortstick8==1)//如果按键1按下并且8短击按下,则进行上翻操作
		{
			if(flagtime6==1)
			{
				timedown2=1;
//				timedown+=1;
				flagtime6=0;
			}
			switch(timedown2)
			{
				//课程选则2,序号处理3,电灯范围4
				case 1: SELECT_CURRICULUM(8);Manage_Serial_Number(1);timedown2++;break;
				case 2: SELECT_CURRICULUM(4);Manage_Serial_Number(2);timedown2=1;flagtime5=1;break;
			}
			keystruct.shortstick8=0;	
		}
	else
	if(keystruct.shortstick4==1&&keystruct.dualstick8==3)
		{
				if(flagtime5==1)
				{
					timedown2=4;
//					timedown-=1;
					flagtime5=0;
				}
					switch(timedown2)
					 {
						case 1: SELECT_CURRICULUM(8);Manage_Serial_Number(1);timedown2=2;flagtime6=1;break;
						case 2: SELECT_CURRICULUM(4);Manage_Serial_Number(2);timedown2-=1;break;
					 }
					keystruct.dualstick8=0;				
				}			
	}
	
//星期五:29
 if(keystruct.shortstick5==1)
 {

			timedown0=1;//上下移动的计次变量
			flagtime1=0;
			flagtime2=0;	

			timedown1=1;//上下移动的计次变量
			flagtime3=0;
			flagtime4=0;
			
			timedown2=1;//上下移动的计次变量
			flagtime5=0;
			flagtime6=0;

 	if(keystruct.shortstick5==1&&keystruct.shortstick8==1)//如果按键1按下并且8短击按下,则进行上翻操作
		{
			if(flagtime8==1)
			{
				timedown3=1;
//				timedown+=1;
				flagtime8=0;
			}
			switch(timedown3)
			{
				//课程选则2,序号处理3,电灯范围4
				case 1: SELECT_CURRICULUM(9);Manage_Serial_Number(1);timedown3++;break;
				case 2: SELECT_CURRICULUM(2);Manage_Serial_Number(2);timedown3=1;flagtime7=1;break;
			}
			keystruct.shortstick8=0;	
		}
	else
	if(keystruct.shortstick5==1&&keystruct.dualstick8==3)
		{
				if(flagtime7==1)
				{
					timedown3=4;
//					timedown-=1;
					flagtime7=0;
				}
					switch(timedown3)
					 {
						case 1: SELECT_CURRICULUM(9);Manage_Serial_Number(1);timedown3=2;flagtime8=1;break;
						case 2: SELECT_CURRICULUM(2);Manage_Serial_Number(2);timedown3-=1;break;
					 }
					keystruct.dualstick8=0;				
				}	
 }

//星期六:无
	if(keystruct.shortstick6==1)//如果按键2按下并且8短击按下,
		{		
			timedown0=1;//上下移动的计次变量
			flagtime1=0;
			flagtime2=0;
			
			timedown1=1;//上下移动的计次变量
			flagtime3=0;
			flagtime4=0;
			
			timedown2=1;//上下移动的计次变量
			flagtime5=0;
			flagtime6=0;
			
			timedown3=1;//上下移动的计次变量
			flagtime7=0;
			flagtime8=0;		
			
			SELECT_CURRICULUM(11);

		}
//星期天:10,选修课
	if(keystruct.shortstick7==1)//如果按键2按下并且8短击按下,
		{
			
			timedown0=1;//上下移动的计次变量
			flagtime1=0;
			flagtime2=0;
			
			timedown1=1;//上下移动的计次变量
			flagtime3=0;
			flagtime4=0;
			
			timedown2=1;//上下移动的计次变量
			flagtime5=0;
			flagtime6=0;
			
			timedown3=1;//上下移动的计次变量
			flagtime7=0;
			flagtime8=0;			
			 SELECT_CURRICULUM(10);
			 Manage_Serial_Number(1);	
		}
}
                                                               

此外关于课表的字符指针数组在<word1.c>中 截取一段展示,其有150个32位的二维字符数组,取每32个为一个字符,进行字符取模然后加入。

const unsigned char word1[150][32]={
//首先word[x]:表示显示的个数,即元素个数
//其次word[x][y]:表示显示的字符长度这里设置长度最长为72个hex类型的文件

//以下是课程名称及其教室:xxxx+@x-xxx
//*****************液压气压传动@2-410(0-12)****************************************//
/*--  文字:  液  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x10,0x60,0x02,0x8C,0x00,0x84,0xE4,0x1C,0x05,0xC6,0xBC,0x24,0x24,0xE4,0x04,0x00,
0x04,0x04,0x7E,0x01,0x00,0x00,0xFF,0x82,0x41,0x26,0x18,0x29,0x46,0x81,0x80,0x00,

/*--  文字:  压  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xFE,0x02,0x82,0x82,0x82,0x82,0xFA,0x82,0x82,0x82,0x82,0x82,0x02,0x00,
0x80,0x60,0x1F,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x44,0x58,0x40,0x40,0x00,

/*--  文字:  气  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x20,0x10,0x4C,0x47,0x54,0x54,0x54,0x54,0x54,0x54,0x54,0xD4,0x04,0x04,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0F,0x30,0x40,0xF0,0x00,

/*--  文字:  压  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x00,0xFE,0x02,0x82,0x82,0x82,0x82,0xFA,0x82,0x82,0x82,0x82,0x82,0x02,0x00,
0x80,0x60,0x1F,0x40,0x40,0x40,0x40,0x40,0x7F,0x40,0x40,0x44,0x58,0x40,0x40,0x00,

/*--  文字:  传  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x00,0x80,0x60,0xF8,0x07,0x40,0x48,0x48,0xE8,0x5F,0x48,0x48,0x48,0x40,0x40,0x00,
0x01,0x00,0x00,0xFF,0x00,0x00,0x02,0x0B,0x12,0x22,0xD2,0x0A,0x06,0x00,0x00,0x00,

/*--  文字:  动  --*/
/*--  宋体12;  此字体下对应的点阵为:宽x高=16x16   --*/
0x40,0x44,0xC4,0x44,0x44,0x44,0x40,0x10,0x10,0xFF,0x10,0x10,0x10,0xF0,0x00,0x00,
0x10,0x3C,0x13,0x10,0x14,0xB8,0x40,0x30,0x0E,0x01,0x40,0x80,0x40,0x3F,0x00,0x00,

 四.创意可行性分析报告

 下面展示的是使用简易流程及其优缺点概述

  •  使用简易流程: 首先人为拟定书本摆放书本顺序,将书本摆放好于9格的书本架子上,然后规定本周课程的二进制编码,输入到电脑的程序界面进行修改,然后点击程序运行,即可初始化本周的课程显示。

  • 以星期一为例子,只有数控技术编程,此时点击七个按键中从右到左数起第1颗按键,显示屏就会显示到当日第一门课,点击第八颗按键可进行上下的切换课程查看(单机向上查看/双击向下查看)。
  • 当日课程查询完毕后,长击第8颗按键即可熄灯熄屏。

  • 可行性缺点报告
  • 需要人为电脑控制每周的课程表更改,而且一旦出现bug的情况就需要检测调试,并且在硬件电路板上的电信号任然会有噪声干扰以及电路信号不稳定的情况,以后可以更合理设计电路以及绘制电路板去减少这些问题的出现。
  • 材料选型上有疏忽,黑底显示屏虽然能达到使用目的,但是显示光度不强。
  • 成本上应进一步缩进,选择更具性价比分材料进行设计。
  • 由于没有加入物联网技术,课表只能暂存至字符指针数组中,不能实时更新,后续可安排改进。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值