硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1025|回复: 6
收起左侧

[技术讨论] STM32F407 裸机 emwin刷新越来越慢问题

[复制链接]

7

主题

22

回帖

43

积分

新手上路

积分
43
发表于 2022-12-21 19:32:52 | 显示全部楼层 |阅读模式
STM32F407上跑了emwin裸机程序,使用的是XTP2046电阻触摸屏,每10毫秒采集一次。当在界面连续点击GUI_ID_BUTTON0,会出现界面刷新变慢现象。
一开始以为是触摸采集的问题,所以我干脆在while(1)循环中模拟了触摸,代码如下。
上电开始的时候,界面还是可以比较正常的刷新,与while(1)中的延时一致,但执行到60次左右开始,刷新就比较慢了,大概要3~5秒刷新一次。
调试发现主要是卡在了GUI_Exec()这个函数,它执行的时间比较久,程序中我也加入了查看当前GUI内存使用的代码,我设置的是50K静态数组,
大概只用了10K左右。
有知道这个是什么原因的吗?

void main()
{
        /*
        *  初始化相关代码
        */
        int count = 0;
        int touch_times = 0;  // 记录触摸次数
        int gui_used_memory = 0; // 记录GUI当前使用内存
        int gui_max_used_memory = 0; // GUI最大使用的内存
        GUI_PID_STATE State;
        State.x = 695;
        State.y = 175;       
        while(1)
        {
                GUI_Delay(100);
                used_memory = GUI_ALLOC_GetNumUsedBytes();
                if(used_memory > max_used_memory)
                        max_used_memory = used_memory;
                count++;
                if(count == 5)  // 触摸按下
                {
                        touch_times++;
                        State.Pressed = 1;
                        GUI_PID_StoreState(&State);
                }
                else if(count >= 6)  // 触摸释放
                {
                        count = 0;
                        State.Pressed = 0;
                        GUI_PID_StoreState(&State);
                }
        }
}

/*界面中的回调函数*/
static void _cbCallback(WM_MESSAGE * pMsg)
{
        int NCode, Id;
        WM_HWIN hWin = pMsg->hWin;
        switch (pMsg->MsgId)
        {
                case WM_PAINT:
                        PaintDialog(pMsg);    // 主要是刷新几条直线
                        break;
                case WM_INIT_DIALOG:
                        InitDialog(pMsg);
                        break;
                case WM_NOTIFY_PARENT:
                        Id = WM_GetId(pMsg->hWinSrc);
                        NCode = pMsg->Data.v;
                        switch (Id)
                        {
                                case GUI_ID_BUTTON0:
                                        if(NCode==WM_NOTIFICATION_RELEASED)
                                        {
                                                PROGBAR_SetValue(WM_GetDialogItem(hWin,GUI_ID_PROGBAR0),0);
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT2), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT3), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT4), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT5), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT6), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT11), " ");  
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT12), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT13), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT14), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT26), " ");  
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT27), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT28), " ");
                                                TEXT_SetText(WM_GetDialogItem(hWin, GUI_ID_TEXT29), " ");
                                                WM_DisableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON0));
                                                WM_DisableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON1));
                                                WM_DisableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON2));
                                                WM_DisableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON3));
                                                WM_DisableWindow(WM_GetDialogItem(hWin,GUI_ID_EDIT0));
                                                GUI_Exec();
                                                Delay_ms(5);   // 纯粹的使用了for循环延时5毫秒
                                                BeepOn(300);   // 蜂鸣器响300毫秒
                                                WM_EnableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON0));
                                                WM_EnableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON1));
                                                WM_EnableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON2));
                                                WM_EnableWindow(WM_GetDialogItem(hWin,GUI_ID_BUTTON3));
                                                WM_EnableWindow(WM_GetDialogItem(hWin,GUI_ID_EDIT0));
                                                GUI_Exec();
                                        }
                                        break;
                                default:
                                        break;
                        }
                default:
                        WM_DefaultProc(pMsg);
        }
}

