当用户点击复位按钮时,系统调用SecCounter_Init函数、small_time_clear函数将所有的时间记录清零,按钮的状态也会复位。
当用户在没有复位的情况下退出秒表程序时,系统不会将秒表的时间清除,而是在中断服务函数中,继续计时。因此就达到了后台运行的目的。
主要用到的函数如下:
void TIM_Configuration(void);//定时器配置 void NVIC_Configuration(void);//定时器中断配置 u8 State2_Stopwatch(void);//秒表状态 void small_time_clear(void);//相对时间清零
void big_time_save(void);//总时间暂存,用于计算相对时间 void SecCounter_Init(void);//复位函数,把时间以及标志位清零 详细代码参见附录二。 5.5.3画板
画板功能提供红、橙、黄、绿、蓝、靛、紫、黑一共八种颜色可选,系统默认画笔颜色为黑色,提供橡皮功能供用户擦除颜色,以及清除功能可以将画板的整个全部清理成白色。主要实现方法如下:
在主界面下点击画板图标,此时系统会检测到触摸屏有按键按下,在按键松开后系统会自动跳转到画板界面,此时系统会首先加载UI界面并且在while循环中不断检测按键的状态,系统在按钮区域和画板区域采用两种不同的扫描方式,在画板区域用户按下触摸屏时系统随即用TP_Draw_Big_Point函数在按下的点填充颜色,并不会等到用户抬起手时再执行下一步动作,以此保证了画笔画图的连贯性,当用户点击的区域为按钮区域时,系统将等待用户松开手时再进行下一步操作,以防止用户按下按键一次系统多次操作。
当用户点击取色按钮时系统调用GUI_RectangleFill函数加载颜色图标并且利用WHILE循环不断检测用户的按键状态,当用户按下某个颜色时系统调用get_color函数将画笔的颜色赋给变量POINT_COLOR。画笔颜色其实是用RGB值表示的,当确定要用什么颜色时,查找RGB值表,一般RGB值为24位,但是本系统的LCD模块采用16位色, RGB位数分别为5:6:5,因此,要对24位的RGB值进行四舍五入。
当用户点击橡皮时系统会调用GUI_RectangleFill函数画填充矩形,我将此
- 29 -
函数的颜色参数设置为白色,与画板的背景颜色一致,当用户点击画板区域时会在以触点为左上顶点长宽分别为16个像素点的区域内填充白色,以此将之前画的颜色覆盖掉。当用户点击清除按钮时,系统再次调用GUI_RectangleFill函数画一个大小与画板区域的大小一样的矩形,在这个函数中仍然将颜色设置为白色,因此整个画板区域就被填充成了白色,实现了清除画板的功能。
主要用到的函数如下:
u8 State4_Drawing_Board(void);//画板状态函数 u8 drawing_board_tp_scan(void);//画板按键扫描函数 u32 get_color(void);//颜色获得函数 void LCD_Clear(u16 color);//LCD清屏函数
void GUI_RectangleFill(uint32 x0, uint32 y0, uint32 x1, uint32 y1, TCOLOR color);//画填充矩形函数
void Draw_Text(u32 x, u32 y, u16 backColor,u16 color, unsigned char *chs, u8 size, u8 mode);//显示字体、字符函数
u8 Is_In_Area(u16 x1,u16 y1,u16 x2,u16 y2);//触摸笔区域判断函数 u8 TP_Scan(u8 tp);//触摸笔坐标获得函数 详细代码参见附录二。 5.5.4闹钟
本系统闹钟设计最多可以提供八个,闹钟时间发生过以后系统自动将其清除 并且闹钟的数据掉电不丢失,开机后自动检测闹钟数据。主要实现方法如下: 在主界面的状态下用户点击闹钟按钮,此时系统会检测到用户按下了闹钟按钮,你用户松开手后,系统自动跳转到闹钟状态。进入到闹钟状态后,系统首先加载UI界面,然后系统会调用I2C_Gets函数读取EEPROM中的闹钟信息。闹钟信息放在以闹钟基地址clock_save_base_add为起始的8个扇区,每个闹钟信息使用一个扇区,然后我定义了一个二维数组alarm_save[8][7]来保存闹钟数据,每个闹钟数据占七个字节,第一个字节存放闹钟标志位,当标志位为‘1’时,说明此闹钟还未响过,当标志位为‘0’时,说明此闹钟已经响过。在读取EEPROM中的闹钟数据后同通过检测这个标志位来筛选哪些闹钟已经响过,具体程序如下:
for(j=0;j<8;j++)
- 30 -
{
if(alarm_save[j][0]==1) {
second_save[k]=mktimev_alarm(&alarm_save[j][0]); k++; } }
其中mktimev_alarm函数将年月日信息转化秒钟以便比较闹钟的次序。然后系统调用bubble_alarm函数对这些时间进行冒泡排序并调用alarm_init函数取最小的时间存入RTC的闹钟寄存器并且把这个时间存在EEPROM的
alarm_OpenMachine_base_add地址用于开机初始化闹钟。随后系统将未响过的闹钟数据显示在LCD屏上并显示删除按钮。当系统检测不到EEPROM中有闹钟数据时则在屏幕中间打印无闹钟。此时是不会显示删除按钮的。然后系统会进入while循环不断检测按钮的状态,具体代码如下:
while(1)
{ if(TPEN()==0) {
TP_Scan(0);//获取AD转换后的物理坐标值 while(!TPEN()); //松手检测
if(Is_In_Area(0,280,60,315)&&k<8)//点击了添加按钮 {
clock_set(); //闹钟设定函数 return 1; }
if(Is_In_Area(90,280,150,315)&&k!=0)//点击了删除按钮 {
clock_delate(); return 1; }
if(Is_In_Area(180,280,235,315))//点击了返回按钮 {
return 6; //返回主界面
- 31 -
} }
}
当用户点击了添加按钮时系统跳转到添加界面,首先加载界面以及按钮这些基本元素,然后系统进入while循环检测用户的按键状态。当用户输入闹钟时间后系统将输入的按键值存入数组keystore[MAX_KEY_NUM],其中
MAX_KEY_NUM是一个宏定义用来标记输入数字数目的最大值。系统不断检测数组中的按键值并实时地打印在屏幕上。当用户输入的时间到达MAX_KEY_NUM时点击确定按钮,系统会调用RTC_GetCounter函数、mktimev_alarm函数、time_judge函数对时间的合法性、时效性进行判断,具体代码如下:
if(time_judge(&alarm_change[1])&&(mktimev_alarm(alarm_change1)-8*60*60>RTC_GetCounter( )) )
{ do
{ I2C_Gets(0xA0,clock_save_base_add+i*8,1,&data_save); i++;} while(data_save!=0); } 当判断结果符合要求时则调用I2C_Puts把这个时间存入EEPROM保存起来。当时间设置成功后则打印“设置成功!!!”。如果输入的时间的合法性与时效性任意一个不符合要求时,则打印“设置失败,请重新设置!!!”,并且重新调用时间设置函数。
用户点击删除按钮时,系统自动在每一个闹钟时间的后边加载删除按钮,当用户按下了某个时间的删除按钮时,系统则将这个时间与EEPROM中的保存的闹钟时间进行匹配,将匹配到到的闹钟信息的标志位由‘1’修改为‘0’系统就检测不出来这个时间了。
当用户点击返回按钮时,系统自动跳转到桌面状态。 此功能用到的函数主要如下: void clock_set(void); //闹钟设置
u8 State1_Clock(void); //闹钟状态界面与检测 void clock_delate(void); //闹钟删除函数 u8 clock_delate_tp_scan(void); //删除闹钟时按键扫描 u32 mktimev_alarm(u8 *tm); //把公历时间转化为秒数
- 32 -
void bubble_alarm(u32 x[],int n); //冒泡排序算法
void to_tm_alarm(u32 tim, u8 * tm); //把秒钟时转化为年月日
void RTC_display_lcd_alarm(u32 x,u32 y,u32 backColor,u32 color,u8 size,u8 mode,u8*tm ); //LCD显示闹钟的年月日
void RTC_display_lcd2_alarm(u32 x,u32 y,u32 backColor,u32 color,u8 size, u8 mode,u8*tm ); //LCD显示闹钟的时分秒
void eeprom_alarm_init(void); //EEPROM初始化 u8 time_judge(u8 *tp); //判断时间的合法性 void alarm_init(u32 alarm_value_load); //闹钟初始化 void alarm_OpenMachine_init(void); //闹钟开机初始化 void time_flag_clear(void); //闹钟时间标志位清除 详细代码参见附录二。 5.5.5 计步
当今人们对健康问题越发关注,计步器作为一种颇受欢迎的日常锻炼进度监控器,已经成为穿戴式设备的标配。本系统设计的计步器开机后自动启动运行,它可以记录用户的行走步数并且可以后台运行,为了正确的反映用户行走的步数,它只能在零点零分零秒由系统自动清零,即一天结束时清零。此计步器可以工作在两种模式:
模式一:可以记录一天用户行走的总步数,只能由系统清零。
模式二:可以记录用户从A地到B地的行走总步数。且可以由用户手动清零。
主要实现方法如下:
首先在系统初始化时调用函数MPU_Init、mpu_dmp_init、CountStepInit对MPU6050、DMP进行初始化。开机之后,系统自动调用MPU_Get_Accelerometer函数获得MPU6050采集的加速度值、并且调用CountStep函数记录用户的步数,而不需要用户的干预。
当用户点击主屏幕上的计步按钮时,系统自动跳转到计步界面,把当前计步器记录的步数输出在屏幕上。这里定义了一个全局变量StepCount用来记录用户的步数。因此无论系统当前处于什么状态,都能记录用户的步数,并保存在变量StepCount中。
- 33 -