STM32F407 기반 LVGL 프로젝트 템플릿(MSP3526 디스플레이), FreeRTOS 및 베어 메탈 버전 포함

STM32F407에 LVGL 그래픽 라이브러리를 포팅 완료했으며, LCD 화면 모델은 MSP3526입니다. 다른 화면으로 교체하려면 LCD 드라이버를 직접 수정하면 되고, 프로젝트는 FreeRTOS 버전과 베어메탈 버전을 모두 포함합니다. SPI+DMA로 화면을 구동합니다.

이 LCD의 해상도는 320×480, 크기는 3.5인치이며, LCD 드라이버 칩은 ST7796이고 인터페이스는 SPI입니다. 정전식 터치 드라이버 칩은 FT6336U이며 IIC 인터페이스를 사용합니다.

MCU를 오버클럭한 상태에서 전체 화면 갱신 시 약 9FPS, 부분 갱신 시 30FPS 이상이 나오며, SPI 기준으로는 괜찮은 수치입니다.

전자/MCU 기술交流群: 2169025065

효과 사진

데모 영상: https://www.bilibili.com/video/BV1Ni421S7ta/






LVGL 소개

LVGL(Light and Versatile Graphics Library)는 무료 오픈소스 그래픽 라이브러리로, 임베디드 GUI를 만들기 위한 모든 것을 제공하며 사용하기 쉬운 그래픽 요소, 아름다운 시각 효과, 낮은 메모리 점유율을 특징으로 합니다.

주요 특징:

  • 풍부하고 강력한 모듈형 그래픽 컴포넌트: 버튼, 차트, 리스트, 슬라이더, 이미지 등
  • 고급 그래픽 엔진: 애니메이션, 안티앨리어싱, 투명도, 부드러운 스크롤, 레이어 블렌딩
  • 터치스크린, 키보드, 인코더, 버튼 등 다양한 입력 장치 지원
  • 다중 디스플레이 지원
  • 특정 하드웨어 플랫폼에 종속되지 않음
  • 설정 가능한 최소 리소스: 64 kB Flash, 16 kB RAM
  • UTF-8 기반 다국어 지원(중국어, 일본어, 한국어, 아랍어 등)
  • CSS 스타일의 Flexbox·Grid 레이아웃
  • OS, 외부 메모리, 하드웨어 가속 지원(STM32 DMA2D, NXP PXP, VGLite 내장)
  • 싱글 프레임 버퍼에서도 매끄러운 렌더링
  • 순수 C로 작성, C++ 호출 가능
  • Micropython 지원
  • 시뮬레이터 지원
  • 풍부한 예제와 온라인/PDF 문서
  • MIT 라이선스

최소 요구사항:

  • 16/32/64비트 마이크로컨트롤러 또는 프로세서
  • 권장 클럭 >16 MHz
  • Flash/ROM: >64 kB(권장 180 kB 이상)
  • RAM
    – 정적 RAM: 약 2 kB
    – 힙: >2 kB(권장 8 kB)
    – 동적 데이터: >2 kB(권장 16 kB), lv_conf.h의 LV_MEM_SIZE로 설정
    – 디스플레이 버퍼: >수평 해상도 픽셀(권장 10×수평 해상도)
    – MCU 또는 외부 컨트롤러 내 프레임 버퍼 하나
  • C99 이상 컴파일러

LVGL 공식 사이트: https://lvgl.io/

배선 설명

LCD屏 MCU/开发板 功能描述
GND GND LCD屏电源地
VCC 5V或3.3V LCD屏电源正极
LCD_CS PE6 LCD屏SPI片选
LCD_RST PC1 LCD屏复位
LCD_RS PC0 LCD屏命令/数据选择
SDI(MOSI) PB5 LCD屏SPI数据线,主机输出从机输入
SCK PB3 LCD屏SPI时钟线
LED 3.3V 背光LED(可以自己接IO口,用软件控制背光)
SDO(MISO) PB4 LCD屏SPI数据线,主机输入从机输出
CTP_SCL PB8 电容触摸屏控制器I2C时钟线
CTP_RST PB7 电容触摸屏控制器复位
CTP_SDA PB9 电容触摸屏控制器I2C数据线
CTP_INT PB6 电容触摸屏控制器中断信号

주의: 제 사진에 사용된 개발板的 PB4 핀은 양쪽 핀헤더에 없고 위쪽 JTAG 커넥터에 있습니다.

