硬件SPI驱动ST7789V2

        前言

        本文是基于F407ZGT6的HAL库方式来驱动的,目前学的是最基础的东西,只是简单的在屏幕上显示ASCII字符和汉字,其他的功能暂时还没学到。写这篇文章是怕以后要使用的时候又忘记怎么驱动的了,又要去翻资料,花大量时间。错误的地方欢迎大家指正,谢谢!

一、ST7789V2

1. 基本介绍

        ST7789V2是一个单芯片控制器/驱动器的262k色,图形型TFT-LCD。它由720条源极线和320栅极线驱动电路组成。该芯片可以直接连接到外部微处理器,并接受8位/9位/16位/18位并行接口。显示数据可以存储在240x320x18位的片上显示数据RAM中。它可以在没有外部操作时钟的情况下进行显示数据RAM读写操作,以降低功耗。此外,由于驱动液晶所需的集成电源电路,可以制造一个具有最少组件的显示系统。

2. 特点

        显示分辨率: 240*RGB (H) *320(V),

        帧内存大小:240x320x18位= 1,382,400位。

        各种显示数据输入格式的可编程像素颜色格式(颜色深度):

         12位/像素:RGB=(444)
         16位/像素:RGB=(565)
         18位/像素:RGB=(666)               

          地址控制:地址计数器设置用于写入和读取的显示数据RAM的地址。数据按像素级写入到驱动器的RAM矩阵中。根据数据格式,收集一个或两个像素的数据(RGB6-6-6位)。一旦这个像素数据信息完成,“RAM上的写访问”就会被激活。RAM的位置由地址指针进行定位。地址范围为X=0到X=239(Efh)和Y=0到Y=319(13Fh)。不允许使用这些范围之外的地址。在写入RAM之前,必须定义一个要写入的窗口。该窗口可通过命令寄存器进行编程,XS,YS指定开始地址,XE,YE指定结束地址。例如,整个显示内容将被写入,窗口由以下值定义:XS=0(0h)YS=0(0h)和XE=239(Efh)、YE=319(13Fh)。
            在垂直寻址模式(MV=1)中,Y地址在每个字节之后递增,在最后一个Y地址(Y=YE)之后,Y绕到YS,X递增以地址下一列。在水平寻址模式(MV=0)中,X地址在每个字节之后递增,在最后一个X地址(X=XE)之后,X绕到XS,Y递增以处理下一行。在每个最后一个地址(X=XE和Y=YE)之后,地址指针环绕到地址(X=XS和Y=YS)。

3.引脚

3.1 电源引脚

3.2 接口逻辑引脚

        DCX引脚为数据/命令发送选择引脚,当DCX为低电平时,单片机发送的是命令,DCX为高电平时发送的是数据。

   4. 电压参数

5. 屏幕显存地址排列

        当我们设置屏幕正常显示时,如下图,屏幕长240Columns,高320lines,左上角为屏幕显存地址的起点00,以第一行为例,地址先是从左往右自增1,增加到最右边0Z时,在增加一个地址就到了第二行的10,也就是说x从X0开始自增,x每增加240,x归零,y加一。也可以看成是在本子上写字,一行从左到右写满240个字再从下一行最左边开始写,直至写完320行。

        要想设置成上述的描述,需要发送内存数据索引控制命令(0x36)来设置,具体见下下图,显示屏的具体初始化后面的程序会有详细的注释。

   

        下图就是内存数据索引控制命令,发送该命令后紧跟的数据就是设置显示屏显示的方向,模式,颜色格式和屏幕刷新方式等,我们写入数据0x00就是按上图的方式来显示。

6. SPI驱动步骤

        上图是我的ST7789V2的原理图,LCD背光阴极LEDK1-LEDK4已经接地了,LCD背光阳极LEDA接上单片机PWM输出就可以控制屏幕亮度了,但是由于还没有学到PWM,所以此处直接接固定的3.3V,即让Q2导通,让PE6输出一个低电平Q2就导通了,3.3V电压就送到了LEDA脚。

        1)设置PE6输出低电平,让LCD背光阳极接到3.3V;

        2)LCD硬件复位(HardWareReset);

        3)LCD退出睡眠模式 (SleepOut);

        3)设置LCD为正常显示(NormalDisplayModeOn);

        4)关闭反转显示(DisplayInversionOff);

        5)设置显示方向为从左到右,从上到下(MemdataAccessControl);

        6)设置显示的像素格式(SetPixelFormat);

        7)打开LCD显示(DisplayOn);

        以上就完成了LCD显示的初始化,若想要整屏显示一个颜色,则写一个函数将屏幕的240*320个像素点全部设置为同一个颜色就可以了。程序放在后面部分。

        每次上电后,需先整屏刷屏,再去显示我们想要显示的文字,数据等,不然上一次上电显示的内容还在。

二、字模提取

1. 字符取模

1.1基本设置

        上方导航窗口点击“模式“,选择字符模式,字体默认宋体,字宽和字高均设置为16

        点击上图中的”选项“按钮将弹出下面的对话框,以下设置根据我的硬件和后续的编程有关,具体还不是很清楚,清楚了再来补充。

1.2 字模选项设置

        点阵格式设置为阴码,取模方式设置为行列式,点阵和索引均设置为16,取模走向为逆向,输出数制为十六进制,输出选项三项都勾选上,像素大小设置为8,格式设为C51格式,自定义格式默认即可,设置完了点击确定即可。

1.3 设置和获取字模

        在下图中第一步的矩形区域中输入自己要显示的字符,然后点击后方的生成字模,就会在下方生成字模对应的数据,然后就可以将数据复制到程序中使用了

2.获取ASCII字模

2.1 进入英文字模获取

        点击下图中文本图标,弹出生成字库对话框

2.2 生成assic库字模

        在下图中的对话框中点击“生成英文点阵字库”,接着会弹出另存为对话框,先将保存类型设置为所有文件,再将文件名设置为ascii.txt或者.c文件也可以。然后点击保存即可。