image.png

回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-12-22 10:45:21 | 显示全部楼层
代码设计有点问题,不能在窗口回调里面嵌套GUI_Exec之类的函数,应该在while大循环里面调用

image.png
回复

使用道具 举报

7

主题

22

回帖

43

积分

新手上路

积分
43
 楼主| 发表于 2022-12-22 11:47:51 | 显示全部楼层
eric2013 发表于 2022-12-22 10:45
代码设计有点问题,不能在窗口回调里面嵌套GUI_Exec之类的函数,应该在while大循环里面调用

这个代码是简化了的,实际在第一个Delay_ms()后还会要开启定时器,然后驱动电机运行并进行ADC的采样,为了实时的更新界面进度条等(定时器中也会调用GUI_Exec()),执行完成后才会运行到BeepOn(), 这就不得不加了调用了GUI_Exec()进行界面的强制更新了。这里有没有什么好的办法可以避免这些不规范的调用,又能比较好的实时更新界面的一些中间的状态呢?是不是一定得上系统才行啊?
回复

使用道具 举报

3

主题

338

回帖

347

积分

高级会员

积分
347
发表于 2022-12-22 15:16:59 | 显示全部楼层
本帖最后由 glory 于 2022-12-22 15:18 编辑

在按钮回调事件中调用GUI_Exec()是符合规范的,比如经常在按钮事件中显示消息框或者对话框,用的是
GUI_MessageBox()或者GUI_ExecCreatedDialog()或者GUI_ExecDialogBox()函数吧,这些函数其实就是先创建Window,然后调用GUI_Exec();
直到对话框关闭再返回。这跟你直接调用GUI_Exec()没两样。
楼主的问题应该不是因为这个,另找原因吧。
回复

使用道具 举报

1万

主题

6万

回帖

10万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
107049
QQ
发表于 2022-12-22 15:27:46 | 显示全部楼层
circlegan 发表于 2022-12-22 11:47
这个代码是简化了的,实际在第一个Delay_ms()后还会要开启定时器,然后驱动电机运行并进行ADC的采样,为 ...

最好就是while大循环里面调用GUI_Delay或者GUI_Eexec。完全处理的过你的控件更新的。

然后就是需要周期更新,或者查询状态更新的控件,使用emWin自带的定时器功能比较方便。
就楼主当前的这些控件内容展示,F407完全处理的过来,应该就是实现方式上有点问题。

回复

使用道具 举报

7

主题

22

回帖

43

积分

新手上路

积分
43
 楼主| 发表于 2022-12-24 13:22:40 | 显示全部楼层
glory 发表于 2022-12-22 15:16
在按钮回调事件中调用GUI_Exec()是符合规范的,比如经常在按钮事件中显示消息框或者对话框,用的是
GUI_Me ...

GUI_Exec()是会将界面中的所有句柄进行响应和重绘吧,这里的感觉就是调用多次后,里面的句柄越来越多了,花费的时间就越来越长了。不够GUI_X_Delay()一直没有得到运行,而且毫秒中断也不能再进去运行,就奇怪了
回复

使用道具 举报

7

主题

22

回帖

43

积分

新手上路

积分
43
 楼主| 发表于 2022-12-24 13:30:22 | 显示全部楼层
eric2013 发表于 2022-12-22 15:27
最好就是while大循环里面调用GUI_Delay或者GUI_Eexec。完全处理的过你的控件更新的。

然后就是需要周 ...

主要是要考虑到电机平稳运行和匀速ADC采样,如果不让电机自己来掌控时间的话,就有可能出现丢步或咔咔咔的声音,最后ADC采样也会有问题。
你的意思是我在这个界面再开一个定时器,然后只对几个需要更新的控件调用GUI_Exec()进行更新对吗?但调用了GUI_Exec()的话,那还是会和我目前调用的GUI_Exec()所产生的效果(后果)一样吧
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2024-5-16 01:01 , Processed in 0.173107 second(s), 28 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表