LCD显示屏增加画线、画点函数

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 







TFTLCD画点函数是用来在TFTLCD显示屏上绘制像素点的函数。它通常需要传入坐标(x, y)和颜色值(color)三个参数。 具体讲解如下: 1. 坐标(x, y):TFTLCD显示屏上的每个像素都有一个唯一的坐标位置,坐标是指该像素在屏幕上的位置。坐标参数通常是以像素为单位的整数值。 2. 颜色值(color):TFTLCD显示屏上的每个像素都可以被设置为不同的颜色。颜色参数通常是一个16位的整数值,其中高8位表示红色分量,中间8位表示绿色分量,低8位表示蓝色分量。 3. 画点函数画点函数是用来在TFTLCD显示屏上绘制像素点的函数。它通常使用底层的硬件驱动来控制TFTLCD显示屏,将像素点的颜色值设置到指定的坐标位置。 下面是一个伪代码示例: ```c++ void drawPixel(int x, int y, uint16_t color){ // 将像素点的颜色值设置到指定的坐标位置 setPixelColor(x, y, color); } ``` 在实际开发中,画点函数通常是由底层的硬件驱动或者绘图库提供的,开发者只需要调用相应的API即可。例如,在Arduino平台上,可以使用TFTLCD库来实现画点函数,示例代码如下: ```c++ #include <Adafruit_TFTLCD.h> // 创建TFTLCD对象 Adafruit_TFTLCD tft; void setup(){ // 初始化TFTLCD显示屏 tft.begin(); } void loop(){ // 绘制一个红色的像素点到坐标(10, 20)的位置上 tft.drawPixel(10, 20, RED); } ``` 需要注意的是,TFTLCD显示屏的像素点数量通常很大,如果需要绘制大量的像素点,可能会导致性能问题。因此,建议在绘制大量像素点时使用批量绘制的方式,例如使用画线函数、画矩形函数等。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值