2.3 生成的ASCII字库

        打开生成的txt字库文件大致如下

三、F407ZGT6

        要驱动ST7789V2显示屏,需使用(硬件)SPI的通信方式,其中还有片选引脚CS,故开始前还需写SPI和GPIO的驱动文件才能去驱动显示屏。

1. CubeMX配置

        先按第一部分的硬件原理图配置CubeMX。配置时钟和调试接口就不贴图了。

1.1 SPI配置

        先按下图将SPI配置为全双工主机模式,参数部分只需要将分频系数改为16,其他的不用动,因为通过查手册我们可以知道,ST7789读数据的最小周期是150ns,也就是说通信SPI的最大频率不能超过150ns对应的频率6.67MHz,这里设置16分频是满足要求的最快的频率了。

        在NVIC中勾选上中断使能,再去DMA Setting中设置DMA,把SPI1_RX和SPI1_TX都添加上,DMA的参数默认就行。

1.2 GPIO配置

        根据原理图配置以下GPIO,输出电平和输出速度均设为High,因为复位脚和片选脚都是低电平生效,所以初始化先将它们设置为高电平。

1.3 工程配置

        按下图设置生成对应外设的头文件和源文件,即可生成工程。

2. 程序部分

2.1 gpio.c

        还需在gpio.h中声明以下函数,只需声明函数的头文件后面都没有贴了,自己创建一个头文件声明供外部调用的函数就行

/* USER CODE BEGIN 2 */
void Write_7789_CS(unsigned char status)
{
	HAL_GPIO_WritePin(GPIOD, GPIO_PIN_3, status?GPIO_PIN_SET:GPIO_PIN_RESET);
}

void Write_7789_DCX(unsigned char status)
{
	HAL_GPIO_WritePin(GPIOF, GPIO_PIN_9, status?GPIO_PIN_SET:GPIO_PIN_RESET);
}

void Write_7789_RST(unsigned char status)
{
	HAL_GPIO_WritePin(GPIOG, GPIO_PIN_15, status?GPIO_PIN_SET:GPIO_PIN_RESET);
}

void Write_7789_BACK(unsigned char status)
{
	HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, status?GPIO_PIN_SET:GPIO_PIN_RESET);
}
/* USER CODE END 2 */
2.2 errno.h

        下述代码中会用到errno.h中的错误返回值,先贴上

#ifndef __ERRNO_H
#define __ERRNO_H

#define	ESUCCESS     0
#define	EPERM		 1	/* Operation not permitted */
#define	ENOENT		 2	/* No such file or directory */
#define	ESRCH		 3	/* No such process */
#define	EINTR		 4	/* Interrupted system call */
#define	EIO		 	 5	/* I/O error */
#define	ENXIO		 6	/* No such device or address */
#define	E2BIG		 7	/* Argument list too long */
#define	ENOEXEC		 8	/* Exec format error */
#define	EBADF		 9	/* Bad file number */
#define	ECHILD		10	/* No child processes */
#define	EAGAIN		11	/* Try again */
#define	ENOMEM		12	/* Out of memory */
#define	EACCES		13	/* Permission denied */
#define	EFAULT		14	/* Bad address */
#define	ENOTBLK		15	/* Block device required */
#define	EBUSY		16	/* Device or resource busy */
#define	EEXIST		17	/* File exists */
#define	EXDEV		18	/* Cross-device link */
#define	ENODEV		19	/* No such device */
#define	ENOTDIR		20	/* Not a directory */
#define	EISDIR		21	/* Is a directory */
#define	EINVAL		22	/* Invalid argument */
#define	ENFILE		23	/* File table overflow */
#define	EMFILE		24	/* Too many open files */
#define	ENOTTY		25	/* Not a typewriter */
#define	ETXTBSY		26	/* Text file busy */
#define	EFBIG		27	/* File too large */
#define	ENOSPC		28	/* No space left on device */
#define	ESPIPE		29	/* Illegal seek */
#define	EROFS		30	/* Read-only file system */
#define	EMLINK		31	/* Too many links */
#define	EPIPE		32	/* Broken pipe */
#define	EDOM		33	/* Math argument out of domain of func */
#define	ERANGE		34	/* Math result not representable */
#define	EDEADLK		35	/* Resource deadlock would occur */
#define	ENAMETOOLONG	36	/* File name too long */
#define	ENOLCK		37	/* No record locks available */

#endif /* __ERRNO_H */
2.3 drv_spi.c
#include "stm32f4xx_hal.h"
#include "errno.h"
#include "spi.h"

static void TranmistFinish_Wait(void);
static void ReceiveFinish_Wait(void);
static unsigned char txcpltflag = 0;
static unsigned char rxcpltflag = 0;

/* spi中断方式发送 */
int SPI_TransmitData(unsigned char *wbuf,unsigned int length)
{
	if(length > 0xFFFFFFFF)			return -EINVAL;
	if(NULL == wbuf)			return -EINVAL;
	unsigned len_init = length;
	if(length < 10)
	{
		HAL_StatusTypeDef status = HAL_SPI_Transmit_IT(&hspi1,wbuf,length);
		if(HAL_OK != status)	return -EIO;
		TranmistFinish_Wait();
	}
	else
	{
		while(length)
		{
			unsigned size = 0;
			if(length > 0xFFFF)
				size = 0xFFFF;
			else
				size = length;
			HAL_StatusTypeDef status = HAL_SPI_Transmit_DMA(&hspi1,wbuf,length);
			if(HAL_OK != status)	return -EIO;
			TranmistFinish_Wait();
			length -= size;
		}
	}
	return len_init;
}

