LCD显示屏增加画线、画点函数。
原文连接
#include "../HARDWARE/LCD/lcd.h"
#include "../HARDWARE/Font/font16/font16.h"
#include "../HARDWARE/Font/fonten/fonten16.h"
#include "main.h"
#include "string.h"
#include "stdio.h"
typedef enum
{
LCD_WRITE_TYPE_COMMAND = 0,
LCD_WRITE_TYPE_DATA,
} LCD_WRITE_TYPE;
uint8_t g_aLcdBuf[LCD_WIDTH][LCD_HIGHT / 8];
// CS 使能(低电平)
#define LCD_CS_PORT GPIOC
#define LCD_CS_PIN GPIO_PIN_4
// RES 复位(低电平)
#define LCD_RST_PORT GPIOC
#define LCD_RST_PIN GPIO_PIN_5
// A0 数据(1)/命令(0)
#define LCD_A0_PORT GPIOB
#define LCD_A0_PIN GPIO_PIN_11
// SCL 串口时钟输入
#define LCD_SCLK_PORT GPIOA
#define LCD_SCLK_PIN GPIO_PIN_5
// SDA 串口数据输入
#define LCD_SDA_PORT GPIOA
#define LCD_SDA_PIN GPIO_PIN_7
// BACKLIGHT 背光正极
#define LCD_BACKLIGHT_PORT GPIOA
#define LCD_BACKLIGHT_PIN GPIO_PIN_6
#define CS_Switch(x) HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN, (GPIO_PinState)x)
#define RST_Switch(x) HAL_GPIO_WritePin(LCD_RST_PORT, LCD_RST_PIN, (GPIO_PinState)x)
#define A0_Switch(x) HAL_GPIO_WritePin(LCD_A0_PORT, LCD_A0_PIN, (GPIO_PinState)x)
#define SCLK_Switch(x) HAL_GPIO_WritePin(LCD_SCLK_PORT, LCD_SCLK_PIN, (GPIO_PinState)x)
#define SDA_Switch(x) HAL_GPIO_WritePin(LCD_SDA_PORT, LCD_SDA_PIN, (GPIO_PinState)x)
#define LEDA_Switch(x) HAL_GPIO_WritePin(LCD_BACKLIGHT_PORT, LCD_BACKLIGHT_PIN, (GPIO_PinState)x)
/**
* 数据传输
*/
static void Write(uint8_t value)
{
uint8_t i;
for (i = 0; i < 8; i++)
{
SCLK_Switch(0); // 拉低SCLK
if (value & 0x80) // 稳定数据
SDA_Switch(1);
else
SDA_Switch(0);
SCLK_Switch(1); // 发送数据
value <<= 1;
}
}
/**
* 写数据
*/
static void WriteLcd(LCD_WRITE_TYPE type, uint8_t value)
{
CS_Switch(0);
A0_Switch(type);
Write(value);
CS_Switch(1);
}
/**
* 设置地址
*/
static void SetAddress(uint8_t column, uint8_t page)
{
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0xb0 + page); // 设置页地址。每页是8行。一个画面的64行被分成8个页。我们平常所说的第1页,在LCD驱动IC里是第0页,所以在这里减去1*/
WriteLcd(LCD_WRITE_TYPE_COMMAND, ((column >> 4) & 0x0f) + 0x10); // 设置列地址的高4位
WriteLcd(LCD_WRITE_TYPE_COMMAND, column & 0x0f); // 设置列地址的低4位
}
/**
* 画点
*/
static void DrawPoint(uint8_t x, uint8_t y, uint8_t data)
{
uint8_t PageNumber = y / 8;
uint8_t WriteByte = 0;
SetAddress(x, PageNumber);
if(data == 0)
{
g_aLcdBuf[x][PageNumber] &=(0xFF|(0 << (y % 8)));
}
else
{
g_aLcdBuf[x][PageNumber] |= 1 << (y % 8);
}
WriteLcd(LCD_WRITE_TYPE_DATA, g_aLcdBuf[x][PageNumber]);
}
/**
* LCD初始化
*/
void LCDInit(void)
{
GPIO_InitTypeDef GPIO_Init;
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
GPIO_Init.Pin = LCD_CS_PIN | LCD_RST_PIN;
GPIO_Init.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Init.Pull = GPIO_NOPULL;
GPIO_Init.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LCD_CS_PORT, &GPIO_Init);
GPIO_Init.Pin = LCD_A0_PIN;
HAL_GPIO_Init(LCD_A0_PORT, &GPIO_Init);
GPIO_Init.Pin = LCD_SCLK_PIN | LCD_SDA_PIN | LCD_BACKLIGHT_PIN;
HAL_GPIO_Init(LCD_SCLK_PORT, &GPIO_Init);
HAL_GPIO_WritePin(LCD_CS_PORT, LCD_CS_PIN | LCD_RST_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_A0_PORT, LCD_A0_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(LCD_SCLK_PORT, LCD_SCLK_PIN | LCD_SDA_PIN | LCD_BACKLIGHT_PIN, GPIO_PIN_RESET);
RST_Switch(0); // 重置RESET
bsp_delay_ms(10);
RST_Switch(1); // 恢复重置RESET
bsp_delay_ms(10);
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0xe2); // System Reset
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0x2c); // Power Rise Step1
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0x2e); // Power Rise Step2
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0x2f); // Power Rise Step3
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0x23);
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0xa2); // Bias 1/9
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0xc0); // Set COM(row) Direction
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0xa1); // Set SEG(column) Direction
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0x40); // Set Scroll Line: the first line
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0xaf); // Display Enable
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0xa4); // Display Enable
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0x81);
WriteLcd(LCD_WRITE_TYPE_COMMAND, 0x1f);
LEDA_Switch(0); // 关闭背光
ClearScreen(); // 清屏
memset(g_aLcdBuf, 0, sizeof(g_aLcdBuf));
}
/**
* 画线
*/
void DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
uint16_t t;
int xerr = 0, yerr = 0, delta_x, delta_y, distance;
int incx, incy, uRow, uCol;
delta_x = x2 - x1; /* 计算坐标增量 */
delta_y = y2 - y1;
uRow = x1;
uCol = y1;
if (delta_x > 0) /* 设置单步方向 */
incx = 1;
else if (delta_x == 0) /* 垂直线 */
incx = 0;
else
{
incx = -1;
delta_x = -delta_x;
}
if (delta_y > 0)
incy = 1;
else if (delta_y == 0) /* 水平线 */
incy = 0;
else
{
incy = -1;
delta_y = -delta_y;
}
if (delta_x > delta_y) /*选取基本增量坐标轴 */
distance = delta_x;
else
distance = delta_y;
for (t = 0; t <= distance; t++) /* 画线输出 */
{
DrawPoint(uRow, uCol,1); /* 画点 */
xerr += delta_x;
yerr += delta_y;
if (xerr + distance / 2 > distance)
{
xerr -= distance;
uRow += incx;
}
if (yerr + distance / 2 > distance)
{
yerr -= distance;
uCol += incy;
}
}
}
/**
* 画矩形
*/
void DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2)
{
DrawLine(x1, y1, x2, y1);
DrawLine(x1, y1, x1, y2);
DrawLine(x2, y1, x2, y2);
DrawLine(x2, y2, x1, y2);
}
/**
* 清屏函数
*/
void ClearScreen(void)
{
uint8_t i, j;
memset(g_aLcdBuf, 0, sizeof(g_aLcdBuf));
for (i = 0; i < 8; i++)
{
SetAddress(0, i);
for (j = 0; j < 132; j++)
{
WriteLcd(LCD_WRITE_TYPE_DATA, 0x00);
}
}
}
/**
* 显示16x16字体
*/
static void DisplayFont16(uint8_t x, uint8_t y, uint8_t reverse, const uint8_t width, const uint8_t *dp)
{
uint8_t i, j, temp = 0;
if (x < 4)
x = 4;
for (i = 0; i < 2; i++)
{
for (uint8_t j = 0; j < width; j++)
{
for (uint8_t count = 0; count < 8; count++)
{
temp = 0;
temp = 0x01 << count;
if ((*dp & temp) != 0)
{
DrawPoint(x + j, y + (i * 8) + count, 1 - reverse);
}
else
{
DrawPoint(x + j, y + (i * 8) + count, reverse - 0);
}
}
dp++;
}
}
}
/**
* x, y 字符转坐标
* reverse 是否反显
* *str 字符串
*/
void DisplayFont(const uint8_t x, const uint8_t y, const uint8_t reverse, const char *str)
{
uint8_t *(*GetFontPoint)(const char *str);
uint8_t font_size = 0, shifting = 0;
if (*str > 0x7F)
{
font_size = 16;
GetFontPoint = fontGetPoint;
shifting = 2;
}
else
{
font_size = 8;
GetFontPoint = fontEn16GetPoint;
shifting = 1;
}
uint8_t fontCount = strlen(str) / (font_size / 8);
for (uint8_t i = 0; i < fontCount; i++)
{
DisplayFont16(x + (i * font_size), y, reverse, font_size, GetFontPoint(&str[i * shifting]));
}
}
#ifndef _LCD_H
#define _LCD_H
#include "stdint.h"
#define LCD_WIDTH 128
#define LCD_HIGHT 64
void LCDInit(void);
void ClearScreen(void);
void DisplayFont(const uint8_t x,uint8_t const y,const uint8_t reverse,const char *str);
void DrawRectangle(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
void DrawLine(uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2);
#endif