- 2024-10-16
-
发表了主题帖:
【匠芯创D133CBS】LVGL的应用 2
上一篇做的UI虽然算是LVGL的应用,但是由于SRAM_S0溢出报错,并且不会配置到PSRAM导致用一个比较笨的方式来展现了匠芯创D133CBS开发板的显示功能,但是根本体现不了其强悍,而且也是我的一种遗憾,后来请教坛友@dirty,有幸得其指导,非常顺利的将PSRAM配置成功,并且做了最后的完善。本篇就来细说一下如何配置PSRAM与智慧餐厅的大致效果。
首先介绍PSRAM如何配置:如图1所示。进入到该界面都将其改成PSRAM即可。
图1 匠芯创D133CBS芯片配置PSRAM
图2 匠芯创D133CBS芯片配置后的界面
如果将上面都配置好之后,再进行编译,基本上就不会出现报错了。
接下来展示一下我添加的功能,基本上智慧餐厅的显示屏上基本上就是显示菜品,价格和支付的二维码,我就简单的使用了GUI-guider进行了界面搭建,主要使用的控件有label,image和qrcode这三种控件,使用GUI-guider是比较简单且方便的可以搭建大致的界面,但是在应用QRcode方面和图片方面是需要自己手动的添加一些代码和修改一些命名,否则是编译报错的。比如在QRcode方面,因为我们生成的C代码是没有包含QRcode部分代码的,所以需要自己手动添加。该库是我从这里克隆而来,如果大家有需要,可以复制过去,进行克隆即可:git clone https://github.com/littlevgl/lv_lib_qrcode.git
/**
* [url=home.php?mod=space&uid=1307177]@File[/url] lv_qrcode.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_qrcode.h"
#include "qrcodegen.h"
/*********************
* DEFINES
*********************/
#define QR_SIZE 140
/**********************
* TYPEDEFS
**********************/
/**********************
* STATIC PROTOTYPES
**********************/
/**********************
* STATIC VARIABLES
**********************/
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
/**
* Create an empty QR code (an `lv_canvas`) object.
* @param parent point to an object where to create the QR code
* @param size width and height of the QR code
* @param dark_color dark color of the QR code
* @param light_color light color of the QR code
* [url=home.php?mod=space&uid=784970]@return[/url] pointer to the created QR code object
*/
lv_obj_t * lv_qrcode_create(lv_obj_t * parent, lv_coord_t size, lv_color_t dark_color, lv_color_t light_color)
{
uint32_t buf_size = LV_CANVAS_BUF_SIZE_INDEXED_1BIT(size, size);
uint8_t * buf = lv_mem_alloc(buf_size);
LV_ASSERT_MALLOC(buf);
if(buf == NULL) return NULL;
lv_obj_t * canvas = lv_canvas_create(parent);
if(canvas == NULL) return NULL;
lv_canvas_set_buffer(canvas, buf, size, size, LV_IMG_CF_INDEXED_1BIT);
lv_canvas_set_palette(canvas, 0, dark_color);
lv_canvas_set_palette(canvas, 1, light_color);
return canvas;
}
/**
* Set the data of a QR code object
* @param qrcode pointer to aQ code object
* @param data data to display
* @param data_len length of data in bytes
* @return LV_RES_OK: if no error; LV_RES_INV: on error
*/
lv_res_t lv_qrcode_update(lv_obj_t * qrcode, const void * data, uint32_t data_len)
{
lv_color_t c;
c.full = 1;
lv_canvas_fill_bg(qrcode, c, LV_OPA_COVER);
if(data_len > qrcodegen_BUFFER_LEN_MAX) return LV_RES_INV;
uint8_t qr0[qrcodegen_BUFFER_LEN_MAX];
uint8_t data_tmp[qrcodegen_BUFFER_LEN_MAX];
memcpy(data_tmp, data, data_len);
bool ok = qrcodegen_encodeBinary(data_tmp, data_len,
qr0, qrcodegen_Ecc_MEDIUM,
qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX,
qrcodegen_Mask_AUTO, true);
if (!ok) return LV_RES_INV;
lv_img_dsc_t * imgdsc = lv_canvas_get_img(qrcode);
lv_coord_t obj_w = imgdsc->header.w;
int qr_size = qrcodegen_getSize(qr0);
int scale = obj_w / qr_size;
int scaled = qr_size * scale;
int margin = (obj_w - scaled) / 2;
uint8_t * buf_u8 = (uint8_t *)imgdsc->data + 8; /*+8 skip the palette*/
/* Copy the qr code canvas:
* A simple `lv_canvas_set_px` would work but it's slow for so many pixels.
* So buffer 1 byte (8 px) from the qr code and set it in the canvas image */
uint32_t row_byte_cnt = (imgdsc->header.w + 7) >> 3;
int y;
for (y = margin; y < scaled + margin; y+=scale) {
uint8_t b = 0;
uint8_t p = 0;
bool aligned = false;
int x;
for (x = margin; x < scaled + margin; x++) {
bool a = qrcodegen_getModule(qr0, (x - margin) / scale, (y - margin) / scale);
if(aligned == false && (x & 0x7) == 0) aligned = true;
if(aligned == false) {
c.full = a ? 0 : 1;
lv_canvas_set_px(qrcode, x, y, c);
} else {
if(!a) b |= (1 << (7 - p));
p++;
if(p == 8) {
uint32_t px = row_byte_cnt * y + (x >> 3);
buf_u8[px] = b;
b = 0;
p = 0;
}
}
}
/*Process the last byte of the row*/
if(p) {
/*Make the rest of the bits white*/
b |= (1 << (8 - p)) - 1;
uint32_t px = row_byte_cnt * y + (x >> 3);
buf_u8[px] = b;
}
/*The Qr is probably scaled so simply to the repeated rows*/
int s;
const uint8_t * row_ori = buf_u8 + row_byte_cnt * y;
for(s = 1; s < scale; s++) {
memcpy((uint8_t*)buf_u8 + row_byte_cnt * (y + s), row_ori, row_byte_cnt);
}
}
return LV_RES_OK;
}
/**
* Delete a QR code object
* @param qrcode pointer to a QR code obejct
*/
void lv_qrcode_delete(lv_obj_t * qrcode)
{
lv_img_dsc_t * img = lv_canvas_get_img(qrcode);
lv_img_cache_invalidate_src(img);
lv_mem_free(img->data);
lv_obj_del(qrcode);
}
/**********************
* STATIC FUNCTIONS
**********************/
图3 添加qrcode库
代码添加完成之后,在进行头文件的包含,正常来说QRcode就可以正常使用了。接下来说说图片image,在图片方面,首先编译会出现报错,提示路径不对,也就是说我们需要的是图片读取方式替换,并且将图片的路径进行替换,这样才可以,而且由于没有包含关于LVGL_PATH的头文件,这里需要注意添加对应的头文件才可以lv_img_set_src(ui->screen_img_1, LVGL_PATH(import/image/bg.png));这里的路径要根据你想要显示的图片的路径来哦,我这个是关于我自己的路径,因此,要想用的话需要自己改到自己的图片路径才可以,至此,关于代码部分就已经大致搞完了。接下来就是展示~
图4 GUI Guider绘制的大致界面
图4 实际显示界面
- 2024-10-15
-
回复了主题帖:
【匠芯创D133CBS】--6.LVGL界面移植
dirty 发表于 2024-10-15 11:42
强,搞定了,感谢大佬,哈哈,解惑了
-
回复了主题帖:
【匠芯创D133CBS】--6.LVGL界面移植
dirty 发表于 2024-10-14 19:43
都选psram,配置命令里可以找到
你好,大佬,我昨晚试了一下在meconfig中没找到,能大致说说me配置,关于PSRAM路径吗?还是因为工程的不一样导致的?我用的是官方例程11.d13x demo88-nor rt-thread helloworld
- 2024-10-14
-
发表了主题帖:
【匠芯创D133CBS】LVGL的应用
本篇为大家带来的是LVGL的应用,匠芯创D133CBS开发板的MCU性能非常强悍,从图1就可以看出,一颗MCU其实可以说是MPU也不过分,其存储配置就非常适合做屏幕应用,并且显示方面支持720P/60FPS的刷新速率,支持2D加速等等非常优秀的功能。因此,把玩一下屏幕是必要的。
图1 匠芯创D133CBS芯片参数说明
LVGL(Light and Versatile Graphics Library)是一个开源的嵌入式图形库,专为资源受限的嵌入式系统设计。它提供了丰富的图形用户界面(GUI)组件,如按钮、标签、图表、滑块等,支持触摸屏和鼠标输入,并且具有高度的可定制性。现在新版本的lvgl制作的UI更加炫酷,因此,现在使用LVGL的用户越来越多。
匠芯创支持的屏幕三方应用有很多,比如QT,LVGL,在LVGL方面还支持使用LVGL官方的SquareLine Studio可视化辅助软件,NXP的GUI Guider等等,所以在使用LVGL方面具有一定的便利性。
本次使用LVGL的V8.3.5移植到匠芯创D133CBS开发板之中。同时使用NXP的GUI Guider来辅助配置GUI界面。
图2 NXP GUI Guider的使用
在创建完成之后,就可以设计自己所需要的界面了,本次我设计的是智慧食堂方面的支付界面。
图3 设计的GUI界面
图4 GUI Guider的仿真界面
有人可能就会问了,你这么大的屏幕为什么设计这么小的界面,其实我心里也不想,哈哈,因为我之前按照1024*600的尺寸设计界面,虽然设计的很漂亮,但是发现编译提示我SRAM_S0溢出的错误,虽然看到坛友说可以通过将存储方面配置成SPRAM上即可,但是我没会配置,哈哈,所以就索性为了避免SRAM_S0溢出的风险,就将画布尺寸缩小到了320*240的大小。图4就是使用GUI Guider仿真的效果图,仿真的时候也会生成C工程文件,这里我们只需要三个文件夹就好。
图5 移植所需的文件
本人参考坛友的操作确实模块化了许多,代码十分的规整,参考链接https://bbs.eeworld.com.cn/thread-1292138-1-1.html,这里要感谢@ dirty坛友。接下来可以参考坛友的移植方式,保姆级的移植方式值得参考,移植好之后,就可以使用me命令进行功能配置了。配置界面和路径如下:
图6 me配置的界面,使能所需的UI
在配置好之后,就可以正常编译了,如果UI的部分会占用很大空间的话,大部分会报错SRAM_S0溢出问题。我是采用缩小UI画布的方式解决的,当然,我这种不算是解决,算是临时测试,真正想要解决的还是要将存储部分配置好
图7 SRAM_S0溢出问题
至此,如果没有遇到SRAM_S0溢出问题,那么大概率是能编译通过的,编译通过之后就可以将生成的固件烧录到开发板之中了。
图8 LVGL效果图
- 2024-10-13
-
回复了主题帖:
【匠芯创D133CBS】--6.LVGL界面移植
大佬您好,这个SRAM_S0溢出报错,这时配置到PSRAM即可,这里一般怎么配置呀?
-
发表了主题帖:
【匠芯创D133CBS】485的应用
本帖最后由 yangjiaxu 于 2024-10-13 12:31 编辑
今天与大家来分享【匠芯创D133CBS】的485通讯的应用,因为我想设计一个HMI显示屏功能,现在市面上的HMI显示屏一般是通过网口或者是串口进行通讯的,但是如果实际应用方面HMI显示屏的应用数量比较多,其实是可以通过485实现通信的,这样不仅可以方便现场施工布线,也可以降低应用架构的成本。
本次通过D133CBS开发板背面的电路布局设计来看,是有485通信电路的,并且根据电路原理图得知,该电路采用的是自适应2线485通讯,因此我们可以通过外接485实现与D133CBS开发板进行数据交互。
图1 D13x7寸开发板(D133CBS)的背面,485电路部分
接下来就是编写程序了,根据官方提供的demo可以看出,如何应用和调用串口通讯,这里将官方的串口例程修改为uart1路径,之后在里面加入自己需要的应用函数即可。修改的文件路径如下luban-lite\bsp\examples\test-uart。
图2 串口通讯例程位置
代码:
//uart.c
#include <getopt.h>
#include <string.h>
#include <rtthread.h>
#include <aic_core.h>
//#include "beep.h"
#define SAMPLE_UART_NAME "uart1"
#define TIMEOUT_NONE -4096
static struct rt_semaphore rx_sem;
static rt_device_t serial;
static char str_send[] = "12";
uint8_t g_recv_max = 128;
static int g_uart_test_result = 1;
static int g_exit = 0;
static int g_timeout = TIMEOUT_NONE;
static rt_timer_t uart1_rx_timeout = RT_NULL;
char str_receive[128 + 1] = {0};
typedef struct
{
uint8_t buf[128];
uint8_t len;
uint8_t rx_over;
} uart_rx_dat_t;
uart_rx_dat_t uart1_rx_dat = { 0 };
static void uart1_rx_timeout_cb(void *p)
{
rt_timer_stop(uart1_rx_timeout);
rt_kprintf("read_length: %d \n", uart1_rx_dat.len);
uart1_rx_dat.rx_over = RT_TRUE;
}
rt_err_t uart1_input(rt_device_t dev, rt_size_t size)
{
char ch;
//rt_sem_release(&rx_sem);
if(rt_device_read(serial, -1, &ch, 1)==1)
{
uart1_rx_dat.buf[uart1_rx_dat.len++] = ch;
rt_timer_start(uart1_rx_timeout);
}
return RT_EOK;
}
void serial_uart1_thread_entry(void *parameter)
{
uint8_t jx=0;
char ch;
int ret = 0;
int cnt = 0;
static int timeout_time = 0;
static uint8_t rx_one_byte_flag = 1;
while (1)
{
if(uart1_rx_dat.rx_over == RT_TRUE)
{
uart1_rx_dat.rx_over = RT_FALSE;
rt_kprintf("read_dat: ");
for(jx=0; jx<uart1_rx_dat.len; jx++)
{
rt_kprintf("%02x ", uart1_rx_dat.buf[jx]);
}
rt_kprintf("\n");
uart1_rx_dat.len=0;
if( uart1_rx_dat.buf[0]==0xff & uart1_rx_dat.buf[1]==0x2a)
{
if(uart1_rx_dat.buf[2]==0x01)
{
//beep_on();
rt_device_write(serial, 0, &uart1_rx_dat, 4);
}
else if(uart1_rx_dat.buf[2]==0x00)
{
//beep_off();
rt_device_write(serial, 0, &uart1_rx_dat, 4);
}
}
}
rt_thread_mdelay(5);
}
}
int test_uart_485(int argc, char *argv[])
{
int c = 0;
rt_err_t ret = RT_EOK;
static rt_uint8_t open_cnt = 0;
//查找串口设备
serial = rt_device_find(SAMPLE_UART_NAME);
if (!serial)
{
rt_kprintf("find %s failed!\n", SAMPLE_UART_NAME);
return -RT_ERROR;
}
//初始化信号量
rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO);
//打开串口设备
ret = rt_device_open(serial, RT_DEVICE_OFLAG_RDWR | RT_DEVICE_FLAG_INT_RX);
if (ret != RT_EOK)
{
rt_kprintf("open %s failed : %d !\n", SAMPLE_UART_NAME, ret);
return -RT_ERROR;
}
//设置接收回调函数
rt_device_set_rx_indicate(serial, uart1_input);
//rt_device_write(serial, 0, str_send, (sizeof(str_send) - 1));
//创建 serial 线程
rt_thread_t thread = rt_thread_create("serial", serial_uart1_thread_entry, RT_NULL, 1024*2, 26, 10);
if (thread != RT_NULL) {
rt_thread_startup(thread);
} else {
rt_device_close(serial);
return -RT_ERROR;
}
//创建接收超时定时器
uart1_rx_timeout = rt_timer_create("serial_timer", uart1_rx_timeout_cb, RT_NULL, 50, RT_TIMER_FLAG_PERIODIC);
return ret;
}
MSH_CMD_EXPORT(test_uart_485, Uart Test);
编写好代码之后需要进行硬件me配置,进入me之后,选择uart1 使能,配置其波特率,数据位停止位等等,并且要配置其为rs485 compact io。
图3 开发板在me环境下,配置uart1
图4 开发板在me环境下,配置为485 compact io
配置好之后记得保存,这里就可以正常编译了,编译完成之后,在调试串口中输入“aicupg”或者是按住uboot重新上电均可使开发板进入到烧录模式,这时我们选择烧录工具进行将刚刚编译好的固件进行烧录即可。
图5 代码编译成功
烧录成功之后,就可以在调试串口界面输入test_uart_485命令,这个命令可以自己通过应用函数修改“MSH_CMD_EXPORT(test_uart_485, Uart Test);”
输入之后即可进入到485通讯功能。这里的应用我简单的写的是开发板收到485的数据之后,利用串口1再返回去,因此在串口调试助手工具中可以看到发送与接收内容相同
图6 485测试界面
至此,关于485通讯部分已经调试通过了,在这里要感谢坛友@TL-LED,感谢坛友的点拨可以快速实现485通讯的调试工作,通过在调试485通讯的过程中遇到了不少麻烦,首先是与正常的单片机裸机通讯不同,这个仅使用C文件就可以,并且每一个C文件相当于一个线程,也就是每个文件相当于一个单片机进行工作。这种感觉非常奇妙,也让我从单线程的裸机通讯逐步学习并了解多线程的通讯方式,接下来我将尝试实现显示功能,敬请期待~
- 2024-09-23
-
回复了主题帖:
【匠芯创D133CBS】 RS485通信测试
TL-LED 发表于 2024-9-23 09:36
默认例程是没有打开的,需要在menuconfig中,打开此例程。
也就是进入到me,配置串口1为rs485 compact io 即可是么?这个我配置成功了,并且我用的是官方的原helloworld例程,原bsp文件夹下有个uart.c文件,我替换成你提供的c文件,编译没报错,但是发送test_uart_sample ,提示没找到该命令。正常操作是将你的uart.c复制到工程里就行吧?
-
回复了主题帖:
【匠芯创D133CBS】 RS485通信测试
大佬,这个例程我也试了一下,但是用串口ttl发送test_uart_sample提示我没有这个命令,是我这个函数没包含到主程序之中吗?是不是将uart.c复制到工程之中就可以呀?正常创建rtt线程是不是就算是包含到工程之中呢?
- 2024-09-11
-
回复了主题帖:
高频UPS
在600V直流电压下,如果对效率和电磁干扰要求较高,且功率需求较大,三电平拓扑结构可能是一个更好的选择。然而,如果成本和控制复杂度是主要考虑因素,两电平拓扑结构可能更合适。
-
回复了主题帖:
串口助手发送PWM光源指令,光源显示很奇怪?
PWM控制器的占空比设置可能存在问题,导致在某些亮度值时占空比没有变化;或者控制软件的逻辑可能存在问题,导致在某些亮度值时无法正确控制PWM输出
-
回复了主题帖:
想找关于初学模拟电子技术基础的教材
模电的话,我觉得TI的书可以看看,而且可以考虑使用仿真电路软件,自己多动手试试
-
回复了主题帖:
【Follow me第二季第2期】Arduino UNO R4 WiFi跟我一起练
这个模块还支持WiFi,确实不错,还用的乐鑫的ESP32,话说,这芯片是不是也要重新烧录自己的程序才行呢?还是直接用的AT啊?
-
回复了主题帖:
运放采样电路送到DSP上电偏差较大是什么原因?
运放失调电压,电源电压波动,温度漂移,输入信号源阻抗不匹配,运放增益带宽积不足都有可能引发你的问题的
-
回复了主题帖:
在树莓派上构建和部署 Node.js 项目
确实部署方面确实麻烦啊,而且主要是内核的兼容性,确实有些时候会有问题
-
回复了主题帖:
【ST NUCLEO-WB09KE测评】-1-开箱
这板子主要是测蓝牙方面是吗?无线方面,我觉得ST的无线方案好是好,就是比较难开发啊
-
回复了主题帖:
【ST NUCLEO-WB09KE测评】-2-基于CubeIDE的开发环境搭建
不错,其实ST的cubeIDE也挺好用的,还免自己的授权,主要调试也是比较方便
-
回复了主题帖:
【ST NUCLEO-WB09KE测评】-3-按键,小灯与串口打印测试
用HAL是不是很容易开发啊,哈哈,我看这个板子也挺好看,支持楼主一波
-
回复了主题帖:
【Follow me第二季第2期】开箱
这板子真的好看啊, 而且还是个沉金的,电路看起来真的很不错,还用了type-C接口
-
回复了主题帖:
【Follow me第二季第2期】配置开发环境
感觉arduino真的好多人在用,还说,用其做一些产品的话,移植和稳定性都是有保障的吗?
-
回复了主题帖:
【Follow me第二季第2期】任务一
用arduino真的不错,我觉得arduino就是为了避免重复造轮子,而且库也是真的多啊