/* spi中断方式接收 */
int SPI_ReceiveData(unsigned char *rbuf,unsigned int length)
{
	if(length > 0xFFFFFFFF)		return -EINVAL;
	if(NULL == rbuf)			return -EINVAL;
	unsigned len_init = length;
	if(length < 10)
	{
		HAL_StatusTypeDef status = HAL_SPI_Receive_IT(&hspi1,rbuf,length);
		if(HAL_OK != status)	return -EIO;
		ReceiveFinish_Wait();
	}
	else
	{
		while(length)
		{
			unsigned size = 0;
			if(length > 0xFFFF)
				size = 0xFFFF;
			else
				size = length;
			HAL_StatusTypeDef status = HAL_SPI_Receive_DMA(&hspi1,rbuf,length);
			if(HAL_OK != status)	return -EIO;
			ReceiveFinish_Wait();
			length -= size;
		}
	}
	return len_init;
}

/* 等待数据发送完成 */
static void TranmistFinish_Wait(void)
{
	while(!txcpltflag);
	txcpltflag = 0;
}

/* 等待数据接收完成 */
static void ReceiveFinish_Wait(void)
{
	while(!rxcpltflag);
	rxcpltflag = 0;
}

void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
	if(hspi == &hspi1)
	{
		txcpltflag = 1;
	}
}

void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
	if(hspi == &hspi1)
	{
		rxcpltflag = 1;
	}
}	
2.4 drv_st7789.h

        先头文件是因为源文件中要用到头文件中定义的结构体。

#ifndef __DRV_ST7789_H
#define __DRV_ST7789_H
											//Receive or continue send
#define SoftwareReset			(0x01)		//No Parameter
#define ReadDisplayID			(0x04)		//4 Parameter,first is dummy data
#define ReadDisplayStatus		(0x09)      //5 Parameter,first is dummy data
#define ReadDisplayPowerMode	(0x0A)      //2 Parameter,first is dummy data
#define ReadDisplayMADCTL		(0x0B)      //2 Parameter,first is dummy data
#define ReadDisplayPixelFormat	(0x0C)      //2 Parameter,first is dummy data
#define SleepIn					(0x10)      //No Parameter
#define SleepIOut				(0x11)      //No Parameter
#define PartialDisplayModeOn	(0x12)      //No Parameter
#define NormalDisplayModeOn		(0x13)      //No Parameter
#define DisplayInversionOff		(0x20)      //No Parameter
#define DisplayInversionOn		(0x21)      //No Parameter
#define DisplayOff				(0x28)      //No Parameter
#define DisplayOn				(0x29)      //No Parameter
#define ColumnAddressSet		(0x2A)      //need to send 4 Bytes Column Address
#define RowAddressSet			(0x2B)      //need to send 4 Bytes Row Address
#define MemoryWrite				(0x2C)      //need to send data from MCU to frame memory
#define MemoryRead				(0x2E)      //n Parameter from frame memory to MCU
#define MemoryDataAccessControl	(0x36)		//need to send one Byte to d defines read/ write scanning direction of frame memory
#define IdleModeOff				(0x38)      //No Parameter
#define IdleModeOn				(0x39)      //No Parameter
#define InterfacePixelFormat	(0x3A)      //need to send 1 Byte to  define the format of RGB picture data

typedef struct DisplayDev{
	char *name;			//名字
	void *FBBase;		//显存
	unsigned short Xre; //x方向分辨率
	unsigned short Yre; //y方向分辨率
	unsigned int dsize; //显存的数据个数
	unsigned short Bpp; //数据格式(12/16/18位)
	int (*Init)(struct DisplayDev *ptd);	//初始化
	int (*ShowOn)(void);  //开启显示
	int (*ShowOff)(void); //关闭显示
	int (*SetWindows)(struct DisplayDev *ptd,unsigned short Xs,unsigned short Xe,
		unsigned short Ys,unsigned short Ye);		//设置窗口显示
	int (*SetPixel)(struct DisplayDev *ptd,unsigned short wx,unsigned short wy,unsigned short color); //设置显示的像素格式
	int (*Flush)(struct DisplayDev *ptd);			//将显存FBBase中的数据写到st7789中
}DisplayDevice;

DisplayDevice *GetST7789V2_Addr(void);
void Display_Clear(unsigned short color);

#endif
2.5 drv_st7789.c
#include "drv_st7789.h"
#include "drv_spi.h"
#include "gpio.h"
#include "errno.h"
#include <stdio.h>

static int WriteCommandNoAck(unsigned char cmd);
static int WriteCommandAck(unsigned char cmd);
static int WriteData(unsigned char *wbuf,unsigned int length);
static int ReadData(unsigned char *rbuf,unsigned int length);
static int MemdataAccessControl(unsigned char mode);
static int SetPixelFormat(unsigned char data);
static int ST7789_Init(struct DisplayDev *ptd);
static int ST7789_ShowOn(void);
static int ST7789_ShowOff(void);
static int ST7789_SetWindows(struct DisplayDev *ptd,unsigned short Xs,unsigned short Xe,
							 unsigned short Ys,unsigned short Ye);
static int ST7789_SetPixel(struct DisplayDev *ptd,unsigned short wx,unsigned short wy,unsigned short color);
static int ST7789_Flush(struct DisplayDev *ptd);

static DisplayDevice st7789v2 = {
	.name = "st7789v2",
	.FBBase = NULL,
	.Xre = 240,
	.Yre = 360,
	.dsize = 0,
	.Bpp = 16,
	.Init = ST7789_Init,
	.ShowOn = ST7789_ShowOn,
	.ShowOff = ST7789_ShowOff,
	.SetWindows = ST7789_SetWindows,
	.SetPixel = ST7789_SetPixel,
	.Flush = ST7789_Flush
};

/* 获取st7789v2的结构体地址 */
DisplayDevice *GetST7789V2_Addr(void)
{
	return &st7789v2;
}

/* 清屏函数 */
void Display_Clear(unsigned short color)
{
	unsigned short xbuf[240] = {0};
	for(unsigned char i=0;i<240;i++)
	{
		xbuf[i] = color;
	}
	st7789v2.FBBase = (unsigned short *)xbuf;
	for(unsigned short i=0;i<320;i++)
	{
		st7789v2.SetWindows(&st7789v2,0,240,i,i+1);
		st7789v2.Flush(&st7789v2);
	}
}

