配置 PWM ADC LCD
This commit is contained in:
328
STM32F103C8T6/Drivers/BSP/LCD/lcd.c
Normal file
328
STM32F103C8T6/Drivers/BSP/LCD/lcd.c
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
* 模块名称:LCD 绘图模块
|
||||
* 模块功能:提供字符、字符串(中英文混合)、线条、矩形、圆形等图形绘制
|
||||
* 适用平台:STM32F103C8T6 + ST7735S + 底层 st7735s.c
|
||||
* 作者:王建锋
|
||||
* 创建日期:2026-07-14
|
||||
* 修改记录:
|
||||
* 2026-07-14 王建锋 从 st7735s.c 拆分
|
||||
*/
|
||||
|
||||
#include "lcd.h"
|
||||
#include "lcd_data.h"
|
||||
#include "hz16_data.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* 函数功能:UTF-8字符转Unicode(辅助)
|
||||
* 入口参数:str - UTF-8字符串指针(会被推进到下一字符起始)
|
||||
* 返回值:Unicode码点,或0(异常/结束)
|
||||
* 函数说明:支持1~3字节UTF-8,推进str
|
||||
*/
|
||||
static uint16_t utf8_to_unicode(const char **str)
|
||||
{
|
||||
uint16_t code;
|
||||
uint8_t c;
|
||||
|
||||
c = (uint8_t)(**str);
|
||||
if (c == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c < 0x80) {
|
||||
code = c;
|
||||
(*str)++;
|
||||
} else if ((c & 0xE0) == 0xC0) {
|
||||
code = c & 0x1F;
|
||||
(*str)++;
|
||||
code = (code << 6) | ((uint8_t)(**str) & 0x3F);
|
||||
(*str)++;
|
||||
} else if ((c & 0xF0) == 0xE0) {
|
||||
code = c & 0x0F;
|
||||
(*str)++;
|
||||
code = (code << 6) | ((uint8_t)(**str) & 0x3F);
|
||||
(*str)++;
|
||||
code = (code << 6) | ((uint8_t)(**str) & 0x3F);
|
||||
(*str)++;
|
||||
} else {
|
||||
(*str)++;
|
||||
return 0;
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:显示一个8x16 ASCII字符
|
||||
* 入口参数:x - 列坐标
|
||||
* y - 行坐标
|
||||
* ch - 字符 (ASCII 32-126)
|
||||
* color - 字符颜色 (RGB565)
|
||||
* bg_color - 背景颜色 (RGB565)
|
||||
* 返回值:无
|
||||
* 函数说明:框选8x16区域→遍历字模bit→发送color或bg_color
|
||||
*/
|
||||
void lcd_draw_char(uint16_t x, uint16_t y, char ch, uint16_t color, uint16_t bg_color)
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t j;
|
||||
uint8_t line;
|
||||
|
||||
if (ch < 32 || ch > 126) {
|
||||
ch = ' ';
|
||||
}
|
||||
|
||||
st7735s_set_window(x, y, x + 7, y + 15);
|
||||
|
||||
HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET);
|
||||
HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_SET);
|
||||
for (i = 0; i < 16; i++) {
|
||||
line = LCD_F8x16[ch - 32][i];
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (line & 0x80) {
|
||||
st7735s_spi_write_byte((uint8_t)(color >> 8));
|
||||
st7735s_spi_write_byte((uint8_t)(color & 0xFF));
|
||||
} else {
|
||||
st7735s_spi_write_byte((uint8_t)(bg_color >> 8));
|
||||
st7735s_spi_write_byte((uint8_t)(bg_color & 0xFF));
|
||||
}
|
||||
line <<= 1;
|
||||
}
|
||||
}
|
||||
HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:显示字符串
|
||||
* 入口参数:x - 列坐标
|
||||
* y - 行坐标
|
||||
* str - 字符串指针
|
||||
* color - 字符颜色 (RGB565)
|
||||
* bg_color - 背景颜色 (RGB565)
|
||||
* 返回值:无
|
||||
* 函数说明:连续显示字符串,自动换行
|
||||
*/
|
||||
void lcd_draw_string(uint16_t x, uint16_t y, const char *str, uint16_t color, uint16_t bg_color)
|
||||
{
|
||||
uint16_t start_x = x;
|
||||
|
||||
while (*str != '\0') {
|
||||
if (*str == '\n') {
|
||||
y += FONT_HEIGHT_16;
|
||||
x = start_x;
|
||||
str++;
|
||||
continue;
|
||||
}
|
||||
if (x + 8 > s_lcd_width) {
|
||||
y += FONT_HEIGHT_16;
|
||||
x = start_x;
|
||||
}
|
||||
if (y + 16 > s_lcd_height) {
|
||||
break;
|
||||
}
|
||||
lcd_draw_char(x, y, *str, color, bg_color);
|
||||
x += FONT_WIDTH_8;
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:显示一个16x16 CJK汉字
|
||||
* 入口参数:x - 列坐标
|
||||
* y - 行坐标
|
||||
* unicode - Unicode码点 (如 0x4E00="一")
|
||||
* color - 字符颜色 (RGB565)
|
||||
* bg_color - 背景颜色 (RGB565)
|
||||
* 返回值:无
|
||||
* 函数说明:框选16x16区域→遍历字模bit→发送color或bg_color
|
||||
*/
|
||||
void lcd_draw_chinese(uint16_t x, uint16_t y, uint16_t unicode,
|
||||
uint16_t color, uint16_t bg_color)
|
||||
{
|
||||
uint16_t i;
|
||||
uint16_t j;
|
||||
uint8_t k;
|
||||
uint8_t line;
|
||||
const uint8_t *bitmap;
|
||||
|
||||
bitmap = cjk_get_bitmap(unicode);
|
||||
if (bitmap == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
st7735s_set_window(x, y, x + CJK_WIDTH - 1, y + CJK_HEIGHT - 1);
|
||||
|
||||
HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_RESET);
|
||||
HAL_GPIO_WritePin(LCD_DC_PORT, LCD_DC_PIN, GPIO_PIN_SET);
|
||||
for (i = 0; i < CJK_HEIGHT; i++) {
|
||||
for (j = 0; j < CJK_WIDTH / 8; j++) {
|
||||
line = bitmap[i * (CJK_WIDTH / 8) + j];
|
||||
for (k = 0; k < 8; k++) {
|
||||
if (line & 0x80) {
|
||||
st7735s_spi_write_byte((uint8_t)(color >> 8));
|
||||
st7735s_spi_write_byte((uint8_t)(color & 0xFF));
|
||||
} else {
|
||||
st7735s_spi_write_byte((uint8_t)(bg_color >> 8));
|
||||
st7735s_spi_write_byte((uint8_t)(bg_color & 0xFF));
|
||||
}
|
||||
line <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, GPIO_PIN_SET);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:显示UTF-8字符串(自动中英文混合)
|
||||
* 入口参数:x - 列坐标
|
||||
* y - 行坐标
|
||||
* str - UTF-8字符串指针
|
||||
* color - 字符颜色 (RGB565)
|
||||
* bg_color - 背景颜色 (RGB565)
|
||||
* 返回值:无
|
||||
* 函数说明:自动识别ASCII(8x16)和CJK(16x16),自动换行
|
||||
*/
|
||||
void lcd_draw_chinese_string(uint16_t x, uint16_t y,
|
||||
const char *str,
|
||||
uint16_t color, uint16_t bg_color)
|
||||
{
|
||||
uint16_t start_x = x;
|
||||
|
||||
while (*str != '\0') {
|
||||
uint8_t c = (uint8_t)(*str);
|
||||
|
||||
if (*str == '\n') {
|
||||
y += CJK_HEIGHT;
|
||||
x = start_x;
|
||||
str++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c < 0x80) {
|
||||
if (x + 8 > s_lcd_width) {
|
||||
y += CJK_HEIGHT;
|
||||
x = start_x;
|
||||
}
|
||||
if (y + 16 > s_lcd_height) {
|
||||
break;
|
||||
}
|
||||
lcd_draw_char(x, y, (char)c, color, bg_color);
|
||||
x += 8;
|
||||
str++;
|
||||
} else {
|
||||
const char *p = str;
|
||||
uint16_t unicode = utf8_to_unicode(&p);
|
||||
if (unicode == 0) {
|
||||
str = p;
|
||||
continue;
|
||||
}
|
||||
if (x + CJK_WIDTH > s_lcd_width) {
|
||||
y += CJK_HEIGHT;
|
||||
x = start_x;
|
||||
}
|
||||
if (y + CJK_HEIGHT > s_lcd_height) {
|
||||
break;
|
||||
}
|
||||
lcd_draw_chinese(x, y, unicode, color, bg_color);
|
||||
x += CJK_WIDTH;
|
||||
str = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:画线(Bresenham算法)
|
||||
* 入口参数:x1 - 起始列
|
||||
* y1 - 起始行
|
||||
* x2 - 结束列
|
||||
* y2 - 结束行
|
||||
* color - 颜色 (RGB565)
|
||||
* 返回值:无
|
||||
*/
|
||||
void lcd_draw_line(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color)
|
||||
{
|
||||
int16_t dx;
|
||||
int16_t dy;
|
||||
int16_t sx;
|
||||
int16_t sy;
|
||||
int16_t err;
|
||||
int16_t e2;
|
||||
int16_t x = (int16_t)x1;
|
||||
int16_t y = (int16_t)y1;
|
||||
|
||||
dx = (x1 < x2) ? (int16_t)(x2 - x1) : (int16_t)(x1 - x2);
|
||||
dy = (y1 < y2) ? (int16_t)(y2 - y1) : (int16_t)(y1 - y2);
|
||||
sx = (x1 < x2) ? 1 : -1;
|
||||
sy = (y1 < y2) ? 1 : -1;
|
||||
err = dx - dy;
|
||||
|
||||
while (1) {
|
||||
st7735s_draw_pixel((uint16_t)x, (uint16_t)y, color);
|
||||
if (x == (int16_t)x2 && y == (int16_t)y2) {
|
||||
break;
|
||||
}
|
||||
e2 = 2 * err;
|
||||
if (e2 > -dy) {
|
||||
err -= dy;
|
||||
x += sx;
|
||||
}
|
||||
if (e2 < dx) {
|
||||
err += dx;
|
||||
y += sy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:画空心矩形
|
||||
* 入口参数:x - 左上角列
|
||||
* y - 左上角行
|
||||
* width - 宽度
|
||||
* height - 高度
|
||||
* color - 颜色 (RGB565)
|
||||
* 返回值:无
|
||||
*/
|
||||
void lcd_draw_rect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, uint16_t color)
|
||||
{
|
||||
uint16_t x2 = x + width - 1;
|
||||
uint16_t y2 = y + height - 1;
|
||||
|
||||
lcd_draw_line(x, y, x2, y, color);
|
||||
lcd_draw_line(x, y, x, y2, color);
|
||||
lcd_draw_line(x2, y, x2, y2, color);
|
||||
lcd_draw_line(x, y2, x2, y2, color);
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:画空心圆(Bresenham算法)
|
||||
* 入口参数:x0 - 圆心列
|
||||
* y0 - 圆心行
|
||||
* radius - 半径
|
||||
* color - 颜色 (RGB565)
|
||||
* 返回值:无
|
||||
*/
|
||||
void lcd_draw_circle(uint16_t x0, uint16_t y0, uint16_t radius, uint16_t color)
|
||||
{
|
||||
int16_t x = 0;
|
||||
int16_t y = (int16_t)radius;
|
||||
int16_t err = 1 - (int16_t)radius;
|
||||
int16_t xc = (int16_t)x0;
|
||||
int16_t yc = (int16_t)y0;
|
||||
|
||||
while (x <= y) {
|
||||
st7735s_draw_pixel((uint16_t)(xc + x), (uint16_t)(yc + y), color);
|
||||
st7735s_draw_pixel((uint16_t)(xc - x), (uint16_t)(yc + y), color);
|
||||
st7735s_draw_pixel((uint16_t)(xc + x), (uint16_t)(yc - y), color);
|
||||
st7735s_draw_pixel((uint16_t)(xc - x), (uint16_t)(yc - y), color);
|
||||
st7735s_draw_pixel((uint16_t)(xc + y), (uint16_t)(yc + x), color);
|
||||
st7735s_draw_pixel((uint16_t)(xc - y), (uint16_t)(yc + x), color);
|
||||
st7735s_draw_pixel((uint16_t)(xc + y), (uint16_t)(yc - x), color);
|
||||
st7735s_draw_pixel((uint16_t)(xc - y), (uint16_t)(yc - x), color);
|
||||
x++;
|
||||
if (err < 0) {
|
||||
err += 2 * x + 1;
|
||||
} else {
|
||||
y--;
|
||||
err += 2 * (x - y) + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user