#include "board.h" #include "bsp.h" #include "main.h" #include "rtc.h" #include "spi.h" #include "../system/sgl/sgl.h" board_t board; #define SGL_PANEL_WIDTH 240 #define SGL_PANEL_HEIGHT 240 static sgl_color_t sgl_panel_buffer[SGL_PANEL_WIDTH * 10]; static void sgl_flush_area(sgl_area_t *area, sgl_color_t *src) { board.lcd->driver.write_pixels(board.lcd, area->x1, area->y1, area->x2, area->y2, (uint16_t *)src); sgl_fbdev_flush_ready(); } void led_open(led_e led) { switch (led) { case LED_USER: GPIO_SET(LED_USER_GPIO_Port, LED_USER_Pin); break; default: break; } } void led_close(led_e led) { switch (led) { case LED_USER: GPIO_RESET(LED_USER_GPIO_Port, LED_USER_Pin); break; default: break; } } void led_toggle(led_e led) { switch (led) { case LED_USER: GPIO_TOGGLE(LED_USER_GPIO_Port, LED_USER_Pin); break; default: break; } } /** * @brief RTC写入后备区域SRAM * @param bkrx : 后备区寄存器编号,范围:0~31 * @param data : 要写入的数据,32位长度 * @retval 无 */ void rtc_write_bkr(uint32_t bkrx, uint32_t data) { HAL_PWR_EnableBkUpAccess(); /* 取消备份区写保护 */ HAL_RTCEx_BKUPWrite(&hrtc, bkrx, data); } /** * @brief RTC读取后备区域SRAM * @param bkrx : 后备区寄存器编号,范围:0~31 * @retval 读取到的值 */ static uint32_t rtc_read_bkr(uint32_t bkrx) { uint32_t temp = 0; temp = RTC_BASE + 0x50 + bkrx * 4; return (*(uint32_t *)temp); /* 返回读取到的值 */ } BOOL rtc_set_time(rtc_time_t time, uint8_t ampm) { RTC_TimeTypeDef rtc_time; rtc_time.Hours = time.hour; rtc_time.Minutes = time.minute; rtc_time.Seconds = time.second; rtc_time.TimeFormat = ampm; rtc_time.DayLightSaving = RTC_DAYLIGHTSAVING_NONE; rtc_time.StoreOperation = RTC_STOREOPERATION_RESET; return HAL_RTC_SetTime(&hrtc, &rtc_time, RTC_FORMAT_BIN) == HAL_OK; } BOOL rtc_set_date(rtc_date_t date) { RTC_DateTypeDef rtc_date; rtc_date.Month = date.month; rtc_date.Date = date.day; rtc_date.Year = date.year; rtc_date.WeekDay = date.weekday; return HAL_RTC_SetDate(&hrtc, &rtc_date, RTC_FORMAT_BIN) == HAL_OK; } void rtc_update(void) { RTC_DateTypeDef rtc_date; RTC_TimeTypeDef rtc_time; HAL_RTC_GetTime(&hrtc, &rtc_time, RTC_FORMAT_BIN); HAL_RTC_GetDate(&hrtc, &rtc_date, RTC_FORMAT_BIN); board.rtc_time.hour = rtc_time.Hours; board.rtc_time.minute = rtc_time.Minutes; board.rtc_time.second = rtc_time.Seconds; board.rtc_date.weekday = rtc_date.WeekDay; board.rtc_date.month = rtc_date.Month; board.rtc_date.day = rtc_date.Date; board.rtc_date.year = rtc_date.Year; } BOOL rtc_init(void) { uint16_t bkpflag = 0; /* 检查是不是第一次配置时钟 */ bkpflag = rtc_read_bkr(RTC_BKP_DR0); /* 读取BKP0的值 */ if ((bkpflag != 0x5050) && (bkpflag != 0x5051)) /* 之前未初始化过, 重新配置 */ { rtc_date_t date; rtc_time_t time; date.year = 25; date.month = 1; date.day = 1; date.weekday = get_weekday(2000 + date.year, date.month, date.day); time.hour = 0; time.minute = 0; time.second = 0; rtc_set_time(time, RTC_HOURFORMAT12_AM); /* 设置时间, 根据实际时间修改 */ rtc_set_date(date); /* 设置日期 */ rtc_write_bkr(RTC_BKP_DR0, 0x5051); /* 写入标记位 */ } return TRUE; } void lcd_rtc_test(void) { char tmp[32]; sgl_obj_delete(NULL); sgl_task_handle(); /* 刷新:屏幕清空 */ sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00)); sgl_obj_t *lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, 70); sgl_obj_set_size(lbl, 240, 28); sgl_label_set_text(lbl, "STM32 RTC Test"); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0xAA, 0xFF)); sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, 100); sgl_obj_set_size(lbl, 240, 28); sgl_label_set_text(lbl, "Resolution: 240x240"); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0xFF, 0xFF, 0x00)); sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, 130); sgl_obj_set_size(lbl, 240, 28); /* 使用 sgl_label_set_text_dyn:文本复制到 label 自有堆内存,label 销毁时自动释放 */ sprintf(tmp, "%d-%02d-%02d %02d:%02d:%02d", 2000 + board.rtc_date.year, board.rtc_date.month, board.rtc_date.day, board.rtc_time.hour, board.rtc_time.minute, board.rtc_time.second); // sgl_label_set_text_dyn(lbl, tmp); sgl_label_set_text(lbl, tmp); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0xFF, 0x40, 0x40)); sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); sgl_task_handle(); } // 清屏测试 void lcd_test_clear(void) { sgl_color_t bg_colors[8]; bg_colors[0] = sgl_rgb(0xFF, 0x80, 0x80); /* LIGHT_RED */ bg_colors[1] = sgl_rgb(0x80, 0xFF, 0x80); /* LIGHT_GREEN */ bg_colors[2] = sgl_rgb(0x80, 0x80, 0xFF); /* LIGHT_BLUE */ bg_colors[3] = sgl_rgb(0xFF, 0xFF, 0x80); /* LIGHT_YELLOW */ bg_colors[4] = sgl_rgb(0x80, 0xFF, 0xFF); /* LIGHT_CYAN */ bg_colors[5] = sgl_rgb(0xA3, 0xA3, 0xA3); /* LIGHT_GREY */ bg_colors[6] = sgl_rgb(0xFF, 0x80, 0xFF); /* LIGHT_MAGENTA */ bg_colors[7] = sgl_rgb(0xFF, 0xFF, 0xFF); /* LCD_WHITE */ sgl_obj_delete(NULL); sgl_obj_t *lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, 70); sgl_obj_set_size(lbl, 240, 28); sgl_label_set_text(lbl, "STM32 Clear Test"); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00)); sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, 100); sgl_obj_set_size(lbl, 240, 28); sgl_label_set_text(lbl, "Resolution: 240x240"); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00)); sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, 130); sgl_obj_set_size(lbl, 240, 28); sgl_label_set_text(lbl, "Controller: ST7789"); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0x00, 0x00)); sgl_label_set_text_align(lbl, SGL_ALIGN_CENTER); for (uint8_t i = 0; i < 8; i++) { sgl_page_set_color(sgl_screen_act(), bg_colors[i]); sgl_task_handle(); HAL_Delay(1000); } sgl_obj_delete(NULL); } // 文本测试 void lcd_test_text(void) { static uint8_t initialized = 0; if (initialized) return; initialized = 1; sgl_obj_delete(NULL); sgl_page_set_color(sgl_screen_act(), sgl_rgb(0x00, 0x00, 0x00)); /* 5 rows of white text */ static const char *white_lines[5] = { "STM32 SGL Text Demo", "ABCDEFGHIJKLMNOPQRST", "0123456789:;<=>?@", "!#$'()*+,-.012345678", "!#$'()*+,-.0123456789", }; for (uint8_t i = 0; i < 5; i++) { sgl_obj_t *lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, i * 24); sgl_obj_set_size(lbl, 240, 24); sgl_label_set_text(lbl, white_lines[i]); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0xFF, 0xFF, 0xFF)); } /* 5 rows of cyan text */ static const char *cyan_lines[5] = { "!#$'()*+,-.0123456789", "!#$'()*+,-.012345678", "0123456789:;<=>?@", "ABCDEFGHIJKLMNOPQRST", "STM32 SGL Text Demo", }; for (uint8_t i = 0; i < 5; i++) { sgl_obj_t *lbl = sgl_label_create(NULL); sgl_obj_set_pos(lbl, 0, 120 + i * 24); sgl_obj_set_size(lbl, 240, 24); sgl_label_set_text(lbl, cyan_lines[i]); sgl_label_set_font(lbl, &song23); sgl_label_set_text_color(lbl, sgl_rgb(0x00, 0xFF, 0xFF)); } } void lcd_init(void) { spi_gpio_group_t gpios; gpios.cs = gpio_create(LCD_CS_GPIO_Port, LCD_CS_Pin); gpios.dc = gpio_create(LCD_DC_GPIO_Port, LCD_DC_Pin); // 初始化LCD相关的SPI lcd_info_t info = { .spi = spi_create(SPI_TYPE_LCD, gpios, 0), // 创建SPI总线 .dir = Direction_V, // 设置显示方向为横向 .width = COL_DOT_MAX_240, // 设置LCD最大宽度为400列 .height = LIN_DOT_MAX_240, // 设置LCD最大高度为240行 .retransmission_count = 3, // 设置重传次数为3次 .disp = NULL, }; info.spi->interface.hardware_enable(info.spi, &hspi3); board.lcd = lcd_create(info); DBG_ASSERT(board.lcd != NULL __DBG_LINE); board.lcd->info.spi->gpios.dc->set(*board.lcd->info.spi->gpios.dc); // DC引脚拉高,默认处于写数据状态 board.lcd->info.spi->gpios.cs->set(*board.lcd->info.spi->gpios.cs); // 拉高片选,禁止通信 LCD_BACKLIGHT_OFF; // 先关闭背光,初始化完成之后再打开 board.lcd->driver.init(board.lcd); LCD_BACKLIGHT_ON; // lcd_test_clear(); // lcd_test_text(); /* SGL初始化 */ sgl_fbinfo_t fbinfo = { .xres = SGL_PANEL_WIDTH, .yres = SGL_PANEL_HEIGHT, .flush_area = sgl_flush_area, .buffer[0] = sgl_panel_buffer, .buffer_size = sizeof(sgl_panel_buffer) / sizeof(sgl_color_t), }; sgl_fbdev_register(&fbinfo); sgl_init(); } /** * @brief 初始化显示板 * */ void board_init(void) { lcd_init(); rtc_init(); sd_init(); // sd_fatfs_test(); }