/*  无返回值且发送之后无需发数据的命令用这个写寄存器的函数  */
static int WriteCommandNoAck(unsigned char cmd)
{
	Write_7789_CS(0);
	Write_7789_DCX(0);
	int ret = SPI_TransmitData(&cmd,1);
	Write_7789_DCX(1);
	Write_7789_CS(1);
	if(ret != 1)	return -EIO;
	return ESUCCESS;
}

/*  有返回值或者要接着发送数据的命令用这个写寄存器的函数  */
static int WriteCommandAck(unsigned char cmd)
{
	Write_7789_DCX(0);
	int ret = SPI_TransmitData(&cmd,1);
	Write_7789_DCX(1);
	if(ret != 1)	return -EIO;
	return ESUCCESS;
}

/* 写入数据函数 */
static int WriteData(unsigned char *wbuf,unsigned int length)
{
	
	int ret = SPI_TransmitData(wbuf,length);
	if(ret != length)	return -EIO;
	return (int)length;
}

/* 读取数据函数 */
static int ReadData(unsigned char *rbuf,unsigned int length)
{
	int ret = SPI_ReceiveData(rbuf,length);
	if(ret != length)	return -EIO;
	return (int)length;
}

/* ST7789V2硬件复位 */
static int HardWareReset(void)
{
	Write_7789_RST(0);	//显示屏RST引脚低电平复位
	HAL_Delay(150);		//复位时间需大于120ms
	Write_7789_RST(1);
	HAL_Delay(5);		//复位后需间隔5ms才能进行通信
	return ESUCCESS;
}

/* 读显示屏ID */
static int ReaddisplayID(void)
{
	unsigned int ID = 0;
	unsigned char data[4] = {0};
	Write_7789_CS(0);
	WriteCommandAck(ReadDisplayID);
	ReadData(data,4);
	Write_7789_CS(1);
	ID = (data[1] << 16) | (data[2] << 8) | (data[3]);
	return (int)ID;
}

/* 显存数据访问控制 */
static int MemdataAccessControl(unsigned char mode)
{
	Write_7789_CS(0);
	/* 假设传进来的命令是0x00,就是将显示屏设置为从左到右,从上到下显示
		数据地址是x++,x加完一行了,y加1,x变成0开始继续下一行的x地址++ */
	WriteCommandAck(MemoryDataAccessControl);
	int ret = WriteData(&mode,1);	
	Write_7789_CS(1);
	if(ret != 1)	return -EIO;
	return ESUCCESS;
}

/* ST7789V2初始化 */
static int ST7789_Init(struct DisplayDev *ptd)
{
	if(NULL == ptd)	return -EINVAL;
//	unsigned id = ReaddisplayID();	//读取显示屏ID
//	printf("ST7789V2 ID:0x%x\r\n",id);
	Write_7789_BACK(0);				//开启显示屏背光
	/* 1.硬件复位 */
	if(HardWareReset() != ESUCCESS)							return -EIO;
	/* 2.退出睡眠模式 */
	if(WriteCommandNoAck(SleepIOut) != ESUCCESS)			return -EIO;
	/* 3.设置为正常显示模式 */
	if(WriteCommandNoAck(NormalDisplayModeOn) != ESUCCESS)	return -EIO;
	/* 4.关闭反转显示,即如果是数据0显示白色时,开启反转则数据1显示白色 */
	if(WriteCommandNoAck(DisplayInversionOff) != ESUCCESS)  return -EIO;
	/* 5.设置显示格式为从左到右,从上到下,地址x自增等 */
	if(MemdataAccessControl(0x00) != ESUCCESS)				return -EIO;
	/* 6.设置像素格式为16-bit/pixel: RGB=(565) */
	if(SetPixelFormat(16) != ESUCCESS)                      return -EIO;
	/* 7.开启显示 */
	if(WriteCommandNoAck(DisplayOn) != ESUCCESS)            return -EIO;
	return ESUCCESS;
}

/* ST7789V2开显示 */
static int ST7789_ShowOn(void)
{
	int ret = WriteCommandNoAck(DisplayOn);
	if(ret != ESUCCESS)		return -EIO;
	return ESUCCESS;
}

/* ST7789V2关显示 */
static int ST7789_ShowOff(void)
{
	int ret = WriteCommandNoAck(DisplayOff);
	if(ret != ESUCCESS)		return -EIO;
	return ESUCCESS;
}

/* ST7789V2设置窗口显示 */
static int ST7789_SetWindows(struct DisplayDev *ptd,unsigned short Xs,unsigned short Xe,
							 unsigned short Ys,unsigned short Ye)
{
	if(NULL == ptd)	return -EINVAL;
	/* 假如我们设置x的范围为0-8,那x分辨率就是0-8,也就是有9位了,但分辨率都是8的倍数,
	9-1=8就是8的倍数了,所以这里先减一再将数据发送给ST7789	*/
	unsigned short wXe = Xe - 1;
	unsigned short wYe = Ye - 1;
	unsigned char xbuf[4] = {Xs >> 8, Xs, wXe >> 8 , wXe};
	unsigned char ybuf[4] = {Ys >> 8, Ys, wYe >> 8 , wYe};
	Write_7789_CS(0);
	/* 先发送写入x坐标地址的命令 */
	if(ESUCCESS != WriteCommandAck(ColumnAddressSet))	return -EIO;
	/* 发送x坐标地址顺序:先发送16位的x起始地址,高位在前,同理再发送x结束地址 */
	if(WriteData(xbuf,4) != 4)	return -EIO;
	/* 发送写入y坐标地址的命令 */
	if(ESUCCESS != WriteCommandAck(RowAddressSet))		return -EIO;
	/* 发送y坐标地址顺序:先发送16位的y起始地址,高位在前,同理再发送y结束地址 */
	if(WriteData(ybuf,4) != 4)	return -EIO;
	Write_7789_CS(1);
	/* 假如传进来的x坐标起始结束地址为0和8,y坐标起始结束地址为0和16 */
	ptd->Xre = Xe - Xs;	//计算x轴分辨率,这时还是用传进来的值:8-0才等于8(分辨率才是8的倍数)
	ptd->Yre = Ye - Ys;	//计算y轴分辨率,这时还是用传进来的值:16-0才等于16(分辨率才是16的倍数)
	ptd->dsize = ptd->Xre * ptd->Yre * ptd->Bpp/8;//计算显存的数据个数,Bpp表示显存中一个数据有多少位
	return ESUCCESS;
}

