模仿NWatch的手表主界面

创建日期结构体

#ifndef __DRIVER_DATE_H
#define __DRIVER_DATE_H

#include <stdint.h>
#include <stdbool.h>

typedef struct{
	uint8_t x;		
	uint8_t y;
	uint8_t font;
	uint8_t w;		
	uint8_t h;
	uint8_t offset;		
	uint8_t val;
	uint8_t maxval;
	bool moving;
}tickerData_t;

typedef struct{
	uint8_t secs;		
	uint8_t mins;
	uint8_t hour;
	char ampm;
}time_s;

typedef enum{
	DAY_MON = 0,
	DAY_TUE = 1,
	DAY_WED = 2,
	DAY_THU = 3,
	DAY_FRI = 4,
	DAY_SAT = 5,
	DAY_SUN = 6,
}day_t;

typedef enum{
	MONTH_JAN = 0,
	MONTH_FEB = 1,
	MONTH_MAR = 2,
	MONTH_APR = 3,
	MONTH_MAY = 4,
	MONTH_JUN = 5,
	MONTH_JUL = 6,
	MONTH_AUG = 7,
	MONTH_SEP = 8,
	MONTH_OCT = 9,
	MONTH_NOV = 10,
	MONTH_DEC = 11
}month_t;
	
typedef struct{
	day_t day;		
	uint8_t date;
	month_t month;
	uint8_t year;
}date_s;

typedef struct{
	time_s time;
	date_s date;
}timeDate_s;

void drawDate(void);

void ticker(void);

#endif

初始化并通过定时器中断来更新secs

timeDate_s timeDate = {{30,20,15},{2,23,1,24}};
void Timer2Callback(TIM_HandleTypeDef *htim)
{
  if(htim->Instance == TIM2){
  		mills++;
		if(mills%1000 == 0){
			timeDate.time.secs = (timeDate.time.secs+1)%60;
		}
  	}
}

当secs发生改变,让相应改变的时间进行改变

向上滚动

#include "drivers.h"
#include "watch.h"
#include "oleddata.h"

#include <string.h>
#include <stdint.h>
#include <stdbool.h>

timeDate_s timeDate = {{30,20,15},{1,14,2,23}};

static void drawTickerNum(tickerData_t *data);

void drawDate(){
	char day[BUFFSIZE_STR_DAYS];
    strcpy(day,days[timeDate.date.day]);
    
    char month[BUFFSIZE_STR_MONTHS];
    strcpy(month,months[timeDate.date.month]);
    
    char buff[BUFFSIZE_DATE_FORMAT];
    sprintf(buff,PSTR(DATE_FORMAT),day,timeDate.date.date,month,timeDate.date.year);
	OledPrintf(0, 0, OLED_16X8, buff);
}

