PotatoWatch-可编程手表

 

-项目概述-

  我需要一块手表,可自定义开发,可以编程,可以玩游戏,可以接收消息,可以规划日程,还有就是不要丢掉初心:时间日期显示是一个手表基本功能......当然了,最重要是装逼。

  • Microsoft ToDo 日程规划API调用,可与手机结合规划日程。
  • 动态显示天气信息。(说实话,咱界面设计还是拿的出手的)
  • 尝试移植ArduBoy游戏库。
  • 三级界面菜单逻辑设计。
  • 拨轮编码器驱动编写。
  • 屏幕驱动板设计。
  • 4层PCB设计。
  • 外壳设计。

-成品预览-

 

-项目框架-

  STC-8G因为接口比ESP-M2多很多,所以选择STC作为外设控制以及端口引出,ESP-M2作为主控,处理消息以及获取网络信息。

  项目导图如下:

  

 

-硬件资料,代码-

主框架逻辑:

 1 /*********************************************
 2  * 创建一个结构体
 3  * 存放界面标志位
 4 */
 5 typedef struct
 6 {
 7     u8 Interface_Mark;     //界面状态
 8     u8 Task_Mark;          //任务状态
 9     u8 Run_Task;           //开始运行任务
10 } Mark;
11 Mark Mark_Sign;//状态标志位
12 
13 /*********************************************
14  * 创建一个枚举
15  * 存放界面变量
16 */
17 enum
18 {
19     Main_Interface = 0x10, /****主界面*****/
20     Menu_Interface = 0x20, /****菜单界面***/
21     Task_Interface = 0x30, /****任务界面***/
22 };
23 
24 
25 switch(Mark_Sign.Interface_Mark)
26 {
27     //状态标志位 主界面
28     case Main_Interface:
29         Main_Interface_APP();//显示主界面
30     break;
31 
32     //状态标志位 菜单界面
33     case Menu_Interface:
34         Menu_Interface_APP();//显示菜单界面
35     break;
36     case Task_Interface:
37             Function_Menu_APP();//显示功能界面
38     break;
39 default:
40     break;
41 }
42 
43 
44 // 每个篮框定义一个结构体存放:起始x,y,长和宽,图像指针
45 void Main_Interface_APP()
46 {
47     // 时间显示
48     
49     // 日期显示
50     
51     // 图标显示
52     
53     // 气温,CO2显示
54 }
55 
56 // 每个菜单选项具有独立的 1.位号,2.标题,3.图标指针
57 struct Table
58 {
59     unsigned char tab_num;
60     char *title;
61     BMP_Ptr *ptr;
62 }
63 
64 // 菜单选项管理器:1.子项个数,3.当前选项指针,4.菜单项数组
65 struct Menu_argument
66 {
67     Table Tab_array[t_size];
68     char t_size;
69     unsigned char *Tab_current;
70 }
71 
72 // 屏幕初始化时,创建菜单管理器
73 // for循环加载各个菜单子项(位号,标题, 图标指针)进入菜单管理器
74 
75 
76 // 图像管理集:专门存放图像的文件,统一使用一个图像指针数组进行管理
77 
78 void Menu_Interface_APP() //显示菜单选项界面
79 {
80     // 绘制隔断线
81     
82     for(i = 0; i < 3; i++)
83     {
84         // 1.绘制第一栏
85         
86         // 2.绘制第二栏(指定为当前指针栏居中,字体放大一号)
87         
88         // 3.绘制第三栏
89         
90     }
91     // 当前指针栏指示符号绘制
92     
93     // 当前指针栏图标加载绘制
94 }

 

 滚轮操作检测逻辑:

 u8 Opera_array[OPERA_NUM];
 这是一个操作队列数组,用来存储51发送过来的操作数据的
bool Busy_flag;
这是繁忙标志,当程序正在执行当前任务时,就不会读取下一个操作数。
实操代码:
#pragma once
#define SCAN_T_MS 10
#define OPERA_NUM 10

enum KEY_VALUE
{
    KEY_FORWARD = 0xA0,  // 滚轮前滚
    KEY_BCKWARD = 0xB0,  // 滚轮后滚
    KEY_UP = 0xC0,         // 滚轮上弹
    KEY_DOWN = 0xD0,     // 滚轮按下
};


// 定义操作结构体:操作数,忙标志,操作队列数组,当前操作数指针
typedef struct
{
    // 有效操作数存在标志
    bool Opera_have_flag;
    // 操作繁忙标志
    bool Busy_flag;
    // 当前队列操作数个数
    u8 Opera_Current_num;
    // 操作队列当前值
    u8 Opera_Current_value;
    // 操作队列数组
    u8 Opera_array[OPERA_NUM];

}Opera_argument;
Opera_argument KeyArgument;