/* 设置ST7789V2的显示像素格式 */
static int SetPixelFormat(unsigned char data)
{
	unsigned char format = 0x55;
	if(data == 12)
	{
		/* 0x53表示12-bit/pixel: RGB=(   ) */
		format = 0x53;
	}
	else if(data == 16)
	{
		/* 0x55表示16-bit/pixel: RGB=(565) */
		format = 0x55;
	}
	else if(data == 18)
	{
		/* 0x66表示18-bit/pixel: RGB=(666) */
		format = 0x66;
	}
	Write_7789_CS(0);
	WriteCommandAck(InterfacePixelFormat);
	int ret = WriteData(&format,1);	
	Write_7789_CS(1);
	if(ret != 1)	return -EIO;
	return ESUCCESS;
}

/* 将显存FBBase中的数据写入到ST7789V2 */
static int ST7789_Flush(struct DisplayDev *ptd)
{
	if(NULL == ptd)			return -ENODEV;
	if(NULL == ptd->FBBase)	return -ENODEV;

	Write_7789_CS(0);
	WriteCommandAck(MemoryWrite);
	int ret = WriteData(ptd->FBBase,ptd->dsize);
	Write_7789_CS(1);
	if(ret != ptd->dsize)	return -EIO;	
	return ESUCCESS;
}

/* 设置ST7789单个像素点的颜色 */
static int ST7789_SetPixel(struct DisplayDev *ptd,unsigned short wx,unsigned short wy,unsigned short color)
{
	if(NULL == ptd)			return -ENODEV;
	unsigned short *buf = (unsigned short *)ptd->FBBase;
	buf += wy * ptd->Xre + wx;
	*buf = color;
	return ESUCCESS;
}
2.6 ascii.c

        将字模提取软件生成的ASCII字库放进来,并把生成的16*16和32*32位的汉字字库也放进来,再写对应的接口函数

