配置 PWM ADC LCD

This commit is contained in:
2026-07-14 17:51:39 +08:00
parent 0a5c478a42
commit 2d0d000a38
67 changed files with 33357 additions and 911 deletions

View 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;
}
}
}