巡检机器人:
巡检机器人通过IP摄像头局域网把视频传到监控显示器,难点在于设计一个远程无线控制机器人控制系统。具有远程显示机器人运动状态,位置,巡行速度,有误异常,外接传感器状态等。
经过上几篇试用,已经对 IMXRT1050-EVKB 开发板资源掌握的差不多了。RT1052功能强大,板载接口丰富,适合项目原型开发。本项目难点在于移植frertoshe和GUI显示系统开发。对比当前主流的嵌入式 GUI 主要有:emWin(uCGUI),TouchGFX,Embedded Wizard GUI,uGFX 和 MicroChip GUI。
TouchGF,被ST收购,以界面华丽,流畅以及强劲的 TouchGFX Designer(即将发布正式版)著称。 官方地址:http://touchgfx.com/en/ 。 TouchGFX 是要收费的,
Embeded Wizard GUI 也是这两年才发布的嵌入式 GUI,同样以华丽,流畅的界面和强劲的GUIBuilder 著称。 官方地址:http://www.embedded-wizard.de/ Embeded Wizard GUI IDE 也是要收费的,免费的教育版本不能商用,需要***才能下载。
很早就注意到LittlevGL,LittlevGL 是一个免费的开源图形库,提供了创建嵌入式 GUI 所需的一切,具有易于使用的组件,美观的视觉效果和低内存占用等特点。支持触摸屏操作,移植简单方便,开发者一直在不断完善更新。
LittlevGL 自带了丰富的控件:窗口、按键、标签、list、图表等,还可以自定义控件;支持很多特效:透明、阴影、自动显示隐藏滚动条、界面切换动画、图标打开关闭动画、平滑的拖拽控件、分层显示、反锯齿、仅耗少量内存的字体等等。
LittlevGL 系统包括应用程序,LVGL图形库以及Driver特定驱动程序,其中应用程序创建GUI,并处理特定任务的应用程序。应用程序可以与图形库进行通信并创建GUI,它包含HAL硬件抽象层接口,用于注册显示和输入设备驱动程序。Driver 除了应用中用到的特定驱动程序,它包含用于驱动显示的功能,另外可选的是包含读取触摸板或者按键输入驱动程序。根据MCU的不同,有两种典型的显示硬件设置。一个内置LCD/TFT驱动,另一个没有内置驱动。在这两种情况下,都需要一个帧缓冲区来存储屏幕的当前图像。 I.MXRT1050/1060有TFT/LCD驱动程序,则可以通过RGB接口直接连接MCU液晶显示器。在这种情况下,帧缓冲器可以在内部RAM中(如果MCU有足够的RAM)或者在外部RAM中(如果MCU具有存储器扩展接口)。入手相当方便。
目前LittlevGL 源码下载地址。
https://github.com/lvgl/lvgl/blob/master/lvgl.h
https://gitee.com/mirrors/lvgl
移植过程分析:
1,修改屏幕分辨率
如果需要根据实际屏幕支持不同大小的分辨率,需要修改参数为如下设置。
在lv_conf_internal.h中修改分辨率大小。
#define LV_HOR_RES_MAX 480
#define LV_VER_RES_MAX 272
在fsl_elcdif.c中修改LCD屏的配置函数参数如下。
void ELCDIF_RgbModeGetDefaultConfig(elcdif_rgb_mode_config_t *config)
{
assert(config);
memset(config, 0,
sizeof(*config));
config->panelWidth = 1024U;
config->panelHeight = 600U;
config->hsw = 41;
config->hfp = 160; //4;
config->hbp = 160; //8;
config->vsw = 10;
config->vfp = 12;//4;
config->vbp = 23;//2;
config->polarityFlags =
kELCDIF_VsyncActiveLow |
kELCDIF_HsyncActiveLow |
kELCDIF_DataEnableActiveLow |
kELCDIF_DriveDataOnFallingClkEdge;
config->bufferAddr = 0U;
config->pixelFormat =
kELCDIF_PixelFormatRGB888;
config->dataBus =
kELCDIF_DataBus24Bit;
}
2.修改显存大小
在单芯片MCU的设计中,不采用外扩RAM的情况下,如何修改I.MXRT的内存大小来适配更大的图像显存。如下为了配置448K TCM的RAM空间,需要在SDK代码里面修改如下部分,在MCUXpresso配置里面设置内存分配大小,OCRAM需要保留最小64K空间,这是由于Boot ROM的要求。
第一步:startup文件修改
不需要配置GPR14寄存器,它和FlexRAM配置无关,只需要添加如下代码到启动文件中。
LDR R0, =0x400ac044
LDR R1, =0xaaaaaaa5 //FlexRAM 配置设置
STR R1,[R0]
LDR R0,=0x400ac040
LDR R1,=0x04
LDR R3,[R0]
ORR R2,R1,R3
STR R2,[R0]
需要注意的是,在使用前修改FlexRAM的配置,因此推荐将上述代码放在reset handler, NXP也提供了FlexRAM相关的使用应用笔记如下。
https://www.nxp.com/docs/en/application-note/AN12077.pdf
第二步:MPU文件修改
ARM只指定普通内存支持非对齐访问,而默认的SDK中只将芯片出厂默认内存配置为普通内存,因此需要将BOARD_ConfigMPU里面的配置做如下修改。
/* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(4, 0x20000000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_256KB);
/* Region 6 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(5, 0x20200000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_512KB);
/* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(6, 0x20040000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_128KB);
/* Region 5 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(7, 0x20060000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64KB);
/* Region 7 setting: Memory with Normal type, not shareable, outer/inner write back */
MPU->RBAR = ARM_MPU_RBAR(8, 0x20280000U);
MPU->RASR = ARM_MPU_RASR(0, ARM_MPU_AP_FULL, 0, 0, 1, 1, 0, ARM_MPU_REGION_SIZE_64KB); //Flexram
第三步:OCRAM使用的注意事项
如果数据全部放在OCRAM里面,需要注意清Cache,防止在LCD显示的时候,下一帧的数据将下一帧的数据重叠,导致出现花屏或者是屏幕抖动。一般来说,OCRAM用于存储局部变量、堆和栈。I/DTCM(FlexRAM组配置为TCM)可以直接通过CPU访问,绕过一级L1 cache,因此,建议将关键代码和需要快速处理的数据放在TCM,例如向量表等。
3,文件配置
LVGL有一个配置头文件lv_conf.h,它设置了库的基本参数,禁用未使用的模块和特性、在编译时调整内存缓存区的大小等等。 复制lvgl目录旁边的lvgl/lv_conf_template.h,并将其重命名为lv_conf.h。打开文件并将开头的“if 0”更改为“#if 1”以启用其内容。当然lv_conf.h也可以复制到其他地方,但是应该将LV_CONF_INCLUDE_SIMPLE定义到编译器选项中(例如,针对gcc编译器 -DLV_CONF_INCLUDE_SIMPLE ),并手动设置include的路径。
在配置文件中,至少检查这三个配置选项,并根据硬件进行修改。LV_HOR_RES_MAX 最大水平分辨率;LV_VER_RES_MAX 最大垂直分辨率;LV_COLOR_DEPTH 颜色深度,8 适用于RG332,16适用于RGB565或者32 用于RGB888 和ARGB8888。
最高参考NXP 官方SDK ,有移植好的案例,对开发事倍功半。
下面展示一下GUI界面:
WIFI模组通过配网流程
WIFI模组通过串口发送AT命令,得到模组回复,关键是判定AT是否成功。
/**
*设置需要得到的回复命令
*
*/
int SetNeedRespondData(char workState,char checkType, char *cmd, uint8_t *data, int dataLen, char *state)
{
int flag = 0;
memset(&gNeedRespond, 0, sizeof(TNeedRespond));
if(cmd)
{
memcpy(gNeedRespond.cmd, cmd, strlen(cmd));
flag = 1;
}
if(data && dataLen > 0)
{
memcpy(gNeedRespond.data, data, dataLen);
gNeedRespond.dataLen = dataLen;
flag = 1;
}
if(state)
{
memcpy(gNeedRespond.state, state, strlen(state));
flag = 1;
}
gNeedRespond.workState = workState;
gNeedRespond.checkType = checkType;
gNeedRespond.count = 3;
gNeedRespond.flag = flag;
return 0;
}
/**
*设置需要得到的回复命令
*
*/
int SetNeedRespondRespondState(char respondState)
{
if(gNeedRespond.flag)
{
gNeedRespond.respondState = respondState;
printf("SetNeedRespondRespondState respondState=%d
",gNeedRespond.respondState);
}
return 0;
}
/**
*获取需要回复命令缓存
*
*/
PNeedRespond GetNeedRespondData(void)
{
return &gNeedRespond;
}
/**
*清除需要回复命令缓存
*
*/
void ClearNeedRespondData(void)
{
memset(&gNeedRespond, 0, sizeof(TNeedRespond));
}
- case MODULE_WORK_STATE_NEED_CONNECT_AP:
- {
- printf("MODULE_WORK_STATE_NEED_CONNECT_AP
- ");
- needRespond = GetNeedRespondData();
- if( needRespond->workState == MODULE_WORK_STATE_NEED_CONNECT_AP)
- {
- //说明上一次的AT命令发送并且收到了成功的服务
- if(needRespond->respondState == RESPONDE_STATE_OK)
- {
- gModuleWorkState = MODULE_WORK_STATE_NEED_CHECK_CONNECT_AP_STATE;
- printf("MODULE_WORK_STATE_NEED_CONNECT_AP CMD OK
- ");
- ClearNeedRespondData();
- break;
- }
- else if(needRespond->respondState == RESPONDE_STATE_IDEL)
- {
- //说明还没收到回复
- break;
- }
- }
复制代码
https://v.youku.com/v_show/id_XNDkxMTkzNTc0NA==.html?x=&sharefrom=android&sharekey=eca5cd2c358cd171d0e71203a0b7c4fe4
https://v.youku.com/v_show/id_XNDkxMTkzNTc0NA==.html?x=&sharefrom=android&sharekey=eca5cd2c358cd171d0e71203a0b7c4fe4``