STM32上实现类似iPhone的解锁和滑屏功能,emwin这个库官方的文档中控件没有一样的,但是有一个上下滑动的,基本上能够完成大致上的功能,但是如果想使用emwin实现类似的效果的话,需要懂这些知识点:
1、内存设备的使用
2、窗口的建立和消息
3、总之需要熟悉这个库的使用
由于本次测试中没有使用到外部SRAM,使用的单一的内部RAM,所以壁纸没有使用内存缓存下来,使用的单调色,基本上还算比较流畅,下面是代码正文,有兴趣的朋友可以参考下。
下面是我自己做的效果视频:
STemwin 实现滑动解锁 翻转主页
摇杆界面的控制视频
主页代码
/*********************************************************************
* *
* SEGGER Microcontroller GmbH & Co. KG *
* Solutions for real time microcontroller applications *
* *
**********************************************************************
* *
* C-file generated by: *
* *
* GUI_Builder for emWin version 5.32 *
* Compiled Oct 8 2015, 11:59:02 *
* (c) 2015 Segger Microcontroller GmbH & Co. KG *
* *
**********************************************************************
* *
* Internet: www.segger.com Support: support@segger.com *
* *
**********************************************************************
*/
// USER START (Optionally insert additional includes)
// USER END
#include "DIALOG.h"
#include "GUI_app/gui_thread.h"
#include "GUI.h"
#include "LCD/lcd.h"
#include "config.h"
/*********************************************************************
*
* 注意
* 1、所有图标必须是正方形
*
**********************************************************************
*/
/*********************************************************************
*
* user config
*
**********************************************************************
*/
#define MAIN_PAGE_SMILE_ICON_Y0 (LCD_ysize/2-STATUS_BAR_HEIGHT) //笑脸图标的中心点Y方向
#define VIEW_ICON_BK_COLOR 0x00FFC880
#define ICON_BAR_BK_COLOR 0x00F0e6c8
#define ICON_SELECTED_COLOR (0x22uL<<24)|GUI_LIGHTBLUE
/********VIEW_ICON********/
//锁定画面尺寸定义
#define VIEW_ICON_RATE 0.72f //解锁条在界面的比例位置
#define VIEW_ICON_X 0
#define VIEW_ICON_Y STATUS_BAR_HEIGHT //滑动图标区的Y起点
#define VIEW_ICON_XSIZE (LCD_xsize-VIEW_ICON_X)
#define VIEW_ICON_YSIZE (int)((LCD_ysize-VIEW_ICON_Y)*VIEW_ICON_RATE)
#define VIEW_SCREEN_YSIZE (LCD_ysize-VIEW_ICON_Y) //主页的Y尺寸
//显示控制参数
#define VIEW_ICON_POSITIONING_VALUE 6 //复位定位值
#define VIEW_ICON_REFRESH_RATE 5 //主页VIEW_ICON更新率
//图标和主页数量
#define MAIN_PAGE_NUM 2 //主页的数量
#define ICON_NUM_X 3 //每行图标个数
#define ICON_NUM_Y 3 //每列图标个数
#define ICON_X_INTERVAL 10 //每行图标间隔
#define ICON_Y_INTERVAL 10 //每列图标间隔
#define ICON_NUM (ICON_NUM_X*ICON_NUM_y) //单页支持的最大图标数量
#define VIEW_ICON_EDGE_XSIZE 0 //图标被选中后的边框距离,单位像素
#define VIEW_ICON_EDGE_YSIZE 4 //图标被选中后的边框距离,单位像素
#define TEXT_EDGE_SIZE 2 //文本和位图间距,单位像素
#define VIEW_ICON_TEXT_OFFSET 2 //文本偏移
#define TEXT_FONT GUI_FONT_6X8_ASCII //使用字体
//调试
#define VIEW_DEBUG 0
/********ICON_BAR********/
#define ICON_BAR_X 0
#define ICON_BAR_Y (VIEW_ICON_Y+VIEW_ICON_YSIZE) //图标条的Y起点,相对于LCD
#define ICON_BAR_XSIZE (LCD_xsize-ICON_BAR_X)
#define ICON_BAR_YSIZE (LCD_ysize-ICON_BAR_Y)
#define ICON_BAR_OUTSIDE_INTERVAL 30 //图标区域X间距
#define ICON_BAR_MIDDLE_INTERVAL 10 //图标区域X间距
#define ICON_BAR_Y_INTERVAL 10 //图标区域y间距
#define ICON_BAR_REFRESH_RATE 1000 //主页 ICON_BAR 更新率
#define ICON_BAR_ICON_NUM_X 3 //行个数
#define ICON_BAR_ICON_NUM_Y 1 //列个数
#define ICON_BAR_TEXT_EDGE_SIZE 2 //文本和位图间距,单位像素
#define ICON_BAR_TEXT_OFFSET -1 //文本偏移
#define ICON_BAR_EDGE_SIZE 2 //图标被选中后的边框距离,单位像素
//行为相关
#define MOVE_TRIGGER_DISTANCE 10 //判定为触摸移动的距离,单位像素
/*********************************************************************
*
* variables
*
**********************************************************************
*/
//函数声明
static void clean_icon_view(void);
static void clean_icon_bar(void);
static void clean_all_icon_flag(void);
static void init_all_mainpage(void);
static void init_mainpage(void);
WM_HWIN CreateTips(void);
//图标位图
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_appstore;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_calculator;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_calendar;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_camera;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_clock;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_compass;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_menssages;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_music;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_phone;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_photos;
extern GUI_CONST_STORAGE GUI_BITMAP bmiconview_weather;
//背景位图
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_smile;
//_icon图标对象表示的是包含位图和文本的所有区域
//由于都是使用GUI等接口进行绘制图形,如果使用窗口管理器,在哪个窗口绘制就是坐标系就是这个窗口原点。
struct _icon {
//变量
unsigned char flag; //图标状态,1:被选择 2:被双击
signed short icon_x; //图标左上角点x坐标,
signed short icon_y; //图标左上角点y坐标
unsigned short icon_xsize; //图标x尺寸
unsigned short icon_ysize; //图标y尺寸
signed short text_y; //文本区域左上角点y坐标,包含位图和文本间距
signed short text_c_x; //文本区域中心点x坐标
signed short text_h_y; //文本区域顶点Y坐标
signed short bitmap_x; //位图区域左上角点x坐标
signed short bitmap_y; //位图区域左上角点y坐标
unsigned short bitmap_xsize; //位图区域x尺寸,起点和图标一致
unsigned short bitmap_ysize; //位图区域y尺寸
unsigned short bitmap_size; //位图尺寸,图标区域,始终正方形
float bitmap_rate; //位图缩放比例
WM_HWIN (*fun)(void); // 双击后的回调函数
GUI_MEMDEV_Handle men_handle;
//赋初值
const char * pText; //图标名称
const GUI_BITMAP * pBitmap; //图标位图
};
typedef struct _icon _ICON;
typedef struct _icon* _ICON_T;
struct _page {
unsigned char init; //初始化状态
unsigned char icon_num; //图标数量
_ICON_T icon_list; //图标集
const GUI_FONT * pFont;
};
typedef struct _page _PAGE;
typedef struct _page* _PAGE_T;
//主页1图标列表
static _ICON icon_list1[]={
{.pText="calculator",.pBitmap=&bmiconview_calculator,.fun=CreateTips},
{.pText="calendar",.pBitmap=&bmiconview_calendar,.fun=CreateTips},
{.pText="camera",.pBitmap=&bmiconview_camera,.fun=CreateTips},
};
//主页2图标列表
static _ICON icon_list2[]={
{.pText="menssages",.pBitmap=&bmiconview_menssages,.fun=CreateTips},
{.pText="weather",.pBitmap=&bmiconview_weather,.fun=CreateTips},
};
//icon_bar 图标列表
static _ICON icon_bar_list[]={
{.pText="phone",.pBitmap=&bmiconview_phone,.fun=CreateTips},
{.pText="app",.pBitmap=&bmiconview_appstore,.fun=CreateTips},
{.pText="photo",.pBitmap=&bmiconview_photos,.fun=CreateTips},
};
static _PAGE _main_page[MAIN_PAGE_NUM]={
{.icon_num=GUI_COUNTOF(icon_list1),.icon_list=icon_list1,.pFont=TEXT_FONT},
{.icon_num=GUI_COUNTOF(icon_list2),.icon_list=icon_list2,.pFont=TEXT_FONT},
};
//变量
static signed short scr_offset_c=0; //屏幕偏移的当前值
static signed short scr_offset_o=0; //屏幕偏移的目标值
static unsigned char c_page=0; // 0表示第一页 1表示第二页
static signed char icon_view_bp_offset=0; //位图偏移到中心点的偏移量 ,注意位图始终为同比例边长
static signed char icon_bar_bp_offset=0; //位图偏移到中心点的偏移量 ,注意位图始终为同比例边长
//移动行为
static signed short move_touch_sxf; //移动触发时的X起点(加上偏移)
static signed short move_touch_sx; //移动触发时的X起点
static signed short move_touch_x; //点击时的x值
static signed short move_touch_c; //此处触发的移动值
static unsigned char move_touch_f; //移动触发开始标志位, 1:表示没有触发 2:触摸 3:触摸并滑动
//触摸单击行为
static signed short touch_click_x; //点击时的x值
static signed short touch_click_y; //点击时的y值
static unsigned char touch_click_f; //点击标志,1:触摸单击触发 2:触摸单击已经绘制
//触摸双击行为
static unsigned char double_click; //双击触发
//页面稳定
static unsigned char page_stability_f=1; //自动返回触发开始标志位
static unsigned short icon_bar_y=0; //预计算出icon_bar_y的起点
//窗口刷新标志位
static unsigned char win_refresh; //标志位 第一位 icon_view 第二位 icon_bar
//窗口句柄
static WM_HWIN icon_view;
static WM_HWIN icon_bar;
static WM_HWIN icon_tips;
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
#define ID_WINDOW_0 (GUI_ID_USER + 0x00)
#define ID_ICONVIEW_0 (GUI_ID_USER + 0x01)
#define ID_TEXT_0 (GUI_ID_USER + 0x02)
#define ID_BUTTON_0 (GUI_ID_USER + 0x03)
#define ID_FRAMEWIN_0 (GUI_ID_USER + 0x04)
#define TIMER_0 0
#define TIMER_1 1
static void init_all_mainpage(void)
{
double_click=0;
scr_offset_c=0;
scr_offset_o=0;
move_touch_f=0;
c_page=0;
clean_all_icon_flag();
}
static void init_mainpage(void)
{
double_click=0;
move_touch_f=0;
clean_all_icon_flag();
}
#if(VIEW_DEBUG==1)
static void debug_view_icon()
{
unsigned char i;
unsigned char t;
for(i=0;i<MAIN_PAGE_NUM;i++){ //页号
for(t=0;t<_main_page[i].icon_num;t++) { //图标号
//绘制图标区域
GUI_SetColor(GUI_WHITE);
GUI_DrawRect(_main_page[i].icon_list[t].icon_x, _main_page[i].icon_list[t].icon_y,
_main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].icon_xsize,
_main_page[i].icon_list[t].icon_y+_main_page[i].icon_list[t].icon_ysize);
//绘制位图区域
GUI_SetColor(GUI_BLACK);
GUI_DrawRect(_main_page[i].icon_list[t].bitmap_x, _main_page[i].icon_list[t].bitmap_y,
_main_page[i].icon_list[t].bitmap_x+_main_page[i].icon_list[t].bitmap_size,
_main_page[i].icon_list[t].bitmap_y+_main_page[i].icon_list[t].bitmap_size);
//绘制文本区域
GUI_SetColor(GUI_ORANGE);
GUI_DrawRect(_main_page[i].icon_list[t].icon_x, _main_page[i].icon_list[t].text_y,
_main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].icon_xsize,
_main_page[i].icon_list[t].text_y+_main_page[i].pFont->YSize+TEXT_EDGE_SIZE);
//绘制文本中心
GUI_SetColor(GUI_RED);
GUI_FillCircle(_main_page[i].icon_list[t].text_c_x, _main_page[i].icon_list[t].text_h_y, 2);
}
}
}
static void debug_icon_bar()
{
unsigned char t;
for(t=0;t<GUI_COUNTOF(icon_bar_list);t++) { //图标号
//绘制图标区域
GUI_SetColor(GUI_WHITE);
GUI_DrawRect(icon_bar_list[t].icon_x, icon_bar_list[t].icon_y,
icon_bar_list[t].icon_x+icon_bar_list[t].icon_xsize,
icon_bar_list[t].icon_y+icon_bar_list[t].icon_ysize);
//绘制位图区域
GUI_SetColor(GUI_BLACK);
GUI_DrawRect(icon_bar_list[t].bitmap_x, icon_bar_list[t].bitmap_y,
icon_bar_list[t].bitmap_x+icon_bar_list[t].bitmap_size,
icon_bar_list[t].bitmap_y+icon_bar_list[t].bitmap_size);
//绘制文本区域
GUI_SetColor(GUI_ORANGE);
GUI_DrawRect(icon_bar_list[t].icon_x, icon_bar_list[t].text_y,
icon_bar_list[t].icon_x+icon_bar_list[t].icon_xsize,
icon_bar_list[t].text_y+_main_page[0].pFont->YSize+ICON_BAR_TEXT_EDGE_SIZE);
//绘制文本中心
GUI_SetColor(GUI_RED);
GUI_FillCircle(icon_bar_list[t].text_c_x, icon_bar_list[t].text_h_y, 2);
}
}
#endif
/*********************************************************************
*
* viewicon_cbDialog
*/
static void clean_icon_view(void)
{
unsigned char i;
unsigned char t;
//清除VIEW_ICON
for(i=0;i<MAIN_PAGE_NUM;i++){ //页号
for(t=0;t<_main_page[i].icon_num;t++) { //图标号
_main_page[i].icon_list[t].flag=0;
}
}
}
static void clean_icon_bar(void)
{
unsigned char t;
//清除ICON_BAR
for(t=0;t<ICON_BAR_ICON_NUM_X;t++) { //图标号
icon_bar_list[t].flag=0;
}
}
static void clean_all_icon_flag(void)
{
clean_icon_view();
clean_icon_bar();
}
static void viewicon_cbDialog(WM_MESSAGE * pMsg)
{
// WM_HWIN hItem;
unsigned char i;
unsigned char t;
unsigned short temp;
unsigned short temp1;
GUI_PID_STATE pState;
// long ram;
switch (pMsg->MsgId) {
case WM_CREATE:
//初始化页参数
// 优化:后期可以分段创建子窗口
for(i=0;i<MAIN_PAGE_NUM;i++){ //页号
for(t=0;t<_main_page[i].icon_num;t++) { //图标号
/*图标区域定位*/
_main_page[i].icon_list[t].icon_xsize=(VIEW_ICON_XSIZE-(ICON_NUM_X+1)*ICON_X_INTERVAL)/ICON_NUM_X;
_main_page[i].icon_list[t].icon_ysize=(VIEW_ICON_YSIZE-(ICON_NUM_Y+1)*ICON_Y_INTERVAL)/ICON_NUM_Y;
temp=t%ICON_NUM_X; //所在行
//图标区域的左上角起点X坐标
_main_page[i].icon_list[t].icon_x=(temp+1)*ICON_X_INTERVAL+temp*_main_page[i].icon_list[t].icon_xsize+VIEW_ICON_XSIZE*i;
temp=t/ICON_NUM_X; //所在列
_main_page[i].icon_list[t].icon_y=(temp+1)*ICON_Y_INTERVAL+temp*_main_page[i].icon_list[t].icon_ysize;
//计算尺寸
_main_page[i].icon_list[t].text_y=_main_page[i].icon_list[t].icon_y+
_main_page[i].icon_list[t].icon_ysize-
_main_page[i].pFont->YSize-TEXT_EDGE_SIZE;
_main_page[i].icon_list[t].bitmap_xsize=_main_page[i].icon_list[t].icon_xsize;
_main_page[i].icon_list[t].bitmap_ysize=_main_page[i].icon_list[t].text_y-_main_page[i].icon_list[t].icon_y;
//文本区域的中心点起点X坐标,由icon_x计算
_main_page[i].icon_list[t].text_c_x=(_main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].bitmap_xsize/2);
_main_page[i].icon_list[t].text_h_y=_main_page[i].icon_list[t].text_y+TEXT_EDGE_SIZE+VIEW_ICON_TEXT_OFFSET;
//绘制位图比例和选边
if(_main_page[i].icon_list[t].bitmap_xsize>_main_page[i].icon_list[t].bitmap_ysize){
//以Y尺寸绘图,y为短边
temp=(_main_page[i].icon_list[t].bitmap_xsize - _main_page[i].icon_list[t].bitmap_ysize)/2; //X方向多余部分,绘制正方形图标
//位图区域的左上角起点X坐标,由icon_x计算
_main_page[i].icon_list[t].bitmap_x=_main_page[i].icon_list[t].icon_x+temp;
_main_page[i].icon_list[t].bitmap_y=_main_page[i].icon_list[t].icon_y;
_main_page[i].icon_list[t].bitmap_rate=
(float)_main_page[i].icon_list[t].bitmap_ysize/_main_page[i].icon_list[t].pBitmap->XSize; //缩放图标比例
_main_page[i].icon_list[t].bitmap_size=_main_page[i].icon_list[t].bitmap_ysize;
}else{
//以x尺寸绘图,x为短边
temp=(_main_page[i].icon_list[t].bitmap_ysize - _main_page[i].icon_list[t].bitmap_xsize)/2;
//位图区域的左上角起点X坐标,由icon_x计算
_main_page[i].icon_list[t].bitmap_x=_main_page[i].icon_list[t].icon_x;
_main_page[i].icon_list[t].bitmap_y=_main_page[i].icon_list[t].icon_y+temp;
_main_page[i].icon_list[t].bitmap_rate=
(float)_main_page[i].icon_list[t].bitmap_xsize/_main_page[i].icon_list[t].pBitmap->XSize; //缩放图标比例
_main_page[i].icon_list[t].bitmap_size=_main_page[i].icon_list[t].bitmap_xsize;
}
/*创建内存设备*/
//内存设备区域的左上角起点X坐标 ,由icon_x计算
_main_page[i].icon_list[t].men_handle=GUI_MEMDEV_CreateFixed(_main_page[i].icon_list[t].bitmap_x, _main_page[i].icon_list[t].bitmap_y,
_main_page[i].icon_list[t].pBitmap->XSize, _main_page[i].icon_list[t].pBitmap->YSize,
GUI_MEMDEV_HASTRANS, GUI_MEMDEV_APILIST_16, GUICC_M565);
//绘制位图
GUI_MEMDEV_Select(_main_page[i].icon_list[t].men_handle);
GUI_DrawBitmap(_main_page[i].icon_list[t].pBitmap,
_main_page[i].icon_list[t].bitmap_x,
_main_page[i].icon_list[t].bitmap_y);
}
}
//提示此时生成位图的正方形边长
i=0; t=0;
//对齐到位图区域中心
icon_view_bp_offset=-(_main_page[i].icon_list[t].pBitmap->XSize-_main_page[i].icon_list[t].bitmap_size)/2;
xprintf("icon_view bitmap_size:%d\r\n",_main_page[i].icon_list[t].bitmap_size);
// ram=GUI_ALLOC_GetNumFreeBytes(); //获取GUI剩余内存空间
// xprintf("icon_view GUI_Free_ram is %d\r\n",ram);
//重新指定LCD输出
GUI_MEMDEV_Select(0);
icon_bar_y=VIEW_ICON_Y+VIEW_ICON_YSIZE;
break;
case WM_PAINT:
//重绘背景
GUI_SetBkColor(VIEW_ICON_BK_COLOR); //自定义调色
GUI_Clear();
// GUI_DrawBitmapEx(&bmicon_smile, VIEW_ICON_XSIZE/2, //耗费CPU资源
// MAIN_PAGE_SMILE_ICON_Y0,bmicon_smile.XSize/2,bmicon_smile.YSize/2,1000,1000);
#if(VIEW_DEBUG==1)
debug_view_icon();
#endif
//绘制滑动图标区域
for(i=0;i<MAIN_PAGE_NUM;i++){ //页号
for(t=0;t<_main_page[i].icon_num;t++) { //图标号
//绘制被选择背景
if(c_page==i && _main_page[i].icon_list[t].flag==1 ){
GUI_SetColor(ICON_SELECTED_COLOR);
GUI_FillRect(_main_page[i].icon_list[t].icon_x-c_page*VIEW_ICON_XSIZE - VIEW_ICON_EDGE_XSIZE,
_main_page[i].icon_list[t].icon_y - VIEW_ICON_EDGE_YSIZE,
_main_page[i].icon_list[t].icon_x+_main_page[i].icon_list[t].icon_xsize-c_page*VIEW_ICON_XSIZE + VIEW_ICON_EDGE_XSIZE ,
_main_page[i].icon_list[t].icon_y+_main_page[i].icon_list[t].icon_ysize + VIEW_ICON_EDGE_YSIZE );
}
//绘制图标区域
GUI_MEMDEV_WriteAt(_main_page[i].icon_list[t].men_handle,
_main_page[i].icon_list[t].bitmap_x+icon_view_bp_offset+scr_offset_c
,_main_page[i].icon_list[t].bitmap_y+icon_view_bp_offset+VIEW_ICON_Y);
// GUI_MEMDEV_WriteExAt();消耗大
//绘制文本区域
GUI_SetColor(GUI_BLACK);
GUI_SetTextMode(GUI_TM_TRANS); //透明背景
GUI_DispStringHCenterAt(_main_page[i].icon_list[t].pText, _main_page[i].icon_list[t].text_c_x+scr_offset_c,
_main_page[i].icon_list[t].text_h_y);
}
}
break;
case WM_TIMER:
if(double_click==1){
WM_DeleteTimer(pMsg->Data.v); //双击行为后 main_page 不在更新
break;
}
else{
WM_RestartTimer(pMsg->Data.v, VIEW_ICON_REFRESH_RATE);
}
GUI_PID_GetState(&pState);
// 移动行为 页面没有达到 单击行为
if(move_touch_f==3 || scr_offset_o!=scr_offset_c){
WM_InvalidateWindow(pMsg->hWin);
}
// 点击行为刷新
if( touch_click_f==1 || touch_click_f==2) //VIEW_ICON 中的图标触发选中
{
WM_InvalidateWindow(pMsg->hWin);
WM_SendMessageNoPara(icon_bar, MSG_WIN_INVAILD); //发送到 icon_bar ,刷新页面
}
/***********行为***********/
/*行为:点击 和 滑动 */
if(pState.Pressed==1 && move_touch_f==1 ){
move_touch_sxf=pState.x-scr_offset_c; // 添加初始偏移值
move_touch_sx=pState.x;
move_touch_f=2; // 记忆发生触摸
}
if(pState.Pressed==1 && move_touch_f>1){
move_touch_x=pState.x;
move_touch_c=move_touch_x-move_touch_sx; //当前触摸滑动的移动值
//确认是否为 滑动 行为
if(abs(move_touch_c)>MOVE_TRIGGER_DISTANCE){
/*行为:滑动 */
if(pState.y>VIEW_ICON_Y && pState.y<icon_bar_y) //需要在指定区域滑动
{
clean_all_icon_flag(); //清除所有的标记
if(win_refresh&0x2){
WM_SendMessageNoPara(icon_bar, MSG_WIN_INVAILD);
win_refresh&=0x1; //清除这个刷新标记
}
move_touch_f=3; //触发触摸移动标志
scr_offset_c=move_touch_x-move_touch_sxf; //在初始偏移值基础上进行增减
//滑动页面两侧极限位置限制
if(scr_offset_c < (-(MAIN_PAGE_NUM-1)*VIEW_ICON_XSIZE)){
scr_offset_c = -(MAIN_PAGE_NUM-1)*VIEW_ICON_XSIZE;
move_touch_c=0;
}
if(scr_offset_c > 0){
scr_offset_c = 0;
move_touch_c=0;
}
}
else{ //超出滑动区域
move_touch_c=0;
}
}
else
{
/*行为:点击图标*/
//touch_click_f
// 0: 一次单击检测开始
// 1: VIEW_ICON 选中
// 2: ICON_BAR 选中
// 3: 都没 选中
if(move_touch_f==2 && page_stability_f==1 && touch_click_f==0 && double_click==0){ //触发点击行为,没有触发翻页
touch_click_x = pState.x;
touch_click_y = pState.y;
// 确定 VIEW_ICON 哪个图标被选中
for(i=0;i<MAIN_PAGE_NUM;i++){ //页号
for(t=0;t<_main_page[i].icon_num;t++) { //图标号
temp = _main_page[i].icon_list[t].icon_x + VIEW_ICON_X - c_page*VIEW_ICON_XSIZE; //当前页的图标X起点
temp1 = _main_page[i].icon_list[t].icon_y + VIEW_ICON_Y; //当前页的图标Y起点
if( i==c_page
&& touch_click_f == 0
&& touch_click_x - temp < _main_page[i].icon_list[t].icon_xsize
&& touch_click_x > temp
&& touch_click_y- temp1 < _main_page[i].icon_list[t].icon_ysize
&& touch_click_y > temp1 )
{
/*行为:双击 图标*/
if(_main_page[i].icon_list[t].flag==1){
double_click=1;
_main_page[i].icon_list[t].fun(); //触发回调
}
_main_page[i].icon_list[t].flag=1;
touch_click_f = 1; // VIEW_ICON 中的图标触发选中
win_refresh|=0x1; // 标记清除选中需要刷新一次
}else
{
_main_page[i].icon_list[t].flag=0; //将 VIEW_ICON 没有选择的标志清除
}
}
}
// 确定 ICON_BAR 哪个图标被选中
for(t=0;t<ICON_BAR_ICON_NUM_X;t++) { //图标号
temp=icon_bar_list[t].icon_x+ICON_BAR_X;
temp1=icon_bar_list[t].icon_y+ICON_BAR_Y;
if(touch_click_f == 0
&& touch_click_x-temp < icon_bar_list[t].icon_xsize
&& touch_click_y-temp1 < icon_bar_list[t].icon_ysize
&& touch_click_x > temp
&& touch_click_y > temp1 )
{
/*行为:双击 图标*/
if(icon_bar_list[t].flag==1){
double_click=1;
icon_bar_list[t].fun(); //触发回调
}
icon_bar_list[t].flag=1;
touch_click_f = 2; // ICON_BAR 中的图标触发选中
win_refresh|=0x2; // 标记清除选中需要刷新一次
}else
{
icon_bar_list[t].flag=0; //将 ICON_BAR 没有选择的标志清除
}
}
// 什么都没有点
if(touch_click_f!=1 && touch_click_f!=2){ //表示什么都没有点击
WM_InvalidateWindow(pMsg->hWin);
WM_SendMessageNoPara(icon_bar, MSG_WIN_INVAILD); //发送到icon_bar ,刷新页面
touch_click_f=3; // 都没有点到
}
}
}
}
else
{
move_touch_c=0;
}
//用于解锁后防止滑动屏幕
if(pState.Pressed==0){
move_touch_f=1; // 记忆没有发生触摸
touch_click_f = 0;
}
/* 行为:更改页面目标值 */
if(move_touch_f==3 && abs(move_touch_c)>VIEW_ICON_XSIZE/4 && page_stability_f==1){
if(move_touch_c<0 && c_page < MAIN_PAGE_NUM-1) //切换下一页
{
scr_offset_o=scr_offset_o-VIEW_ICON_XSIZE;
page_stability_f=0;
c_page++;
}else if(move_touch_c>0 && c_page>0){ //切换上一页
scr_offset_o=scr_offset_o+VIEW_ICON_XSIZE;
page_stability_f=0;
c_page--;
}
}
/*行为:自动定位主页*/
if( move_touch_f==1 && scr_offset_o>scr_offset_c ){
if((scr_offset_o-scr_offset_c)<VIEW_ICON_POSITIONING_VALUE)
scr_offset_c=scr_offset_o; //防止无法准确到达scr_offset_o值
else
scr_offset_c=scr_offset_c+VIEW_ICON_POSITIONING_VALUE;
}else if( move_touch_f==1 && scr_offset_o<scr_offset_c ){
if((scr_offset_c-scr_offset_o)<VIEW_ICON_POSITIONING_VALUE)
scr_offset_c=scr_offset_o; //防止无法准确到达scr_offset_o值
else
scr_offset_c=scr_offset_c-VIEW_ICON_POSITIONING_VALUE;
}
//页面稳定
if(scr_offset_o==scr_offset_c)page_stability_f=1;
// xprintf("move_touch_f:%d\r\n",move_touch_f);
break;
case WM_DELETE:
init_all_mainpage();
// 删除所有的内存设备
for(i=0;i<MAIN_PAGE_NUM;i++){ //页号
for(t=0;t<_main_page[i].icon_num;t++) { //图标号
GUI_MEMDEV_Delete(_main_page[i].icon_list[t].men_handle);
}
}
break;
default:
WM_DefaultProc(pMsg);
break;
}
}
static void iconbar_cbDialog(WM_MESSAGE * pMsg)
{
// WM_HWIN hItem;
// unsigned char i;
unsigned char t;
unsigned short temp;
#if(VIEW_DEBUG==1)
long ram;
#endif
switch (pMsg->MsgId) {
case WM_CREATE:
for(t=0;t<GUI_COUNTOF(icon_bar_list);t++) { //图标号
/*图标区域定位*/
icon_bar_list[t].icon_xsize=(ICON_BAR_XSIZE-(ICON_BAR_ICON_NUM_X-1)*ICON_BAR_MIDDLE_INTERVAL-2*ICON_BAR_OUTSIDE_INTERVAL)/ICON_BAR_ICON_NUM_X;
icon_bar_list[t].icon_ysize=(ICON_BAR_YSIZE-(ICON_BAR_ICON_NUM_Y+1)*ICON_BAR_Y_INTERVAL)/ICON_BAR_ICON_NUM_Y;
temp=t%ICON_BAR_ICON_NUM_X; //所在行
//图标区域的左上角起点X坐标
icon_bar_list[t].icon_x=ICON_BAR_OUTSIDE_INTERVAL+ temp*ICON_BAR_MIDDLE_INTERVAL+temp*icon_bar_list[t].icon_xsize;
temp=t/ICON_BAR_ICON_NUM_X; //所在列
icon_bar_list[t].icon_y=(temp+1)*ICON_BAR_Y_INTERVAL+temp*icon_bar_list[t].icon_ysize;
//计算尺寸
icon_bar_list[t].text_y=icon_bar_list[t].icon_y+
icon_bar_list[t].icon_ysize-
_main_page[0].pFont->YSize-ICON_BAR_TEXT_EDGE_SIZE;
icon_bar_list[t].bitmap_xsize=icon_bar_list[t].icon_xsize;
icon_bar_list[t].bitmap_ysize=icon_bar_list[t].text_y-icon_bar_list[t].icon_y;
//文本区域的中心点起点X坐标,由icon_x计算
icon_bar_list[t].text_c_x=(icon_bar_list[t].icon_x+icon_bar_list[t].bitmap_xsize/2);
icon_bar_list[t].text_h_y=icon_bar_list[t].text_y+ICON_BAR_TEXT_EDGE_SIZE+ICON_BAR_TEXT_OFFSET;
//绘制位图比例和选边
if(icon_bar_list[t].bitmap_xsize>icon_bar_list[t].bitmap_ysize){
//以Y尺寸绘图,y为短边
temp=(icon_bar_list[t].bitmap_xsize - icon_bar_list[t].bitmap_ysize)/2; //X方向多余部分,绘制正方形图标
//位图区域的左上角起点X坐标,由icon_x计算
icon_bar_list[t].bitmap_x=icon_bar_list[t].icon_x+temp;
icon_bar_list[t].bitmap_y=icon_bar_list[t].icon_y;
icon_bar_list[t].bitmap_rate=
(float)icon_bar_list[t].bitmap_ysize/icon_bar_list[t].pBitmap->XSize; //缩放图标比例
icon_bar_list[t].bitmap_size=icon_bar_list[t].bitmap_ysize;
}else{
//以x尺寸绘图,x为短边
temp=(icon_bar_list[t].bitmap_ysize - icon_bar_list[t].bitmap_xsize)/2;
//位图区域的左上角起点X坐标,由icon_x计算
icon_bar_list[t].bitmap_x=icon_bar_list[t].icon_x;
icon_bar_list[t].bitmap_y=icon_bar_list[t].icon_y+temp;
icon_bar_list[t].bitmap_rate=
(float)icon_bar_list[t].bitmap_xsize/icon_bar_list[t].pBitmap->XSize; //缩放图标比例
icon_bar_list[t].bitmap_size=icon_bar_list[t].bitmap_xsize;
}
/*创建内存设备*/
//内存设备区域的左上角起点X坐标 ,由icon_x计算
//这里使用的内存创建后没有主动释放
icon_bar_list[t].men_handle=GUI_MEMDEV_CreateFixed(icon_bar_list[t].bitmap_x, icon_bar_list[t].bitmap_y,
icon_bar_list[t].pBitmap->XSize, icon_bar_list[t].pBitmap->YSize,
GUI_MEMDEV_HASTRANS, GUI_MEMDEV_APILIST_16, GUICC_M565);
//绘制位图
GUI_MEMDEV_Select(icon_bar_list[t].men_handle);
GUI_DrawBitmap(icon_bar_list[t].pBitmap,
icon_bar_list[t].bitmap_x,
icon_bar_list[t].bitmap_y);
}
//提示此时生成位图的正方形边长
//对齐到位图区域中心,使用图片1的,所以要保证图标大小一致,否则其他图标位置错误
t=0;
icon_bar_bp_offset=-(icon_bar_list[t].pBitmap->XSize-icon_bar_list[t].bitmap_size)/2+1;
xprintf("icon_bar bitmap_size:%d\r\n",icon_bar_list[t].bitmap_size);
// ram=GUI_ALLOC_GetNumFreeBytes(); //获取GUI剩余内存空间
// xprintf("icon_bar GUI_Free_ram is %d\r\n",ram);
//重新指定LCD输出
GUI_MEMDEV_Select(0);
#if(VIEW_DEBUG==1)
ram=GUI_ALLOC_GetNumFreeBytes(); //获取GUI剩余内存空间
xprintf("GUI_Free_ram is %d\r\n",ram);
#endif
break;
case WM_PAINT:
GUI_SetBkColor(ICON_BAR_BK_COLOR);
GUI_Clear();
#if(VIEW_DEBUG==1)
debug_icon_bar();
#endif
//绘制图标区域
for(t=0;t<ICON_BAR_ICON_NUM_X;t++) { //图标号
//绘制被选择背景
if(icon_bar_list[t].flag==1){
GUI_SetColor(ICON_SELECTED_COLOR);
GUI_FillRect(icon_bar_list[t].icon_x-ICON_BAR_EDGE_SIZE,
icon_bar_list[t].icon_y-ICON_BAR_EDGE_SIZE,
icon_bar_list[t].icon_x+icon_bar_list[t].icon_xsize+ICON_BAR_EDGE_SIZE,
icon_bar_list[t].icon_y+icon_bar_list[t].icon_ysize+ICON_BAR_EDGE_SIZE);
}
//绘制图标区域
GUI_MEMDEV_WriteAt(icon_bar_list[t].men_handle,
icon_bar_list[t].bitmap_x+icon_bar_bp_offset
,icon_bar_list[t].bitmap_y+icon_bar_bp_offset+ICON_BAR_Y);
//绘制文本区域
GUI_SetColor(GUI_BLACK);
GUI_SetTextMode(GUI_TM_TRANS); //透明背景
GUI_DispStringHCenterAt(icon_bar_list[t].pText,icon_bar_list[t].text_c_x,
icon_bar_list[t].text_h_y);
}
// xprintf("icon_bar_refresh\r\n");
break;
case MSG_WIN_INVAILD:
WM_InvalidateWindow(pMsg->hWin);
break;
case WM_DELETE:
init_all_mainpage();
// 删除所有的内存设备
for(t=0;t<GUI_COUNTOF(icon_bar_list);t++) { //图标号
GUI_MEMDEV_Delete(icon_bar_list[t].men_handle);
}
break;
default:
WM_DefaultProc(pMsg);
break;
}
}
/*********************************************************************
*
* Createwin_mainpage
*/
WM_HWIN Createwin_mainpage(void);
WM_HWIN Createwin_mainpage(void) {
WM_HWIN win[WIN_MAX_NUM]={0};
//初始化主屏幕参数
init_all_mainpage();
/*****创建VIEW ICON区域*****/
win[0]=WM_CreateWindowAsChild(VIEW_ICON_X, VIEW_ICON_Y, VIEW_ICON_XSIZE, VIEW_ICON_YSIZE,
WM_HBKWIN, WM_CF_SHOW, viewicon_cbDialog, 0);
//创建VIEW ICON定时器
WM_CreateTimer(win[0], TIMER_0, VIEW_ICON_REFRESH_RATE, 0);
// /*****创建ICON BAR区域*****/
win[1]=WM_CreateWindowAsChild(ICON_BAR_X, ICON_BAR_Y, ICON_BAR_XSIZE, ICON_BAR_YSIZE,
WM_HBKWIN, WM_CF_SHOW, iconbar_cbDialog, 0);
icon_view = win[0];
icon_bar = win[1];
switch_win(win,MIAN_PAGE_WIN_ID);
return win[0];
}
#define TIPS_WIN_XSIZE 150
#define TIPS_WIN_YSIZE 120
#define TIPS_WIN_X (LCD_xsize-TIPS_WIN_XSIZE)/2
#define TIPS_WIN_Y ((LCD_ysize-TIPS_WIN_YSIZE)/2-STATUS_BAR_HEIGHT)
#define TIPS_BUTTON_XSIZE 50
#define TIPS_BUTTON_YSIZE 25
#define TIPS_BUTTON_X ((TIPS_WIN_XSIZE-TIPS_BUTTON_XSIZE)/2)
#define TIPS_BUTTON_Y (int)(TIPS_WIN_YSIZE * 0.65f)
#define TIPS_BUTTON_FONT GUI_FONT_8X12_ASCII
#define TIPS_TEXT_XSIZE (TIPS_WIN_XSIZE-20)
#define TIPS_TEXT_YSIZE (TIPS_WIN_YSIZE-TIPS_BUTTON_YSIZE-60) //不要覆盖到按钮窗口
#define TIPS_TEXT_X (TIPS_WIN_XSIZE-TIPS_TEXT_XSIZE)/2
#define TIPS_TEXT_Y (int)(TIPS_WIN_YSIZE * 0.30f)
#define TIPS_TEXT_TEXT GUI_FONT_8X12_ASCII
#if(VIEW_DEBUG==1)
static void debug_view_region(void)
{
//绘制窗口区域
GUI_SetColor(GUI_RED);
GUI_DrawRect(0,0,
0+TIPS_WIN_XSIZE-1,
0+TIPS_WIN_YSIZE-1);
//绘制文本区域
GUI_SetColor(GUI_WHITE);
GUI_DrawRect(TIPS_TEXT_X, TIPS_TEXT_Y,
TIPS_TEXT_X+TIPS_TEXT_XSIZE,
TIPS_TEXT_Y+TIPS_TEXT_YSIZE);
//绘制按钮区域
GUI_SetColor(GUI_BLACK);
GUI_DrawRect(TIPS_BUTTON_X, TIPS_BUTTON_Y,
TIPS_BUTTON_X+TIPS_BUTTON_XSIZE,
TIPS_BUTTON_Y+TIPS_BUTTON_YSIZE);
}
#endif
//创建提示窗口
static void Tips_cbDialog(WM_MESSAGE * pMsg) {
#if(VIEW_DEBUG==0)
WM_HWIN hItem;
#endif
int NCode;
int Id;
// long ram;
switch (pMsg->MsgId) {
case WM_CREATE:
//显示框架
#if(VIEW_DEBUG==0)
hItem=FRAMEWIN_CreateEx(0,0,TIPS_WIN_XSIZE,TIPS_WIN_YSIZE,pMsg->hWin,
WM_CF_SHOW,0,ID_FRAMEWIN_0,"Tips",0);
hItem=TEXT_CreateEx(TIPS_TEXT_X, TIPS_TEXT_Y,TIPS_TEXT_XSIZE, TIPS_TEXT_YSIZE,
pMsg->hWin,WM_CF_SHOW,
TEXT_CF_HCENTER|TEXT_CF_TOP, ID_TEXT_0, "Please set callback function");
TEXT_SetWrapMode(hItem,GUI_WRAPMODE_WORD);
WM_SetStayOnTop(hItem,1); //文本窗口始终在最上面
hItem = BUTTON_CreateEx(TIPS_BUTTON_X,TIPS_BUTTON_Y,TIPS_BUTTON_XSIZE,TIPS_BUTTON_YSIZE,pMsg->hWin,WM_CF_SHOW,0,ID_BUTTON_0);
WM_SetFocus(hItem);
WM_SetStayOnTop(hItem,1); //按钮窗口始终在最上面
BUTTON_SetFont(hItem, TIPS_BUTTON_FONT);
BUTTON_SetText(hItem, "OK");
#endif
#if(VIEW_DEBUG==1)
debug_view_region();
#endif
// ram=GUI_ALLOC_GetNumFreeBytes(); //获取GUI剩余内存空间
// xprintf("GUI_Free_ram is %d\r\n",ram);
break;
case WM_NOTIFY_PARENT:
Id = WM_GetId(pMsg->hWinSrc);
NCode = pMsg->Data.v;
switch(Id) {
case ID_BUTTON_0: // Notifications sent by 'Button'
switch(NCode) {
case WM_NOTIFICATION_CLICKED:
WM_DeleteWindow(pMsg->hWin);
break;
case WM_NOTIFICATION_RELEASED:
break;
}
break;
}
break;
case WM_PAINT:
#if(VIEW_DEBUG==1)
debug_view_region();
#endif
break;
case WM_DELETE:
init_mainpage();
if(_hLastFrame[0]!=0){
WM_CreateTimer(icon_view, TIMER_0, VIEW_ICON_REFRESH_RATE, 0);
}
break;
default:
WM_DefaultProc(pMsg);
break;
}
}
WM_HWIN CreateTips(void) {
icon_tips=WM_CreateWindowAsChild(TIPS_WIN_X, TIPS_WIN_Y, TIPS_WIN_XSIZE, TIPS_WIN_YSIZE,
icon_view, WM_CF_SHOW|WM_CF_HASTRANS, Tips_cbDialog, 0);
return icon_tips;
}
/*************************** End of file ****************************/
解锁页代码
/*********************************************************************
* *
* SEGGER Microcontroller GmbH & Co. KG *
* Solutions for real time microcontroller applications *
* *
**********************************************************************
* *
* C-file generated by: *
* *
* GUI_Builder for emWin version 5.32 *
* Compiled Oct 8 2015, 11:59:02 *
* (c) 2015 Segger Microcontroller GmbH & Co. KG *
* *
**********************************************************************
* *
* Internet: www.segger.com Support: support@segger.com *
* *
**********************************************************************
*/
// USER START (Optionally insert additional includes)
// USER END
#include "DIALOG.h"
#include "SCROLLBAR.h"
#include "SCROLLBAR_Private.h"
#include "GUI_app/gui_thread.h"
#include "config.h"
/*********************************************************************
*
* user config
*
**********************************************************************
*/
//锁定画面尺寸定义
#define LOCK_SCREEN_X 0
#define LOCK_SCREEN_Y STATUS_BAR_HEIGHT
#define LOCK_SCREEN_XSIZE (LCD_xsize-LOCK_SCREEN_X)
#define LOCK_SCREEN_YSIZE (LCD_ysize-LOCK_SCREEN_Y)
//在状态栏的基础上偏移
#define LOCK_BAR_Y0_RATE 0.75f //解锁条在LCD屏幕的比例位置
#define LOCK_BAR_Y0 (int)(LCD_ysize*LOCK_BAR_Y0_RATE-STATUS_BAR_HEIGHT) //解锁条的Y方向起点,始终保证在
#define TEXT_BAR_Y0 50 //文本框的左上角起点,相对于LOCK_SCREEN为0
#define TEXT_BAR_YSIZE 40
#define SMILE_ICON_Y0 (LOCK_SCREEN_YSIZE)/2 //笑脸图标的中心点Y方向
//锁定界面参数
#define VALUE_NO_TRIGGER -1 //滑条按钮没有触发下的返回减少的值
#define LOCK_BAR_REFRESH_RATE 30 //解锁条刷新率
#define TIME_REFRESH_RATE 1000 //时间显示刷新率
//解锁条外观调整
#define LOCK_BAR_LIMIT 15 //解锁条超出限制,由于不要左右按钮,需要起点和终点超出界限
#define LOCK_BAR_WIDTH 40 //解锁条的宽度,上下高度
#define SLIDE_STRIP_VALUE 40 //滑条最大值,决定滑块大小
#define LOCK_BAR_OSIZE 1 //解锁条外框尺寸
#define LOCK_BAR_ISIZE 1 //解锁条内框尺寸
#define LOCK_BAR_RSIZE 3 //解锁条中所有圆角尺寸
#define SLIDE_OSIZE 3 //滑块在解锁条中的间距
#define DY_SLIDE_WIDTH 20 //动态滑条宽度
#define DY_SLIDE_OSIZE 3 //动态滑条尺寸
#define DY_SLIDE_SPEED 1 //动态速度
//时间外观调整
#define TIME_Y_OFFSET 100 //时间的垂直位置,越大越往上
#define VIEW_DEBUG 0
/*********************************************************************
*
* variables
*
**********************************************************************
*/
static float dy_slider_value=0; //动态滑块的移动值
extern WM_HWIN _hLastFrame[WIN_MAX_NUM];;
extern GUI_CONST_STORAGE GUI_BITMAP bmwallpaper_ios15_1; //失真的IOS壁纸
extern GUI_CONST_STORAGE GUI_BITMAP bmwallpaper_ios15_2; //全彩的IOS壁纸
extern GUI_CONST_STORAGE GUI_BITMAP bmwallpaper_smile; //失真的笑脸壁纸
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_unlock_arrow;
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_smile;
extern GUI_CONST_STORAGE GUI_FONT GUI_Fontfont_songti_38_bold_ascii_unicode;
extern RTC_TimeTypeDef RTC_TimeStruct;
extern RTC_DateTypeDef RTC_DateStruct;
extern void init_mainpage(void);
WM_HWIN Createlockwin(void);
WM_HWIN Createwin_mainpage(void);
WM_HWIN lock_handle;
GUI_MEMDEV_Handle icon_arrow_handle;
/*********************************************************************
*
* Defines
*
**********************************************************************
*/
#define ID_WINDOW_0 (GUI_ID_USER + 0x00)
#define ID_SCROLLBAR_0 (GUI_ID_USER + 0x01)
#define ID_TEXT_0 (GUI_ID_USER + 0x02)
#define TIMER_0 0
#define TIMER_1 1
// USER START (Optionally insert additional defines)
// USER END
/*********************************************************************
*
* Static code
*
**********************************************************************
*/
#if(VIEW_DEBUG==0)
static signed short but_lcd_xoffset;
static signed short but_lcd_yoffset;
static int SCROLLBAR_0_DrawSkin(const WIDGET_ITEM_DRAW_INFO * pDrawItemInfo) {
static int SCROLLBAR0_state=0;
static int UNLOCK_BAR_x0=0,UNLOCK_BAR_y0=0,UNLOCK_BAR_x1=0,UNLOCK_BAR_y1=0;
static unsigned char init=0;
SCROLLBAR_SKINFLEX_INFO * pSkinInfo;
pSkinInfo = (SCROLLBAR_SKINFLEX_INFO *)pDrawItemInfo->p;
char text[]=" slide to unlock";
GUI_RECT pRect;
int offset;
int temp;
switch (pDrawItemInfo->Cmd) {
case WIDGET_ITEM_CREATE: //创建控件后立即发送
return SCROLLBAR_DrawSkinFlex(pDrawItemInfo);
case WIDGET_ITEM_DRAW_BUTTON_L: //皮肤设置函数将绘制左侧按钮
if( but_lcd_yoffset==0){
// offset=pDrawItemInfo->x1-pDrawItemInfo->x0;
temp=WM_GetWindowOrgX(pDrawItemInfo->hWin);
but_lcd_xoffset=temp+LOCK_BAR_OSIZE+LOCK_BAR_ISIZE+SLIDE_OSIZE-2;
but_lcd_yoffset=WM_GetWindowOrgY(pDrawItemInfo->hWin)+LOCK_BAR_OSIZE+LOCK_BAR_ISIZE+SLIDE_OSIZE-5;
// xprintf("xoffset:%d yoffset:%d \r\n",but_lcd_xoffset,but_lcd_yoffset);
}
//不绘制
return 0;
case WIDGET_ITEM_DRAW_BUTTON_R: //皮肤设置函数将绘制右侧按钮
//不绘制
return 0;
case WIDGET_ITEM_DRAW_OVERLAP: //皮肤设置函数将绘制重叠区域。
return SCROLLBAR_DrawSkinFlex(pDrawItemInfo);
case WIDGET_ITEM_DRAW_SHAFT_L: //皮肤设置函数将绘制轴的左侧部分
// xprintf("SHAFT_L x0:%d y0:%d x1:%d y1:%d \r\n",pDrawItemInfo->x0,pDrawItemInfo->y0,pDrawItemInfo->x1,pDrawItemInfo->y1);
//绘制外框,外框使用圆角矩形,填充后,下面又覆盖中间区域
UNLOCK_BAR_x0=pDrawItemInfo->x0;
UNLOCK_BAR_y0=pDrawItemInfo->y0;
if(UNLOCK_BAR_x1){
GUI_SetColor(GUI_GRAY); //指定外框颜色
//绘制外框区域
GUI_FillRoundedRect(UNLOCK_BAR_x0,UNLOCK_BAR_y0,UNLOCK_BAR_x1,UNLOCK_BAR_y1,LOCK_BAR_RSIZE);
//绘制内框,虽然为填充,后面覆盖掉
offset=LOCK_BAR_OSIZE;
GUI_DrawGradientRoundedV(UNLOCK_BAR_x0+offset, //根据外框尺寸偏移
UNLOCK_BAR_y0+offset,
UNLOCK_BAR_x1-offset,
UNLOCK_BAR_y1-offset,
LOCK_BAR_RSIZE,GUI_DARKGRAY,GUI_LIGHTGRAY); //滑条底部渐变为白色
//绘制滑条
offset=LOCK_BAR_OSIZE+LOCK_BAR_ISIZE;
GUI_DrawGradientRoundedV(UNLOCK_BAR_x0+offset,
UNLOCK_BAR_y0+offset,
UNLOCK_BAR_x1-offset,
UNLOCK_BAR_y1-offset,
LOCK_BAR_RSIZE,GUI_BLACK,GUI_DARKGRAY);
//绘制动态滑条
offset=LOCK_BAR_OSIZE+LOCK_BAR_ISIZE+DY_SLIDE_OSIZE;
pRect.x0=dy_slider_value+UNLOCK_BAR_x0+offset;
pRect.x1=pRect.x0+DY_SLIDE_WIDTH;
pRect.y0=UNLOCK_BAR_y0+offset;
pRect.y1=UNLOCK_BAR_y1-offset;
if(dy_slider_value<=DY_SLIDE_WIDTH && init==0){ //头部逐渐出现
pRect.x0=UNLOCK_BAR_x0+offset;
pRect.x1=UNLOCK_BAR_x0+offset+dy_slider_value;
if(dy_slider_value==DY_SLIDE_WIDTH){
init=1; //头部出现效果完成
dy_slider_value=0; //正常显示开始
}
}
if((pRect.x1)>=UNLOCK_BAR_x1-offset){ //尾部逐渐消失
pRect.x1=UNLOCK_BAR_x1-offset;
if(pRect.x0>=pRect.x1){
init=0;
dy_slider_value=0;
}
}
// 绘制动态滑条,使用透明效果
GUI_DrawGradientRoundedH(pRect.x0,pRect.y0,pRect.x1,pRect.y1,
LOCK_BAR_RSIZE,GUI_MAKE_COLOR((0xaauL << 24) | GUI_DARKGRAY),GUI_MAKE_COLOR((0xaauL << 24) | GUI_WHITE)); //制作混合色
//显示字体
pRect.x0=UNLOCK_BAR_x0;
pRect.y0=UNLOCK_BAR_y0;
pRect.x1=UNLOCK_BAR_x1;
pRect.y1=UNLOCK_BAR_y1;
GUI_SetColor(GUI_GRAY); //指定外框颜色
GUI_SetFont(GUI_FONT_8X16_ASCII);
GUI_SetTextMode(GUI_TM_TRANS|GUI_TM_XOR); //设置为显示透明文本
GUI_DispStringInRectEx(text,&pRect,GUI_TA_VCENTER|GUI_TA_HCENTER,sizeof(text),GUI_ROTATE_0);
}
return 0;
case WIDGET_ITEM_DRAW_SHAFT_R: //皮肤设置函数将绘制轴的右侧部分。
UNLOCK_BAR_x1=pDrawItemInfo->x1;
UNLOCK_BAR_y1=pDrawItemInfo->y1;
return 0;
case WIDGET_ITEM_DRAW_THUMB: //皮肤设置函数将绘制缩略图
// xprintf("THUMB x0:%d y0:%d x1:%d y1:%d \r\n",pDrawItemInfo->x0,pDrawItemInfo->y0,pDrawItemInfo->x1,pDrawItemInfo->y1);
if(SCROLLBAR0_state!=pSkinInfo->State){ //保存中间按钮状态到用户数据
SCROLLBAR0_state=pSkinInfo->State;
SCROLLBAR_SetUserData(pDrawItemInfo->hWin,&SCROLLBAR0_state,sizeof(SCROLLBAR0_state));
}
//绘制滑块
GUI_DrawGradientRoundedV(pDrawItemInfo->x0+SLIDE_OSIZE,
pDrawItemInfo->y0+SLIDE_OSIZE,
pDrawItemInfo->x1-SLIDE_OSIZE,
pDrawItemInfo->y1-SLIDE_OSIZE,
LOCK_BAR_RSIZE,GUI_WHITE,GUI_LIGHTGRAY); //滑条底部渐变为白色
//绘制箭头
// GUI_DrawBitmapEx(&bmicon_unlock_arrow, pDrawItemInfo->x0+(pDrawItemInfo->x1-pDrawItemInfo->x0)/2+2,
// (pDrawItemInfo->y1-pDrawItemInfo->y0)/2,bmicon_unlock_arrow.XSize/2,bmicon_unlock_arrow.YSize/2,500,500);
GUI_MEMDEV_WriteAt(icon_arrow_handle,
but_lcd_xoffset + ((pDrawItemInfo->x1-pDrawItemInfo->x0)-bmicon_unlock_arrow.XSize)/2+pDrawItemInfo->x0,
but_lcd_yoffset + ((pDrawItemInfo->y1-pDrawItemInfo->y0)-bmicon_unlock_arrow.YSize)/2+pDrawItemInfo->y0);
return 0;
case WIDGET_ITEM_GET_BUTTONSIZE:
return (pSkinInfo->IsVertical) ?
pDrawItemInfo->x1 - pDrawItemInfo->x0 + 1 :
pDrawItemInfo->y1 - pDrawItemInfo->y0 + 1;
default: //所有其他类型将以默认皮肤执行
return SCROLLBAR_DrawSkinFlex(pDrawItemInfo);
}
}
#endif
/*********************************************************************
*
* _cbDialog
*/
#if(VIEW_DEBUG==1)
static void debug_view_region(void)
{
//绘制窗口区域
GUI_SetColor(GUI_RED);
GUI_FillCircle(2,2,2);
GUI_SetColor(GUI_RED);
GUI_DrawRect(LOCK_SCREEN_X-LOCK_BAR_LIMIT, LOCK_BAR_Y0,LOCK_SCREEN_X-LOCK_BAR_LIMIT+LOCK_SCREEN_XSIZE+LOCK_BAR_LIMIT*2,
LOCK_BAR_Y0+(int)LOCK_SCREEN_YSIZE*0.15f);
//绘制文本区域
GUI_SetColor(GUI_WHITE);
GUI_DrawRect(LOCK_SCREEN_X, TEXT_BAR_Y0,
LOCK_SCREEN_X+LOCK_SCREEN_XSIZE,
TEXT_BAR_Y0+TEXT_BAR_YSIZE);
}
#endif
static void _cbDialog(WM_MESSAGE * pMsg) {
WM_HWIN hItem;
int SCROLLBAR0_state=0;
int SCROLLBAR0_value=0;
char time_id;
char tbuf[40];
// USER START (Optionally insert additional variables)
// USER END
switch (pMsg->MsgId) {
case WM_CREATE :
#if(VIEW_DEBUG==0)
//创建解锁条
hItem=SCROLLBAR_CreateUser(LOCK_SCREEN_X-LOCK_BAR_LIMIT, LOCK_BAR_Y0,LOCK_SCREEN_XSIZE+LOCK_BAR_LIMIT*2,(int)LOCK_SCREEN_YSIZE*0.15f,
pMsg->hWin,WM_CF_SHOW, SCROLLBAR_CF_FOCUSSABLE ,ID_SCROLLBAR_0, sizeof(SCROLLBAR0_state));
SCROLLBAR_SetNumItems(hItem, SLIDE_STRIP_VALUE);
SCROLLBAR_SetWidth(hItem,LOCK_BAR_WIDTH);
SCROLLBAR_SetSkin(hItem,SCROLLBAR_0_DrawSkin); //设置控件的皮肤回调
WM_SetFocus(hItem);
//创建文本框,显示时间
sprintf((char*)tbuf,"%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes);
hItem=TEXT_CreateEx(LOCK_SCREEN_X, TEXT_BAR_Y0,LOCK_SCREEN_XSIZE, TEXT_BAR_YSIZE,
pMsg->hWin,WM_CF_SHOW,TEXT_CF_HCENTER|TEXT_CF_TOP, ID_TEXT_0,tbuf);
TEXT_SetFont(hItem,&GUI_Fontfont_songti_38_bold_ascii_unicode);
TEXT_SetBkColor(hItem, GUI_INVALID_COLOR); //使用背景颜色,透明字体
/*创建内存设备*/
//内存设备区域的左上角起点X坐标 ,由icon_x计算
icon_arrow_handle=GUI_MEMDEV_CreateFixed(100,100,
bmicon_unlock_arrow.XSize,bmicon_unlock_arrow.YSize,
GUI_MEMDEV_HASTRANS, GUI_MEMDEV_APILIST_16, GUICC_M565);
//绘制位图
GUI_MEMDEV_Select(icon_arrow_handle);
GUI_DrawBitmap(&bmicon_unlock_arrow, 100,100);
//重新指定LCD输出
GUI_MEMDEV_Select(0);
#endif
break;
case WM_PAINT:
//绘制图标区域
GUI_SetBkColor(0x00FFC880); //自定义调色
GUI_Clear();
GUI_DrawBitmap(&bmicon_smile,
LOCK_SCREEN_XSIZE/2-bmicon_smile.XSize/2,
SMILE_ICON_Y0 - bmicon_smile.YSize/2);
#if(VIEW_DEBUG==1)
debug_view_region();
#endif
break;
case WM_TIMER:
time_id=WM_GetTimerId(pMsg->Data.v);
switch(time_id){
case TIMER_0: //解锁条的刷新率
WM_RestartTimer(pMsg->Data.v, LOCK_BAR_REFRESH_RATE);
//高刷新率刷新解锁条
//如果滑条按钮没有被按,自动回退
hItem=WM_GetDialogItem(pMsg->hWin, ID_SCROLLBAR_0);
WM_InvalidateWindow(hItem); //单独刷新解锁条
SCROLLBAR_GetUserData(hItem,&SCROLLBAR0_state,sizeof(SCROLLBAR0_state)); //可以使用全局变量
if(!(SCROLLBAR0_state & PRESSED_STATE_THUMB)){
SCROLLBAR_AddValue(hItem,VALUE_NO_TRIGGER); //中间按钮返回
}
dy_slider_value=dy_slider_value+DY_SLIDE_SPEED;
SCROLLBAR0_value=SCROLLBAR_GetValue(hItem);
//xprintf("SCROLLBAR0_value:%d\r\n",SCROLLBAR0_value);
if(SCROLLBAR0_value==(SLIDE_STRIP_VALUE-10)){ //解锁屏幕
detete_last_win();
Createwin_mainpage();
}
break;
case TIMER_1: //时间的刷新率
sprintf((char*)tbuf,"%02d:%02d",RTC_TimeStruct.RTC_Hours,RTC_TimeStruct.RTC_Minutes);
hItem=WM_GetDialogItem(pMsg->hWin, ID_TEXT_0);
TEXT_SetText(hItem,tbuf);
WM_RestartTimer(pMsg->Data.v, TIME_REFRESH_RATE);
break;
}
break;
case WM_DELETE:
GUI_MEMDEV_Delete(icon_arrow_handle);
break;
default:
WM_DefaultProc(pMsg);
break;
}
}
/*********************************************************************
*
* Public code
*
**********************************************************************
*/
/*********************************************************************
*
* Createunlockwin
*/
WM_HWIN Createlockwin(void) {
WM_HWIN win[WIN_MAX_NUM]={0};
win[0]=WM_CreateWindowAsChild(LOCK_SCREEN_X, LOCK_SCREEN_Y, LOCK_SCREEN_XSIZE, LOCK_SCREEN_YSIZE,
WM_HBKWIN, WM_CF_SHOW, _cbDialog, 0);
lock_handle=win[0];
WM_CreateTimer(win[0], TIMER_0, LOCK_BAR_REFRESH_RATE, 0);
WM_CreateTimer(win[0], TIMER_1, TIME_REFRESH_RATE, 0);
switch_win(win,LOCK_WIN_ID);
return win[0];
}
// USER START (Optionally insert additional public code)
// USER END
/*************************** End of file ****************************/
GUI线程代码 gui_thread.c
#include "GUI_app/gui_thread.h"
#include "stm32f4xx.h"
#include "GUI.h"
#include "WM.h"
#include "serial.h"
#include "LCD/lcd.h"
/*********************************************************************************************
* GUI全局配置变量
*********************************************************************************************/
WM_HWIN _hLastFrame[WIN_MAX_NUM]={0}; //当前所在窗口的句柄,全局
unsigned char Last_win_id; //当前所在窗口的ID,全局
GUI_MEMDEV_Handle hMempic;
GUI_PID_STATE pid_state;
unsigned short LCD_xsize;
unsigned short LCD_ysize;
extern GUI_CONST_STORAGE GUI_BITMAP bmIOS15_1;
extern struct graphic_device g_dev;
extern WM_HWIN Createlockwin(void);
extern WM_HWIN Createwin_mainpage(void);
extern WM_HWIN CreateFramewin(void);
extern WM_HWIN Createstatus_bar(void);
extern GUI_CONST_STORAGE GUI_BITMAP bmicon_smile;
/*********************************************************************************************
* 声明
*********************************************************************************************/
#if(USE_GUI_EXAMPLE==2)
static void touch_app_1(void);
static void gui_app_1(void);
static void gui_app_2(void);
#endif
#if(USE_GUI_EXAMPLE==1)
static void gui_alloc_GetNumFreeBytes(void);
#endif
void switch_win(WM_HWIN* win,unsigned char id)
{
memcpy(_hLastFrame,win,sizeof(WM_HWIN)*WIN_MAX_NUM);
Last_win_id=id;
}
void detete_last_win(void)
{
char i;
WM_HWIN temp;
for(i=0;i<WIN_MAX_NUM;i++){
if(_hLastFrame[i]!=0){
temp=_hLastFrame[i];
_hLastFrame[i]=0; //在父窗口删除前,先清理掉标志位。防止硬件错误。
WM_DeleteWindow(temp);
}
}
}
/*********************************************************************************************
* 名称:emwin_init()
* 功能:emWin初始化
* 参数:无
* 返回:无
* 修改:
* 注释:
*********************************************************************************************/
static void emwin_init(void)
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_CRC, ENABLE); // 开启CRC时钟
GUI_Init(); // emWin初始化
WM_SetCreateFlags(WM_CF_MEMDEV); // 窗口启用内存设备
GUI_UC_SetEncodeUTF8(); // 使用UTF-8编码
GUI_EnableAlpha(1); // 开启透明效果
// WM_MULTIBUF_Enable(1); // 开启多缓存
WM_MOTION_Enable(1); // 窗口移动支持
}
static void emwin_init_parameter(void)
{
LCD_xsize=LCD_GetXSize();
LCD_ysize=LCD_GetYSize();
}
/*********************************************************************************************
* 函 数 名: _cbBkWindow
* 功能说明: 桌面窗口回调函数
* 形 参:pMsg 参数指针
* 返 回 值: 无
*********************************************************************************************/
static void _cbBkWindow(WM_MESSAGE* pMsg)
{
switch (pMsg->MsgId)
{
case WM_PAINT:
GUI_SetBkColor(GUI_WHITE); //自定义调色
GUI_Clear();
break;
case MSG_LOCK:
detete_last_win();
Createlockwin();
break;
default:
WM_DefaultProc(pMsg);
}
}
/*********************************************************************************************
* 名称:gui_thread_entry()
* 功能:GUI线程入口函数
* 参数:*parameter -> 入口参数(暂无)
* 返回:无
* 修改:
* 注释:
*********************************************************************************************/
void gui_thread_Task(void *parameter)
{
(void)parameter;
unsigned int time=0;
emwin_init();
emwin_init_parameter();
WM_SetCallback(WM_HBKWIN, &_cbBkWindow); //设置桌面窗口的回调函数
Createstatus_bar();
// Createlockwin();
Createwin_mainpage();
while(1)
{
#if(USE_GUI_EXAMPLE==1)
gui_alloc_GetNumFreeBytes(); // 获取GUI VM管理器的剩余内存
// gui_app_1(); // 测试DEMO
// touch_app_1(); // 测试DEMO
#endif
GUI_TOUCH_Exec(); // 触摸刷新
GUI_Delay(GUI_TASK_DELAY); // GUI刷新并延时
// 触发锁屏
if(Last_win_id!=LOCK_WIN_ID){
time++;
if(time*GUI_TASK_DELAY>=(unsigned int)LOCK_DELAY*1000){
WM_SendMessageNoPara(WM_HBKWIN,MSG_LOCK);
time=0;
}
// 重置计时
if(time%20==0){ //降低消耗
GUI_TOUCH_GetState(&pid_state);
}
if(pid_state.Pressed){
time=0;
pid_state.Pressed=0;
}
}
}
// vTaskDelete(NULL);
}
#if(USE_GUI_EXAMPLE==1)
// 获取GUI当前的剩余内存
static void gui_alloc_GetNumFreeBytes(void)
{
uint32_t ram;
static uint32_t times;
times++;
if(times%1000==0){
ram=GUI_ALLOC_GetNumFreeBytes(); //获取GUI剩余内存空间
xprintf("ram is %d\r\n",ram);
}
}
#endif
#if(USE_GUI_EXAMPLE==2)
//测试验证读点函数
static void gui_app_2(void)
{
GUI_SetColor(GUI_YELLOW);
GUI_SetDefaultFont(&GUI_Font8x16);
GUI_SetFont(&GUI_Font8x16);
GUI_SetBkColor(GUI_BLUE);
GUI_Clear();
GUI_SetPenSize(10);
GUI_SetColor(GUI_RED);
GUI_DrawLine(20, 10, 180, 90); //某个指定起点到某个指定终点之间的线,前面是点1的XY
GUI_DrawLine(20, 90, 180, 10);
GUI_SetBkColor(GUI_BLACK);
GUI_SetColor(GUI_WHITE);
GUI_SetTextMode(GUI_TM_NORMAL); //设置为显示正常文本
GUI_DispStringHCenterAt("GUI_TM_NORMAL", 100, 10);
GUI_SetTextMode(GUI_TM_REV); //设置为显示反转文本,就是字体和背景颜色反转颜色
GUI_DispStringHCenterAt("GUI_TM_REV", 100, 26);
GUI_SetTextMode(GUI_TM_TRANS); //设置为显示透明文本
GUI_DispStringHCenterAt("GUI_TM_TRANS", 100, 42);
GUI_SetTextMode(GUI_TM_XOR); //设置为反相显示的文本,会存在读点颜色
GUI_DispStringHCenterAt("GUI_TM_XOR", 100, 58);
GUI_SetTextMode(GUI_TM_TRANS | GUI_TM_REV); //反转文本和透明背景
GUI_DispStringHCenterAt("GUI_TM_TRANS | GUI_TM_REV", 100, 74);
}
//验证
static void gui_app_1(void)
{
static const GUI_COLOR color[3][2] = {
{0x00FFFF, 0x0000FF}, // 黄色 -> 红色
{0xFFFF00, 0x00FF00}, // 青色 -> 绿色
{0xFF00FF, 0xFF0000}, // 紫色 -> 蓝色
};
static short x = 0, y = 0;
static unsigned char num = 0;
if(x >= g_dev.lcd_dev->width) // 制造位移变色效果
{
x = -60; //X复位
y += 20; //Y方向下移
if(y >= g_dev.lcd_dev->height)
{
num++; //变化颜色
if(num >= 3)
num = 0;
y = 0; //Y复位
}
}
// 绘制用水平颜色梯度填充的矩形
GUI_DrawGradientH(x, y, x+60, y+20, color[num][0], color[num][1]);
x++;
}
//验证emwin是否正常回调触摸刷新
static void touch_app_1(void)
{
int x_value=GUI_TOUCH_GetxPhys();
int y_value=GUI_TOUCH_GetyPhys();
xprintf("x:%d,y:%d\r\n",x_value,y_value);
}
#endif
gui_thread.h
#ifndef __GUI_THREAD_H_
#define __GUI_THREAD_H_
#include "GUI.h"
#include "WM.h"
// 窗口消息定义
#define MSG_SWITCH (WM_USER + 1)
#define MSG_MAIN_PAGE_SWITCH (WM_USER + 2)
#define MSG_WIN_INVAILD (WM_USER + 3)
#define MSG_LOCK (WM_USER + 4)
// 通知父窗口消息定义
#define NOTIFICATION_UNLOCK (WM_NOTIFICATION_USER+1)
// 窗口ID
#define LOCK_WIN_ID 1
#define MIAN_PAGE_WIN_ID 2
#define WIN_MAX_NUM 5 //页面支持的最大窗口数量
// 外部引用声明
extern WM_HWIN _hLastFrame[WIN_MAX_NUM]; //当前所在窗口的句柄,全局
extern unsigned char Last_win_id; //当前所在窗口的ID,全局
extern unsigned short LCD_xsize;
extern unsigned short LCD_ysize;
// 函数声明
void gui_thread_Task(void *parameter);
void lock(void); //创建解锁画面
void switch_win(WM_HWIN* win,unsigned char id); //切换窗口需要引用
void detete_last_win(void);
#endif //__GUI_THREAD_H_
config.h
#ifndef __CONFIG_H__
#define __CONFIG_H__
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "semphr.h"
#include "stdio.h"
#include "string.h"
/* Hardware and starter kit includes. */
#include "stm32f4xx.h"
#include "stm32f4xx_conf.h"
/*************全局config文件*************/
/*************ESP32配置*************/
//#define CAR_MACADDR "40:22:d8:eb:49:bc" //设置小车的目标地址
#define CAR_MACADDR "" //设置小车的目标地址
/*************STemWin532*************/
#define PKG_STEMWIN_MEM_SIZE 120 //STemWin532使用的动态内存大小,内存设备需要较大的RAM
#define GUI_NUMBYTES (PKG_STEMWIN_MEM_SIZE * 1024)
/* Define the average block size */
#define GUI_BLOCKSIZE 0x80 //块大小
/* 电阻触摸屏的AD定义 校准使用 */
#define TOUCH_AD_LEFT 170
#define TOUCH_AD_RIGHT 3850
#define TOUCH_AD_TOP 265
#define TOUCH_AD_BOTTOM 3950
/* GUI线程 */
#define GUI_TASK_DELAY 5 //GUI主线程延时,单位ms
#define LOCK_DELAY 120 //屏幕没有触发后时间锁定,单位s
#define USE_GUI_EXAMPLE 0 //GUI开启示例
#define STATUS_BAR_HEIGHT 15 //单位像素
/*************微秒级函数*************/
void hw_us_delay(unsigned int us); //微秒级延时
unsigned int xtime(void); //获取系统的运行时间us
/*************中断优先级配置*************/
#define USART1_INT_PRIORITY 7
#define USART3_INT_PRIORITY 7
#define RTC_ALARM_INT_PRIORITY 10
#define CPU_USAGE_TIMER_PRIORITY 6
/*************CLI示例命令*************/
#define CLI_USE_EXAMPLE 0
/*************CPU使用率统计*************/
#define CPU_USAGE_USE_TIM 0
/*************定时器使用*************/
#if(CPU_USAGE_USE_TIM==1)
#define CPU_USAGE_TIMER TIM6
#define CPU_USAGE_TIMER_RCC RCC_APB1Periph_TIM6
#define CPU_USAGE_TIMER_IRQ TIM6_DAC_IRQn
#endif
#endif
源代码链接:
https://download.csdn.net/download/W809291634/88362696
因没有时间去优化,是一个测试代码,此源码存在以下问题:
1、没有使用带OS enwin库,所以建议单线程使用emwin的API,比如,不要在两个线程中使用到emwin的API,否则可能会出现硬件错误
2、串口DMA接收处理使用的其中的一种方法,可以使用环形缓存区进行改进
3、基本上测试稳定,有很大的优化空间