자료 및 프로그램 다운로드

화면 자료 온라인 문서: https://url.zeruns.com/68x3Y
화면 자료 패키지 다운로드1: https://www.123pan.com/s/2Y9Djv-rZevH.html
화면 자료 패키지 다운로드2: https://url.zeruns.com/gzBO4

베어메탈 STM32F407+LVGL 프로젝트 다운로드1: https://url.zeruns.com/X242k
베어메탈 STM32F407+LVGL 프로젝트 다운로드2: https://pan.baidu.com/s/1vAhHijYd_aWvRr3_c1_WtA?pwd=ry4g

FreeRTOS STM32F407+LVGL 프로젝트 다운로드1: https://www.123pan.com/s/2Y9Djv-CzevH.html
FreeRTOS STM32F407+LVGL 프로젝트 다운로드2: https://url.zeruns.com/0iOHF

Star 한 번만 눌러주세요!

프로그램 Gitee 오픈소스: https://gitee.com/zeruns/STM32F407_LVGL_Template_MSP3526
프로그램 GitHub 오픈소스: https://github.com/zeruns/STM32F407_LVGL_Template_MSP3526

Gitee·GitHub 최신 버전은 FreeRTOS를 사용하며, 베어메탈 버전은 릴리스 0.1.3에 있습니다.

STM32CubeMX로 생성한 프로젝트이며 Keil5+VScode+EIDE로 개발했습니다.
정점원자(正点原子) 튜토리얼을 참고해 포팅했습니다.

정점원자 LVGL 사용·포팅 영상 다운로드1: https://www.123pan.com/s/2Y9Djv-0ZevH.html
정점원자 LVGL 사용·포팅 영상 다운로드2: https://www.alipan.com/s/Pd6TDfT2rBL

사용 방법

코드를 다운로드받아 그대로 컴파일·다운로드하면 바로 작동합니다.
FPS와 메모리 점유율 표시를 끄려면 lv_conf.h에서 아래 두 매크로의 1을 0으로 바꾸세요.

/*1: Show CPU usage and FPS count*/
#define LV_USE_PERF_MONITOR 1
#if LV_USE_PERF_MONITOR
    #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
#endif

/*1: Show the used memory and the memory fragmentation
 * Requires LV_MEM_CUSTOM = 0*/
#define LV_USE_MEM_MONITOR 1
#if LV_USE_MEM_MONITOR
    #define LV_USE_MEM_MONITOR_POS LV_ALIGN_BOTTOM_LEFT
