337 lines
9.5 KiB
C
337 lines
9.5 KiB
C
#include "board.h"
|
||
#include "bsp.h"
|
||
#include "main.h"
|
||
#include "rtc.h"
|
||
#include "spi.h"
|
||
#include "../system/sgl/sgl.h"
|
||
#include "os.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();
|
||
vTaskDelay(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();
|
||
}
|