随便拍了几张,现在我的队友在做硬件,有些功能等硬件出来再做,现在完成的主要功能有:
1.阳历年,月,日,时,分,秒,星期,闰年,平年显示
2.农历月,日
3,生肖,节气,重要节假日显示
4.模拟时钟
5.时间设置,时间自动校准+/-8second,3个闹钟设置,分单次和每天两个模式
6.主界面是图形菜单,最多有三级菜单
7.能存贮,校准值,闹钟设置,掉电后不消失
8,温度显示
主要硬件有:1块ST7920控制器的12864,主控MCU:STC12C5A60S2,DS1302,DS18B20,4个按键
源码暂不上传,等完工后,会把视频和源码一并奉上,呵呵
上图是所有工程文件。fficeffice" />
///////////////////////////////////////////////////////////////////////////////
//变量定义
unsigned char KeyFuncIndex=0; //存放当前的菜单索引
unsigned char KEY_TYPE=0; //当前按下的键值类型
void (*KeyFuncPtr)(); //定义按键功能指针
//////////////////////////////////////////////////////////////////////////////////
//定义菜单切换链表
StatusTab code KeyTab[MENU_SIZE]=
{
{0,3,2,1,0,(*InitMenuIterface)}, //初始化主菜单界面 默认时钟
{1,7,0,2,1,(*state0)}, //主界面菜单设置
{2,2,1,0,2,(*state1)}, //主界面菜单说明
{3,5,4,4,0,(*state2)}, //时钟选择界面1
{4,6,3,3,0,(*state3)}, //时钟选择界面2
{5,5,5,5,3,(*state4)}, //数字时钟
{6,6,6,6,4,(*state5)}, //模拟时钟
{7,10,9,8,1,(*state6)}, //时间设置
{8,11,7,9,1,(*state7)}, //时间校准
{9,12,8,7,1,(*state8)}, //闹钟设置
{10,10,10,10,7,(*state9)}, //时间设置界面
{11,11,11,11,8,(*state10)}, //时间自动校准 +/-8 sec
{12,15,14,13,9,(*state11)}, //闹钟设置1菜单
{13,16,12,14,9,(*state12)}, //闹钟设置2菜单
{14,17,13,12,9,(*state13)}, //闹钟设置3菜单
{15,15,15,15,12,(*state14)}, //闹钟1设置界面
{16,16,16,16,13,(*state15)}, //闹钟2设置界面
{17,17,17,17,14,(*state16)}, //闹钟3设置界面
};
///////////////////////////////////////////////////////////////////////////////
void MenuOperate() //运行菜单
{
switch(KEY_TYPE)
{
case 1:
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyOKStatus; //确认按键
break;
case 2:
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyUpStatus; //向上按键
break;
case 3:
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyDownStatus; //向下按键
break;
case 4:
KeyFuncIndex=KeyTab[KeyFuncIndex].KeyBackStatus; //返回按键
break;
default:
break;
//此处添加按键错误代码
}
KeyFuncPtr=KeyTab[KeyFuncIndex].CurrentOperate; //下面是执行按键的操作
(*KeyFuncPtr)(); //执行当前的按键操作
}
采用上面的菜单管理所有的程序,这种架构就是那种状态机的思维,对应菜单项都有对应的操作,每次操作都会,所有的状态都是一环扣一环的,跳转很方便,每次跳转执行相应的函数,处于一种稳定的状态。如下面的函数:
///////////////////////////////////////////////////////////////////////////////
//初始化主菜单界面 默认时钟
void InitMenuIterface()
{
LCD12864PutStr(0,3,"时钟"); //写字符串函数
LCD12864DrawPicture(0,16,15,47,gImage_arrows_left,0);
LCD12864DrawPicture(112,16,127,47,gImage_arrows_right,0);
LCD12864DrawPicture(16,16,47,47,gImage_set,0);
LCD12864DrawPicture(48,16,79,47,gImage_timer,1);
LCD12864DrawPicture(80,16,111,47,gImage_explanation,0);
LCD12864PutStr(3,3,"选择"); //写字符串函数
while(1)
{
KEY_TYPE = KeyScan();
if((KEY_TYPE!=0)&&(KEY_TYPE!=4))
{
WriteCom(CLEAR_DDRAM); //清楚DDRAM
CLEAR_GDRAM(); //清楚GDROM如果不清除会出现花屏
break; //无按键或者,按下返回键则 都无效,处于等待状态!
}
}
}
上面使用while(1)的原因是因为上面只要执行一次的,当接受到按键消息的时候立即作出相应的处理,跳入到下一个状态。一环扣一环,当我加入闹钟功能的时候就比较蛋疼了,闹钟需要不断的实时检测,不向STM32那样自带的闹钟中断,我只能把闹钟检测加入到所有的状态中去了。不知道各位兄弟有什么比较好的办法没。还有我基本上把所有的状态都添加到了menu_function这个文件中去了,似乎也不太合理。程序过于庞大,都超过1500行了。但是再放到其他的文件当中又怕过于凌乱,以后检查菜单跳转又不怎么方便。
题外话:本来打算用STM32做一个大型的带GUI的项目,硬件,基本上准备好了,就差一个能够综合所有东西的架构了。这次电赛,题目不是很难,基本上上面的这种架构就可以满足系统的要求了,可是对于STM32如何组织起来,结构更加合理,我还是一脸茫然。
|