#endif
```![](upload://gM3vy1FSbkp0rfvCP6rg7bj5HDX.png)

FreeRTOS 버전을 사용하는 경우 `freertos.c` 파일에 코드를 작성하면 되며, STM32CubeMX 소프트웨어를 사용하여 스레드나 세마포어 등을 생성한 후 코드를 생성할 수 있습니다. 생성된 코드는 지정된 위치에 규격에 맞게 작성되며, 다시 생성해도 사용자가 작성한 코드에는 영향을 주지 않습니다. 베어 메탈 버전은 `main.c` 파일에 바로 코드를 작성하면 됩니다.

데모 프로그램을 종료하려면 아래 그림의 코드를 주석 처리하면 됩니다.

![](upload://rnrQUS1XVqXJTepVovvXcJek7T2.png)

## 부품 구매 링크

- STM32F407VET6 개발보드: [https://s.click.taobao.com/sQSMWmt](https://s.click.taobao.com/t?e=m%3D2%26s%3DGxUVgIOWBWVw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2IT%2BVhjqUP7X0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAhscfsB2%2FyzZJq71CBMBeP%2F1SarTXhIOTsgIpc1WFZiJNubylQlnZt0ft88oCh4qlKjZ0Zrpn9cYR7kNHbGZ5w15bTaW0%2FWfaQBd0yVbMw3IeTeL3FeYp0owmLWBgEm80VKxcI130SjETn2JhMaQNtYWLhXkoGmYygFktLIh%2BAXuBHaXkFVFVVsYOae24fhW0&union_lens=lensId%3APUB%401716477927%40212abf30_0d16_18fa60ea164_1890%40025BlJPZdLaOG4oFPxX7gKUY%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_5a7fc953-12f7-46f5-8abf-f0725f8174cf_)
- Daplink 다운로더: [https://s.click.taobao.com/9kMKWmt](https://s.click.taobao.com/t?e=m%3D2%26s%3DTHTCnVvsTHtw4vFB6t2Z2ueEDrYVVa64YUrQeSeIhnK53hKxp7mNFrMfIvbtZ%2F%2B2mFKI%2FmDcMIH0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAFBcM8wkWlGmBPeR%2FUFCetKLWMw3EOEsyJN2owMjhufwDudUsQ2T%2Bdnc9abdYtRqDTzYdoB%2FDOjstFZhpb%2ByhLzPbHWUbis%2BWsZGiFV6vs3eSWi1ViPhRlULEkqTedE399KEV1g6mN9AKChukhDzWey1fmH6DK4UhxgxdTc00KD8%3D&union_lens=lensId%3APUB%401716478245%4021673e1b_0d06_18fa6137a23_e4cb%40023uxCV3Edv0RnAmphuKflFP%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_be2f7d85-fcee-40ff-96c5-d9d5bd472c5d_)
- MSP3526 화면: [https://s.click.taobao.com/i1Z29nt](https://s.click.taobao.com/t?e=m%3D2%26s%3DepCXgq%2FZmWBw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2tJl3z4Kcvjj0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMA%2FEM5jbZlb7P9R7R4oT9ML5ESMSIvSnZOMN7NXhFCiynJvjSktgLu1nmUrf%2BRsjyAm8kA6wY1r21y2p9AgG%2F91VmfPAhbcEJheBtNII99o%2FtnjWeMZ%2B39PZGZ9wPRcXV%2BQ%2FMlsmagC3ST4aDEgnPNca8ZkUY0DmW2xiXvDf8DaRs%3D&skuId=5223178287593&union_lens=lensId%3APUB%401716478528%40212c5298_0d1d_18fa617cd1e_3501%40034rs5qkRnldNGhC5eLF4gZ4%40eyJmbG9vcklkIjo4NTQ2Nywiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfZGV0YWlsX2h0bSIsInNyY0Zsb29ySWQiiOiiI4MDY3NCJ9%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_18bdbb55-0a4c-494e-96fc-a14c1b4c6732_)
- 듀퐁 와이어: [https://s.click.taobao.com/W1wHWmt](https://s.click.taobao.com/t?e=m%3D2%26s%3DD%2BKEsm2G8bhw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2Sn8%2BqdSFAFT0JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAhscfsB2%2FyzZJq71CBMBeP%2F1SarTXhIOTsgIpc1WFZiJNubylQlnZt5Tr%2BZsTRXxVoTwQXkQy%2BZ5FeGSAzHUbnuYhpSNeyz6v9H5aeGRpz8mogVv1SEjhEYwmLWBgEm80VKxcI130SjETn2JhMaQNtYWLhXkoGmYyO0%2FufYOLJc1EEap0MMy2i8YOae24fhW0&union_lens=lensId%3APUB%401716478612%402104b45c_0cd2_18fa619123a_652e%40023dY61JLu6wYjo297E4L0ip%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_c09a2639-b75e-40a9-8886-2b13dfb05f6a_)
- STM32F407VGT6 개발보드: [https://s.click.taobao.com/VjC29nt](https://s.click.taobao.com/t?e=m%3D2%26s%3DimgWkSQh79Jw4vFB6t2Z2ueEDrYVVa64g3vZOarmkFi53hKxp7mNFrMfIvbtZ%2F%2B2VCC9Q%2BPYiL70JlhLk0Jl4QTquP0kWxBLBDnvz6xo38xspWc9%2BCL4bTGF1ceZMhPo8mL8HhJ3EdVrH4ks4QyiY4z4rjZDGVMAhscfsB2%2FyzZJq71CBMBeP%2F1SarTXhIOTsgIpc1WFZiJNubylQlnZt1PgRVjPwS2ItjXwer7KgrNYvdwnwfvUuaclSgSzfliuRVQ2zHzYrnKVyphVinEJT4wmLWBgEm80VKxcI130SjETn2JhMaQNtYWLhXkoGmYy0ZHJIUNbntFzUAbdwYp3usYOae24fhW0&union_lens=lensId%3APUB%401716478657%4021547cbb_0d71_18fa619c373_1476%40027J4l8QPFtC3F2VYygWUUdV%40eyJmbG9vcklkIjo4MDY3NCwiic3BtQiiI6Il9wb3J0YWxfdjJfcGFnZXNfcHJvbW9fZ29vZHNfaW5kZXhfaHRtIiiwiic3JjRmxvb3JJZCI6IjgwNjc0In0ie%3BtkScm%3AselectionPlaza_site_4358%3Bscm%3A1007.30148.329090.pub_search-item_a456d2bb-5c50-4eb6-a55f-0e6f4ff87eed_)

## 주요 코드 조각

주로 `lv_port_disp.c` 파일의 `disp_flush` 함수 안에서 아래 LCD 채우기 함수를 호출합니다. LCD 드라이버는 화면 제조사에서 제공한 예제를 기반으로 수정했습니다.

```c
/**
 * @brief LCD 화면 지정 사각형 영역 채우기
 * LVGL 라이브러리 색상값으로 LCD 지정 영역을 채웁니다.
 * @param sx 시작 X 좌표
 * @param sy 시작 Y 좌표
 * @param ex 끝 X 좌표
 * @param ey 끝 Y 좌표
 * @param color_p 채울 색상을 가리키는 포인터
 */