/* ascii字库 */
static unsigned char ascii[128][16] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"  ",0*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*"  ",1*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"  ",2*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*"  ",3*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*"  ",4*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*"  ",5*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*"  ",6*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*"  ",7*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*"  ",8*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"  ",9*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",10*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",11*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",12*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",13*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",14*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",15*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",16*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",17*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",18*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",19*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",20*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",21*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",22*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",23*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",24*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",25*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",26*/
{0x00,0xFE,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0xFE,0x00,0x00},/*" ",27*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",28*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",29*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",30*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"", 31*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*" ",32*/
{0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x08,0x08,0x00,0x00},/*"!",33*/
{0x00,0x48,0x24,0x24,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*""",34*/
{0x00,0x00,0x00,0x48,0x48,0x48,0x7E,0x24,0x24,0x24,0x7E,0x24,0x24,0x24,0x00,0x00},/*"#",35*/
{0x00,0x00,0x10,0x3C,0x52,0x52,0x12,0x1C,0x30,0x50,0x50,0x52,0x52,0x3C,0x10,0x10},/*"$",36*/
{0x00,0x00,0x00,0x22,0x25,0x15,0x15,0x0D,0x2A,0x58,0x54,0x54,0x52,0x22,0x00,0x00},/*"%",37*/
{0x00,0x00,0x00,0x0C,0x12,0x12,0x12,0x0A,0x76,0x25,0x29,0x19,0x91,0x6E,0x00,0x00},/*"&",38*/
{0x00,0x06,0x04,0x04,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"'",39*/
{0x00,0x40,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x10,0x10,0x20,0x40,0x00},/*"(",40*/
{0x00,0x02,0x04,0x08,0x08,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x04,0x02,0x00},/*")",41*/
{0x00,0x00,0x00,0x00,0x08,0x08,0x6B,0x1C,0x1C,0x6B,0x08,0x08,0x00,0x00,0x00,0x00},/*"*",42*/
{0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0xFE,0x10,0x10,0x10,0x00,0x00,0x00,0x00},/*"+",43*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x04,0x04,0x02},/*",",44*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"-",45*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x06,0x00,0x00},/*".",46*/
{0x00,0x00,0x40,0x20,0x20,0x20,0x10,0x10,0x08,0x08,0x08,0x04,0x04,0x02,0x02,0x00},/*"/",47*/
{0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00},/*"0",48*/
{0x00,0x00,0x00,0x10,0x1C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x7C,0x00,0x00},/*"1",49*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x40,0x20,0x10,0x08,0x04,0x42,0x7E,0x00,0x00},/*"2",50*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x40,0x20,0x18,0x20,0x40,0x42,0x42,0x3C,0x00,0x00},/*"3",51*/
{0x00,0x00,0x00,0x20,0x30,0x30,0x28,0x24,0x24,0x22,0xFE,0x20,0x20,0xF8,0x00,0x00},/*"4",52*/
{0x00,0x00,0x00,0x7E,0x02,0x02,0x02,0x1E,0x22,0x40,0x40,0x42,0x22,0x1C,0x00,0x00},/*"5",53*/
{0x00,0x00,0x00,0x18,0x24,0x02,0x02,0x3A,0x46,0x42,0x42,0x42,0x44,0x38,0x00,0x00},/*"6",54*/
{0x00,0x00,0x00,0x7E,0x42,0x20,0x20,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x00,0x00},/*"7",55*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x3C,0x00,0x00},/*"8",56*/
{0x00,0x00,0x00,0x1C,0x22,0x42,0x42,0x42,0x62,0x5C,0x40,0x40,0x24,0x18,0x00,0x00},/*"9",57*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00},/*":",58*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x08},/*";",59*/
{0x00,0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x04,0x08,0x10,0x20,0x40,0x00,0x00},/*"<",60*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00},/*"=",61*/
{0x00,0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00},/*">",62*/
{0x00,0x00,0x00,0x3C,0x42,0x42,0x46,0x20,0x10,0x10,0x10,0x00,0x18,0x18,0x00,0x00},/*"?",63*/
{0x00,0x00,0x00,0x1C,0x22,0x5A,0x55,0x55,0x55,0x55,0x55,0x3A,0x42,0x3C,0x00,0x00},/*"@",64*/
{0x00,0x00,0x00,0x08,0x08,0x18,0x14,0x14,0x24,0x3C,0x22,0x42,0x42,0xE7,0x00,0x00},/*"A",65*/
{0x00,0x00,0x00,0x1F,0x22,0x22,0x22,0x1E,0x22,0x42,0x42,0x42,0x22,0x1F,0x00,0x00},/*"B",66*/
{0x00,0x00,0x00,0x7C,0x42,0x42,0x01,0x01,0x01,0x01,0x01,0x42,0x22,0x1C,0x00,0x00},/*"C",67*/
{0x00,0x00,0x00,0x1F,0x22,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1F,0x00,0x00},/*"D",68*/
{0x00,0x00,0x00,0x3F,0x42,0x12,0x12,0x1E,0x12,0x12,0x02,0x42,0x42,0x3F,0x00,0x00},/*"E",69*/
{0x00,0x00,0x00,0x3F,0x42,0x12,0x12,0x1E,0x12,0x12,0x02,0x02,0x02,0x07,0x00,0x00},/*"F",70*/
{0x00,0x00,0x00,0x3C,0x22,0x22,0x01,0x01,0x01,0x71,0x21,0x22,0x22,0x1C,0x00,0x00},/*"G",71*/
{0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x7E,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"H",72*/
{0x00,0x00,0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"I",73*/
{0x00,0x00,0x00,0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x11,0x0F},/*"J",74*/
{0x00,0x00,0x00,0x77,0x22,0x12,0x0A,0x0E,0x0A,0x12,0x12,0x22,0x22,0x77,0x00,0x00},/*"K",75*/
{0x00,0x00,0x00,0x07,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x42,0x7F,0x00,0x00},/*"L",76*/
{0x00,0x00,0x00,0x77,0x36,0x36,0x36,0x36,0x36,0x2A,0x2A,0x2A,0x2A,0x6B,0x00,0x00},/*"M",77*/
{0x00,0x00,0x00,0xE3,0x46,0x46,0x4A,0x4A,0x52,0x52,0x52,0x62,0x62,0x47,0x00,0x00},/*"N",78*/
{0x00,0x00,0x00,0x1C,0x22,0x41,0x41,0x41,0x41,0x41,0x41,0x41,0x22,0x1C,0x00,0x00},/*"O",79*/
{0x00,0x00,0x00,0x3F,0x42,0x42,0x42,0x42,0x3E,0x02,0x02,0x02,0x02,0x07,0x00,0x00},/*"P",80*/
{0x00,0x00,0x00,0x1C,0x22,0x41,0x41,0x41,0x41,0x41,0x41,0x4D,0x32,0x1C,0x60,0x00},/*"Q",81*/
{0x00,0x00,0x00,0x3F,0x42,0x42,0x42,0x3E,0x12,0x12,0x22,0x22,0x42,0xC7,0x00,0x00},/*"R",82*/
{0x00,0x00,0x00,0x7C,0x42,0x42,0x02,0x04,0x18,0x20,0x40,0x42,0x42,0x3E,0x00,0x00},/*"S",83*/
{0x00,0x00,0x00,0x7F,0x49,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1C,0x00,0x00},/*"T",84*/
{0x00,0x00,0x00,0xE7,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"U",85*/
{0x00,0x00,0x00,0xE7,0x42,0x42,0x22,0x24,0x24,0x14,0x14,0x18,0x08,0x08,0x00,0x00},/*"V",86*/
{0x00,0x00,0x00,0x6B,0x2A,0x2A,0x2A,0x2A,0x2A,0x36,0x14,0x14,0x14,0x14,0x00,0x00},/*"W",87*/
{0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x18,0x18,0x18,0x24,0x24,0x42,0xE7,0x00,0x00},/*"X",88*/
{0x00,0x00,0x00,0x77,0x22,0x22,0x14,0x14,0x08,0x08,0x08,0x08,0x08,0x1C,0x00,0x00},/*"Y",89*/
{0x00,0x00,0x00,0x7E,0x21,0x20,0x10,0x10,0x08,0x04,0x04,0x42,0x42,0x3F,0x00,0x00},/*"Z",90*/
{0x00,0x78,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x78,0x00},/*"[",91*/
{0x00,0x00,0x02,0x04,0x04,0x04,0x08,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x40,0x40},/*"\",92*/
{0x00,0x1E,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x1E,0x00},/*"]",93*/
{0x00,0x18,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"^",94*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF},/*"_",95*/
{0x00,0x06,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"`",96*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x22,0x30,0x2C,0x22,0x32,0x6C,0x00,0x00},/*"a",97*/
{0x00,0x00,0x00,0x00,0x03,0x02,0x02,0x1A,0x26,0x42,0x42,0x42,0x26,0x1A,0x00,0x00},/*"b",98*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x44,0x02,0x02,0x02,0x44,0x38,0x00,0x00},/*"c",99*/
{0x00,0x00,0x00,0x00,0x60,0x40,0x40,0x7C,0x42,0x42,0x42,0x42,0x62,0xDC,0x00,0x00},/*"d",100*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x7E,0x02,0x42,0x3C,0x00,0x00},/*"e",101*/
{0x00,0x00,0x00,0x00,0x30,0x48,0x08,0x3E,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"f",102*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x22,0x22,0x1C,0x02,0x3C,0x42,0x42,0x3C},/*"g",103*/
{0x00,0x00,0x00,0x00,0x03,0x02,0x02,0x3A,0x46,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"h",104*/
{0x00,0x00,0x00,0x0C,0x0C,0x00,0x00,0x0E,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"i",105*/
{0x00,0x00,0x00,0x30,0x30,0x00,0x00,0x38,0x20,0x20,0x20,0x20,0x20,0x20,0x22,0x1E},/*"j",106*/
{0x00,0x00,0x00,0x00,0x03,0x02,0x02,0x72,0x12,0x0A,0x0E,0x12,0x22,0x77,0x00,0x00},/*"k",107*/
{0x00,0x00,0x00,0x08,0x0E,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x3E,0x00,0x00},/*"l",108*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7F,0x92,0x92,0x92,0x92,0x92,0xB7,0x00,0x00},/*"m",109*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3B,0x46,0x42,0x42,0x42,0x42,0xE7,0x00,0x00},/*"n",110*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3C,0x42,0x42,0x42,0x42,0x42,0x3C,0x00,0x00},/*"o",111*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1B,0x26,0x42,0x42,0x42,0x26,0x1A,0x02,0x07},/*"p",112*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x58,0x64,0x42,0x42,0x42,0x64,0x58,0x40,0xE0},/*"q",113*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x4C,0x04,0x04,0x04,0x04,0x1F,0x00,0x00},/*"r",114*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x42,0x02,0x3C,0x40,0x42,0x3E,0x00,0x00},/*"s",115*/
{0x00,0x00,0x00,0x00,0x00,0x08,0x08,0x3E,0x08,0x08,0x08,0x08,0x48,0x30,0x00,0x00},/*"t",116*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x63,0x42,0x42,0x42,0x42,0x62,0xDC,0x00,0x00},/*"u",117*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x77,0x22,0x22,0x14,0x14,0x08,0x08,0x00,0x00},/*"v",118*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x91,0x52,0x5A,0x2A,0x24,0x24,0x00,0x00},/*"w",119*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6E,0x24,0x18,0x18,0x18,0x24,0x76,0x00,0x00},/*"x",120*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE7,0x42,0x24,0x24,0x18,0x18,0x08,0x08,0x06},/*"y",121*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x22,0x10,0x08,0x08,0x44,0x7E,0x00,0x00},/*"z",122*/
{0x00,0xC0,0x20,0x20,0x20,0x20,0x20,0x20,0x10,0x20,0x20,0x20,0x20,0x20,0xC0,0x00},/*"{",123*/
{0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10},/*"|",124*/
{0x00,0x03,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x04,0x04,0x04,0x04,0x04,0x03,0x00},/*"}",125*/
{0x04,0x5A,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"~",126*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/*"  ",127*/
};

/* 16*16汉字字库 */
unsigned char xiaochijing[6][16] = {
{0x00,0x02,0x04,0x04,0xE0,0x20,0x28,0x28,0x24,0x27,0xE4,0x24,0x04,0x04,0x04,0x00},
{0x02,0x02,0x02,0x02,0x3F,0x22,0x22,0x22,0x22,0x22,0x3F,0x22,0x02,0x02,0x02,0x02},/*"冲",0*/
{0x10,0x10,0x10,0xF8,0x88,0x84,0x82,0x80,0xFF,0x80,0x40,0x40,0x20,0x10,0x0C,0x03},
{0x00,0x00,0x00,0x1F,0x00,0x00,0x00,0x00,0x7F,0x00,0x01,0x01,0x02,0x04,0x18,0x60},/*"矢",1*/
{0x00,0xF8,0x08,0xF8,0x08,0xF8,0x00,0x30,0x0E,0x22,0x22,0x3A,0x26,0x12,0x08,0x06},
{0x00,0x0F,0x08,0x0F,0x08,0x0F,0x00,0x00,0x3F,0x21,0x21,0x21,0x29,0x11,0x01,0x01},/*"昴",2*/
};

/* 32*32汉字字库 */
unsigned char dachijing[16][32] = {
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x80,0x80,0xC0,0x40,0x60,0x30,0x10,0x08,0x04,0x00,0x80,0xC0,0x20,0x18,0x00},
{0x00,0x00,0x80,0x80,0x80,0x80,0x80,0xFF,0x80,0x80,0x80,0x80,0x80,0xFF,0x30,0x30,0x31,0x33,0x31,0x30,0x18,0x18,0x18,0x0C,0x0C,0x06,0x03,0x01,0x80,0x00,0x00,0x00},
{0x00,0x00,0x01,0x03,0x01,0x01,0x01,0xFF,0x01,0x01,0x01,0x01,0x01,0xFF,0x18,0x18,0x58,0x98,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x1F,0x1E,0x0C,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x07,0x00,0x00,0x00,0x00,0x30,0x7F,0x00,0x00,0x00,0x00,0x03,0x06,0x0C,0x1C,0x18,0x18,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"赤",0*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x60,0x18,0x04,0x00},
{0x00,0x00,0x08,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x08,0x08,0x0C,0x0C,0x0C,0x06,0x06,0x03,0x01,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x18,0x38,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x08,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"井",1*/
{0x00,0x00,0x00,0x00,0x80,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x20,0x18,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xC0,0x30,0x08,0x00},
{0x00,0x00,0x00,0x00,0xFF,0x80,0x80,0x80,0xFF,0xE0,0xB0,0x98,0x8C,0x86,0x83,0x80,0x00,0xFF,0x30,0x10,0x18,0x18,0x18,0x0C,0x0C,0x06,0x03,0x01,0x00,0x00,0x00,0x00},
{0x00,0x00,0x80,0xFE,0x03,0x01,0x01,0x01,0xFF,0x05,0x09,0x11,0x21,0xC1,0x81,0x00,0x10,0x3F,0x18,0x18,0x0C,0xFE,0x04,0x00,0x00,0x00,0x80,0x82,0xFC,0xF0,0x20,0x00},
{0x00,0x00,0x01,0x03,0x00,0x00,0x00,0x18,0x3F,0x00,0x00,0x00,0x00,0x00,0x03,0x1F,0x3C,0x08,0x00,0x00,0x02,0x07,0x03,0x03,0x03,0x01,0x01,0x01,0x01,0x00,0x00,0x00},/*"秀",2*/
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0C,0x3F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},/*"一",3*/
};

unsigned char *GetASCIIBuffer(const char c)
{
	return &ascii[c][0];
}

unsigned char *GetxiaochiAddr(unsigned char addr)
{
	return &xiaochijing[addr][0];
}

unsigned char *GetdachiAddr(unsigned char addr)
{
	return &dachijing[addr][0];
}
2.7 font.c
#include "font.h"
#include "drv_st7789.h"
#include<string.h>

/* 显示8**16的单个ASCII字符函数 */
void ShowChar(char c,unsigned short x,unsigned short y,unsigned short color)
{
	DisplayDevice *st7789 = GetST7789V2_Addr();
	st7789->SetWindows(st7789,x,x+8,y,y+16);
	unsigned short wbuf[128] = {0};
	st7789->FBBase = (unsigned short *)wbuf;
	unsigned char *fbuf = GetASCIIBuffer(c);
	unsigned char i =0;
	for(unsigned char y=0;y<16;y++)
	{
		for(unsigned char x=0;x<8;x++)
		{
			if((fbuf[y] & (0x01 << x)) != 0)
				wbuf[i] = color;
//				st7789->SetPixel(st7789,x,y,color);
			else
				wbuf[i] = ~color;
//				st7789->SetPixel(st7789,x,y,~color);
			i++;
		}
	}
	st7789->Flush(st7789);
}

/* 显示多个ASCII字符函数 */
void ShowString(char *wbuf,unsigned short x,unsigned short y,unsigned short color)
{
	if(NULL == wbuf)	return;
	while(*wbuf != 0)
	{
		ShowChar(*wbuf,x,y,color);
		x += 8;
		if(x>240)
		{
			x = 0;
			y++;
			if(y > 320)
				y = 0;
		}
		wbuf++;
	}
}

/* 显示半个16*16的汉字函数 */
void ShowChinese16Half(unsigned char data,unsigned short x,unsigned short y,unsigned short color)
{
	DisplayDevice *st7789 = GetST7789V2_Addr();
	st7789->SetWindows(st7789,x,x+8,y,y+16);
	unsigned short wbuf[128] = {0};
	st7789->FBBase = (unsigned short *)wbuf;
	unsigned char *buf = GetxiaochiAddr(data);
	unsigned char i = 0;
	for(unsigned char y=0;y<16;y++)
	{
		for(unsigned char x=0;x<8;x++)
		{
			if((*buf & (0x01 << x)) != 0)
				wbuf[i] = color;
			else
				wbuf[i] = ~color;
			i++;
		}
		buf++;
	}
	st7789->Flush(st7789);
}

/* 显示1/4个32*32的汉字函数 */
void ShowChinese32Quarter(unsigned char data,unsigned short x,unsigned short y,unsigned short color)
{
	DisplayDevice *st7789 = GetST7789V2_Addr();
	st7789->SetWindows(st7789,x,x+8,y,y+32);
	unsigned short wbuf[256] = {0};
	st7789->FBBase = (unsigned short *)wbuf;
	unsigned char *buf = GetdachiAddr(data);
	unsigned char i = 0;
	for(unsigned char y=0;y<32;y++)
	{
		for(unsigned char x=0;x<8;x++)
		{
			if((*buf & (0x01 << x)) != 0)
				wbuf[i] = color;
			else
				wbuf[i] = ~color;
			i++;
		}
		buf++;
	}
	st7789->Flush(st7789);
}
2.8 font.h
#ifndef __FONT_LIB_H
#define __FONT_LIB_H

unsigned char *GetASCIIBuffer(const char c);
unsigned char *GetxiaochiAddr(unsigned char addr);
unsigned char *GetdachiAddr(unsigned char addr);
void ShowChar( char c,unsigned short x,unsigned short y,unsigned short color);
void ShowString(char *wbuf,unsigned short x,unsigned short y,unsigned short color);
void ShowChinese16Half(unsigned char data,unsigned short x,unsigned short y,unsigned short color);
void ShowChinese32Quarter(unsigned char data,unsigned short x,unsigned short y,unsigned short color);


#endif
2.9 app_st7789_test.c

        将里面的测试函数声明后在主函数中调用

#include "stm32f4xx_hal.h"
#include "drv_st7789.h"
#include "errno.h"
#include "font.h"
#include "app.h"

void app_st7789_test(void)
{
	DisplayDevice *st7789 = GetST7789V2_Addr();
	int ret = st7789->Init(st7789);
	if(ret != ESUCCESS)	return;
	Display_Clear(0xFFFF);
	
	/* 从(0,0)开始显示字符串 */
	ShowString("Hello World!",0,0,0X0000);
	/* 从(0,16)开始显示字符串 */
	ShowString("123456789",0,16,0x0000);
	
	unsigned char  ch = 96;
	/* 从(96,48)开始显示汉字 */
	for(int i=0;i<6;i++)
	{
		ShowChinese16Half(i,ch,48,0x0000);
		ch += 8;
	}
	ch = 64;
	/* 从(64,72)开始显示汉字 */
	for(int i=0;i<16;i++)
	{
		ShowChinese32Quarter(i,ch,72,0x0000);
		ch += 8;
	}

	while(1)
	{

	}
}
2.10 测试结果

        如下图,按照我们的程序在指定位置显示了字符串和汉字

  • 27
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值