void ticker(void){
	static uint8_t yPos;
	static uint8_t yPos_secs;
	static bool moving = false;
	static bool moving2[5] = {0};

	static uint8_t secs = 30;
	static uint8_t mins = 20;
	static uint8_t hour = 15;
	if(timeDate.time.secs != secs){
		yPos = 0;
        yPos_secs = 0;
		moving = true;

		moving2[0] = (timeDate.time.secs/10)!=(secs/10);
		if(moving2[0] && (secs/10==5)){
			timeDate.time.mins = (timeDate.time.mins + 1)%60;
		}
		moving2[1] = (timeDate.time.mins%10)!=(mins%10);
		moving2[2] = (timeDate.time.mins/10)!=(mins/10);
		if(moving2[2] && (mins/10==5)){
			timeDate.time.hour = (timeDate.time.hour + 1)%24;
		}
		moving2[3] = (timeDate.time.hour%10)!=(hour%10);
		moving2[4] = (timeDate.time.hour/10)!=(hour/10);
		if(moving2[4] && (hour/10==2)){
			//
		}
		
		secs = timeDate.time.secs;
		mins = timeDate.time.mins;
		hour = timeDate.time.hour;
	}

	if(moving){
		if(yPos <= 3){
			yPos++;
		}else if(yPos <= 6){
			yPos+=3;
		}else if(yPos <= 16){
			yPos+=5;
		}else if(yPos <= 22){
			yPos+=3;
		}else if(yPos <= MIDFONT_HEIGHT){
			yPos++;
		}

		if(yPos >= MIDFONT_HEIGHT){
			yPos = 255;
		}

		if(yPos_secs <= 1){
			yPos_secs++;
		}else if(yPos_secs <= 13){
            yPos_secs+=3;
        }else if(yPos_secs <= SMLFONT_HEIGHT){
            yPos_secs++;
        }

		if(yPos_secs > SMLFONT_HEIGHT){
			yPos_secs = 255;
		}
		
		if( (yPos > MIDFONT_HEIGHT) && (yPos_secs > SMLFONT_HEIGHT) ){

			yPos = 0;
			yPos_secs = 0;
			moving = false;
			memset(moving2,0,sizeof(moving2));
		}
	}

	tickerData_t data;

    //秒
	data.y = 24;
	data.w = SMLFONT_WIDTH;
	data.h = SMLFONT_HEIGHT;

	data.x = 80;
	data.val = timeDate.time.secs/10;
	data.maxval = 5;
	data.moving = moving2[0];
	data.offset = yPos_secs;
	data.font = OLED_24X16;
	drawTickerNum(&data);

	data.x = 96;
	data.val = timeDate.time.secs%10;
	data.maxval = 9;
	data.moving = moving;
	data.offset = yPos_secs;
	drawTickerNum(&data);

	data.y = 16;
	data.w = MIDFONT_WIDTH;
	data.h = MIDFONT_HEIGHT;
    //分
    data.x = 64;
	data.val = timeDate.time.mins%10;
	data.maxval = 9;
	data.moving = moving2[1];
	data.offset = yPos;
	data.font = OLED_32X16;
	drawTickerNum(&data);
    
    data.x = 48;
	data.val = timeDate.time.mins/10;
	data.maxval = 5;
	data.moving = moving2[2];
	data.offset = yPos;
	drawTickerNum(&data);
    
    //时
    data.x = 16;
	data.val = timeDate.time.hour%10;
	data.maxval = 9;
	data.moving = moving2[3];
	data.offset = yPos;
	drawTickerNum(&data);
    
    data.x = 0;
	data.val = timeDate.time.hour/10;
	data.maxval = 5;
	data.moving = moving2[4];
	data.offset = yPos;
	drawTickerNum(&data);
    
    if(timeDate.time.secs%2 == 0){
        OledShowImage(32, 16,MIDFONT_WIDTH,MIDFONT_HEIGHT,OLED_F32X16[10*4],0);
    }else{
        OledShowImage(32, 16,MIDFONT_WIDTH,MIDFONT_HEIGHT,OLED_F32X16[11*4],0);
    }
}

static void drawTickerNum(tickerData_t *data){
	if(!data->moving || data->offset == 0 || data->offset == 255 ){
		if(data->font == OLED_24X16){
			OledShowChar(data->x, data->y, data->val*3, OLED_24X16);
		}else{
			OledShowChar(data->x, data->y, data->val*4, OLED_32X16);
		}
	}else{
		uint8_t prev = data->val - 1;
		if(prev == 255){
			prev = data ->maxval;
		}

		if(data->font == OLED_24X16){
			OledShowImage(data->x, data->y,data->w,data->h,OLED_F24X16[data->val*3],data->offset-SMLFONT_HEIGHT);
			OledShowImage(data->x, data->y,data->w,data->h,OLED_F24X16[prev*3],data->offset);
		}else{
			OledShowImage(data->x, data->y,data->w,data->h,OLED_F32X16[data->val*4],data->offset-MIDFONT_HEIGHT);
			OledShowImage(data->x, data->y,data->w,data->h,OLED_F32X16[prev*4 ],data->offset);
		}
	}

}

主函数中循环调用

该程序是在FreeRTOS下编写 在裸机中也可以正常使用在主函数中使用while()循环即可

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  DataInit();
  unsigned int count = 10;
  OledInit();
  TimerInit(&htim2);
  for(;;)
  {
  		drawwatch();
		OledUpdate();
		OledClear();

  }
  /* USER CODE END StartDefaultTask */
}

效果展示

手表主界面

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葛霸霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值