void LCD_Fill_LVGL(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey, lv_color_t *color_p)
{
	uint32_t i, j;
	uint16_t width = ex - sx + 1;	 // 채우기 영역 너비 계산
	uint16_t height = ey - sy + 1;	 // 채우기 영역 높이 계산
	uint32_t Pixel = width * height; // 채우기 영역 픽셀 수 계산
	LCD_SetWindows(sx, sy, ex, ey);	 // LCD 표시 창을 지정된 영역으로 설정

//	for (i = 0; i < height; i++)
//	{
//		for (j = 0; j < width; j++){
//			Lcd_WriteData_16Bit(color_p->full); // 데이터 쓰기
//		}
//	}

// 데이터 분할 값,分批 전송에 사용
#define data_split 3000

	uint8_t data[Pixel * 2]; // 색상 데이터 저장용 배열 생성

	for (i = 0; i < Pixel; i++)
	{
		// 16비트 색상 데이터를 두 개의 8비트 데이터로 변환
		data[i * 2] = (color_p->full) >> 8;			 // 상위 8비트 데이터 획득
		data[i * 2 + 1] = (uint8_t)(color_p->full); // 하위 8비트 데이터 획득
		color_p++;									 // 다음 색상값 가리킴

		// 데이터량이 10000보다 크면分批 전송
		if (Pixel > 10000)
		{
			if ((i + 1) % data_split == 0)
			{
				if ((i + 1) == data_split)
				{
					Lcd_WriteData_DMA(data, data_split * 2); // DMA 방식으로 데이터 전송
				}
				else
				{
					while (HAL_SPI_GetState(LCD_SPI) != HAL_SPI_STATE_READY);							  // SPI 버스 대기
					uint8_t *temp = &data[((uint16_t)((i + 1) / data_split) - 1) * data_split * 2]; // 남은 데이터 획득
					Lcd_WriteData_DMA(temp, data_split * 2);										  // DMA 방식으로 데이터 전송
				}
			}
			else if (((i + 1) % data_split > 0) && ((i + 1) > data_split) && (i == (Pixel - 1)))
			{
				if ((uint16_t)((i + 1) / data_split) == 1)
				{
					while (HAL_SPI_GetState(LCD_SPI) != HAL_SPI_STATE_READY)
						;									   // SPI 버스 대기
					uint8_t *temp = &data[data_split * 2];	   // 남은 데이터 획득
					Lcd_WriteData_DMA(temp, ((i + 1) % data_split) * 2); // DMA 방식으로 데이터 전송
				}
				else
				{
					while (HAL_SPI_GetState(LCD_SPI) != HAL_SPI_STATE_READY)
						;															  // SPI 버스 대기
					uint8_t *temp = &data[(uint16_t)((i + 1) / data_split) * data_split * 2]; // 남은 데이터 획득
					Lcd_WriteData_DMA(temp, ((i + 1) % data_split) * 2);
				}
			}
		}
	}

	if (Pixel <= 10000)
	{
		// 전송할 데이터가 10000*2바이트 이하일 때 한 번에 모두 전송
		Lcd_WriteData_DMA(data, Pixel * 2);
	}

	LCD_SetWindows(0, 0, lcddev.width - 1, lcddev.height - 1); // 창 설정을 전체 화면으로 복원
}

기타 오픈소스 프로젝트 추천

추천 읽기

1개의 좋아요