首页 > 编程语言 >PotatoWatch-可编程手表

PotatoWatch-可编程手表

时间:2023-01-16 17:11:42浏览次数:43  
标签:case 界面 Opera 手表 break 任务 编号 可编程 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.电脑点击烧录
    • 看到百分号进度条才能把手松开
    • 等待程序下载完成

   

标签:case,界面,Opera,手表,break,任务,编号,可编程,PotatoWatch
From: https://www.cnblogs.com/polaris07/p/17055867.html

相关文章

  • 可编程逻辑器件PLD基本结构
    可编程逻辑器件PLD(ProgrammableLogicDevice)分类①基于乘积项的PLD结构:根据逻辑函数的乘积项展开的②基于“查找表LUT”的PLD结构:以存储器方式将逻辑函数的真值表存储......
  • EP2AGX45CU17I5G IC FPGA现场可编程门阵列规格参数
    ArriaIIGX低功耗6G收发器FPGA切实降低了成本和功耗,为基于6G收发器的应用提供更强的功能。40-nmArriaII系列含有成本最低的6.375-Gbps收发器FPGA,静态功耗比竞争......
  • 可编程中断控制器
    可编程中断控制器8259A8259A内部寄存器ICW1寄存器ICW2寄存器ICW3寄存器ICW4寄存器OCW1寄存器OCW2寄存器OCW3寄存器参考资料可编程中断控制器在x86中,外部......
  • 305-基于XC7Z020的AI 人工智能 可编程相机
     基于XC7Z020的AI人工智能可编程相机   一、产品概述   本产品为一款基于FPGAsoc的支持二次开发的智能相机平台,基于大量已有的图形......
  • 可编程 USB 转串口适配器
    概述可编程USB转UART/I2C/SMBus/SPI/CAN/1-Wire适配器USB2S(USBToSerialports)是多种数字接口物理层协议转发器,自带强大灵活的S2S协议固件程序,支持嵌入C语言程序开发,可实现......
  • XC5VLX30T-2FF323I(XC5VLX30T-1FF323C) FPGA Virtex-5 LXT可编程器件
    概述Virtex-5FPGA有-3,-2,-1速度等级,其中-3具有最高的性能。Virtex-5FPGA直流和交流特性指定为商业和工业级别。除工作温度范围外,除非另有说明,所有直流和交流电气参数对于......
  • 开发调试工具:USB转IIC/I2C/SPI/UART适配器模块可编程开发板
    开发调试工具:USB转IIC/I2C/SPI/UART适配器模块可编程开发板 发个方便测试I2C、SPI、1Wire接口的工具模块总的思路是通过USB或者UART接口发送一些协议字符串,由模块转换......
  • 可编程渲染管线(Scriptable Render Pipeline, SRP)
    原文链接可编程渲染管线处理数据的流程可分为以下3大阶段1.应用阶段这个阶段大概会由CPU处理4件事情。首先会对模型数据进行可见性判断。模型数据由顶点位置、法线方......
  • OLED_mini_手表
    esp32OLED_mini手表实际效果https://www.bilibili.com/video/BV16t4y1M758/代码#include"Wire.h"#include"SSD1306.h"#include<WiFi.h>#include<TimeLib.h>......
  • 力扣(leetcode) 401. 二进制手表(枚举)(奇妙思路循环)
    题目在这:​​https://leetcode-cn.com/problems/binary-watch/​​题目分析:用通俗易懂的语言解释一下题目的意思。上面一行是小时。下面一行是分钟。拿题目给的图解释......