// 按键操作数初始化
void Init_KeyScan()
{
    // 所有值清0
    KeyArgument.Opera_have_flag = 0;
    KeyArgument.Busy_flag = 0;  // 默认不繁忙
    KeyArgument.Opera_Current_num = 0;
    for (int i = 0; i < OPERA_NUM; i++)
    {
        KeyArgument.Opera_array[i] = 0;
    }
}

// 定时按键扫描函数:
void Key_Scan()
{    
    // 有效操作数是否存在
    if (KeyArgument.Opera_Current_num != 0)
    {
        // 当前是否存在操作繁忙
        if (KeyArgument.Busy_flag != 1)
        {
            // 操作数赋值给主函数,繁忙标志开启
            KeyArgument.Opera_Current_value = KeyArgument.Opera_array[0];
            KeyArgument.Busy_flag = 1;
            Serial.println("in_scan");
            // 当前值置零,数组整体前移,当前队列操作个数-1
            // KeyArgument.Opera_array[0] = 0;
            for (int i = 0; i < OPERA_NUM; i++)
            {
                KeyArgument.Opera_array[i] = KeyArgument.Opera_array[i + 1];
            }
            KeyArgument.Opera_Current_num--;
        }
    }    
}

 

 三级菜单界面切换逻辑:

 1 //按键滚轮一共会产生以下几种触发状态
 2 /*
 3  * 1.滚轮前滚
 4  * 2.滚轮后滚
 5  * 3.滚轮按下
 6  * 4.滚轮按下前滚
 7  * 5.滚轮按下后滚
 8  * 6.滚轮长按
 9  */
10 
11 // 中断程序操作伪代码
12 if(触发操作 == 滚轮按下)
13 {
14     if(息屏 == 当前屏幕状态)
15     {
16         当前屏幕状态 = 主界面;
17     }
18     else if(主界面 == 当前屏幕状态)
19     {
20         当前屏幕状态 = 菜单界面;
21     }
22     else if(菜单界面 == 当前屏幕状态)
23     {
24         当前屏幕状态 = 任务界面;
25         
26         switch(当前带单界面任务编号)
27         {
28             case 任务编号1:
29             即将执行任务编号 = 当前带单界面任务编号;break;
30             case 任务编号2:
31             即将执行任务编号 = 当前带单界面任务编号;break;
32             case 任务编号3:
33             即将执行任务编号 = 当前带单界面任务编号;break;
34             case 任务编号4:
35             即将执行任务编号 = 当前带单界面任务编号;break;
36             default:break;
37         }
38     }
39     else if(任务界面 == 当前屏幕状态)
40     {
41         switch(即将执行任务编号)
42         {
43             case 任务编号1:
44             break;
45             case 任务编号2:
46             break;
47             case 任务编号3:
48             break;
49             case 任务编号4:
50             break;
51             
52         }
53     }
54 }
55 else if(触发操作 == 滚轮滚动)
56 {
57     // 仍然判断当前屏幕状态
58     if(息屏 == 当前屏幕状态)
59     {
60         当前屏幕状态 =主菜单;
61     }
62     else if(主菜单 == 当前屏幕状态)
63     {
64         // 无操作响应
65     }
66     else if(菜单界面 == 当前屏幕状态)
67     {
68         // 定义滚动方向变量(0):上滚变量赋值-1;下滚变量赋值+1
69         
70         // 菜单当前主任务指示指针+滚动方向变量
71         
72         // 滚动操作变量复位0
73     }
74     else if(任务界面 == 当前屏幕状态)
75     {
76         // 定义滚动方向变量(0):上滚变量赋值-1;下滚变量赋值+1
77         switch(任务序号)
78         {
79             case 任务编号1:
80             // 1.编号1任务子选项指针,加滚动方向变量
81             break;
82             case 任务编号2:
83             // 1.编号2任务子选项指针,加滚动方向变量
84             break;
85             case 任务编号3:
86             // 1.编号3任务子选项指针,加滚动方向变量
87             break;
88             case 任务编号4:
89             // 1.编号4任务子选项指针,加滚动方向变量
90             break;
91             
92         }
93     }
94 }

项目全部文件:

个人博客下方私信领取

http://potatoworld.top:5800/

 

 -项目槽点-

  • 画了三年板子了,还是把RX与TX画反了......(自抽三巴掌)
  • 重要的事情说三遍,for(int i = 0; i < 3; i++){  cout << "ESP系列的模块一定要独立电源供电,否则运行不了";  }  我就是直接在板子上用了两块AMS1117,一块专门给ESP-M2
  • ESP模块下载程序的时候,有个细节:
    • 1.先关电源  
    • 2.在断电模式下,FLASH键接地(我是直接按住FLASH按钮接地)
    • 3.开启电源,注意!!!FLASH此时仍然需要持续按住(接地),此时ESP-M2已经工作再FLASH下载模式了
    • 4.电脑点击烧录
    • 看到百分号进度条才能把手松开
    • 等待程序下载完成

   

posted @ 2023-01-16 17:04  北極星  阅读(125)  评论(0编辑  收藏  举报