[DigiKey "Smart Manufacturing, Non-stop Happiness" Creative Competition] Porting FreeRTOS + LVGL + Lwip to implement TCPclient
[Copy link]
【Foreword】
Previously, I used rtthread studio+lvgl to implement a basic demo, but there were problems in porting lwip, so I changed to freertos+lvgl+lwip to build the development environment.
【Development environment】
Win11 + STM32CubeIde
【Transplantation steps】
- Install stm32cubeide. The official website has detailed tutorials, which will not be explained in detail here.
- After installation, open stm32cubeide, create a new stm32 project, and select stm32f746G-Discovery as the target development board. Generate the project according to the default options. The default OS running in the project is freeRTos.
- Download the open source source code of stm32f746-discoer from github: git clone --recursive
- After downloading, we copy the STM32F746G-Discovery and Components in the lvgl, hal_stm_lvgl and Uilitites directories shown in the figure below to the specified directory of the project.
- Copy lvgl.conf.h to the project directory.
- After compiling, follow the prompts to add the directory referenced by the file. I will not record them one by one here.
- Add Lwip. In the configuration interface, we turn on LWIP, disable DHCP, and configure the network card according to the development environment.
- Select the network PHY chip. Our version uses LAN8742:
- Add two tasks in freertos, task 1 is lvgl, task 2 is lwip, and create a queue for communication between the two tasks:
- In Task 1, we add a button and a label in lvgl. The code is as follows:
lv_obj_t *label;
void lvgl_lable_test(){
/* 创建??????个标?????? */
label = lv_label_create(lv_scr_act());
if (NULL != label)
{
// lv_obj_set_x(label, 90); // 设置控件的X坐标
// lv_obj_set_y(label, 100); // 设置控件的Y坐标
// lv_obj_set_size(label, 60, 20); // 设置控件大小
lv_label_set_text(label, "Counter"); // 初始显示 0
// lv_obj_center(label); // 居中显示
lv_obj_align(label, LV_ALIGN_CENTER, 0, -50); // 居中显示后,向上偏移50
}
}
/**
* [url=home.php?mod=space&uid=159083]@brief[/url] 按钮事件回调函数
*/
static void btn_event_callback(lv_event_t* event)
{
static uint32_t counter = 1;
lv_obj_t* btn = lv_event_get_target(event); //获取事件对象
if (btn != NULL)
{
lv_label_set_text_fmt(label, "%d", counter); //设置显示内容
lv_obj_align(label, LV_ALIGN_CENTER, 0, -50); // 居中显示后,向上偏移50
if(osMessagePut(myQueue01Handle, counter, 100) != osOK)
{
printf("send error\r\n");
}
counter++;
}
}
/**
* @brief 创建按钮
*/
void lvgl_button_test(){
/* 在当前界面中创建??????个按?????? */
lv_obj_t* btn = lv_btn_create(lv_scr_act()); // 创建Button对象
if (btn != NULL)
{
lv_obj_set_size(btn, 80, 20); // 设置对象宽度和高??????
// lv_obj_set_pos(btn, 90, 200); // 设置按钮的X和Y坐标
lv_obj_add_event_cb(btn, btn_event_callback, LV_EVENT_CLICKED, NULL); // 给对象添加CLICK事件和事件处理回调函??????
lv_obj_align(btn, LV_ALIGN_CENTER, 0, 50); // 居中显示后,向下偏移50
lv_obj_t* btn_label = lv_label_create(btn); // 基于Button对象创建Label对象
if (btn_label != NULL)
{
lv_label_set_text(btn_label, "button"); // 设置显示内容
lv_obj_center(btn_label); // 对象居中显示
}
}
}
void StartTask1(void const * argument)
{
/* init code for USB_HOST */
MX_USB_HOST_Init();
/* init code for LWIP */
// MX_LWIP_Init();
/* USER CODE BEGIN StartTask1 */
lv_init();
tft_init();
touchpad_init();
lvgl_lable_test();
lvgl_button_test();
// client_socket_init();
/* Infinite loop */
for(;;)
{
lv_task_handler();
osDelay(10);
}
/* USER CODE END StartTask1 */
}
- Task 2 is to create the lwip task, which is mainly to connect to the TCP server and wait for the key to send information. If the queue message is received, the message will be sent to the TCP server.
void StartTaskLwip(void const * argument)
{
/* USER CODE BEGIN StartTaskLwip */
osEvent event;
MX_LWIP_Init();
int sock;
struct sockaddr_in address;
uint8_t send_buf[64]= {0};
/* create a TCP socket */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Socket error\n");
return;
}
address.sin_family = AF_INET;
address.sin_port = htons(PORT);
address.sin_addr.s_addr = inet_addr(IP_ADDR);
memset(&(address.sin_zero), 0, sizeof(address.sin_zero));
if (connect(sock,(struct sockaddr *)&address,sizeof(struct sockaddr)) == -1)
{
printf("Connect failed!\n");
closesocket(sock);
}
else
{
printf("Connect to iperf server successful!\n");
}
while (1)
{
event = osMessageGet(myQueue01Handle, 100);
if(event.status == osEventMessage)
{
sprintf(send_buf,"get messege %d\r\n",event.value.v);
if (write(sock,send_buf,sizeof(send_buf)) < 0)
break;
memset(send_buf,0,sizeof(send_buf));
}
vTaskDelay(10);
}
closesocket(sock);
/* USER CODE END StartTaskLwip */
}
- At the same time, we need to open the two macros LWIP_NETCONN and LWIP_SOCKET in lwipopts.h, as follows:
By then, our transplantation work will be completed.
[Experimental results]
We press the button on the touch screen and receive the information sent by the development board on the TCP server:
【Experience】
Stm32cubeIDE has been officially upgraded and is now becoming more and more user-friendly. In addition, the official driver has been provided for the development board, allowing developers to get started very quickly. FreeRTos is much better than RTT. It seems that domestic RTT still has a long way to go and the ecosystem needs to be further strengthened.
|