- 打卡等级:常住居民I
- 打卡总天数:79
- 最近打卡:2025-05-02 07:07:52
金牌会员
- 积分
- 1067
|
typedef struct
{
unsigned char Index[4];
unsigned char Msk[128];
}typFNT_GB32;
"康",0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x7F,0xFE,0xFF,0xFF,0xFF,0xF8,0xFF,
0xFF,0xFF,0xF9,0xFF,0xDF,0xFF,0xFB,0xE7,0x1F,0x00,0x00,0xC0,0x9F,0xFF,0xFD,0xFF,
0x9F,0xFF,0xF9,0xFF,0x9F,0xFF,0xFD,0xFE,0x9F,0x01,0x00,0xFC,0x9F,0xFF,0xFD,0xFC,
0x9F,0xFF,0xFD,0xFC,0x9F,0xFF,0xFD,0xE4,0x1F,0x00,0x00,0xC0,0x9F,0xFF,0xFD,0xFC,
0x9F,0xFF,0xFD,0xFC,0x9F,0x01,0x00,0xFC,0x9F,0xFF,0xF5,0xFE,0x9F,0xFB,0xF5,0xF3,
0x9F,0xE7,0xF5,0xE1,0xDF,0xCF,0xED,0xFC,0xDF,0xCF,0x4C,0xFE,0xCF,0x1F,0x9D,0xFF,
0xEF,0xCF,0x9D,0xFF,0xEF,0xE3,0x3D,0xFF,0xE7,0xF8,0x7D,0xFC,0x77,0xFC,0xFC,0xE0,
0xFB,0x1E,0xFC,0xE1,0xFB,0x7F,0xFC,0xF7,0xFD,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*"康",2*/
"佳",0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xF7,0xFF,0xFF,0xF9,0xC7,0xFF,
0xFF,0xF8,0xE7,0xFF,0xFF,0xFC,0xE7,0xFF,0xFF,0xFC,0xE7,0xFF,0x7F,0xFE,0xE7,0xF9,
0x7F,0x0E,0x00,0xF0,0x7F,0xFF,0xE7,0xFF,0x3F,0xFF,0xE7,0xFF,0x3F,0xFE,0xE7,0xFF,
0x5F,0xFE,0xE7,0xFF,0x4F,0xFE,0xE7,0xE7,0x6F,0x02,0x00,0xC0,0x77,0xFE,0xFF,0xFF,
0x7B,0xFE,0xE7,0xFF,0x7D,0xFE,0xC7,0xFF,0x7F,0xFE,0xE7,0xFF,0x7F,0xFE,0xE7,0xFF,
0x7F,0xFE,0xE7,0xFB,0x7F,0x0E,0x00,0xF0,0x7F,0xFE,0xE7,0xFF,0x7F,0xFE,0xE7,0xFF,
0x7F,0xFE,0xE7,0xFF,0x7F,0xFE,0xE7,0xFF,0x7F,0xFE,0xE7,0xFF,0x7F,0xFE,0xE7,0xE7,
0x7F,0x00,0x00,0xC0,0x7F,0xFE,0xFF,0xFF,0x7F,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,/*"佳",3*/
};
//======================================================================
#include "config.h"
#include "STC32G_SPI.h"
#include "LCD_TFT.h"
#include "face_word.h"
#include "ASCII_8x16_H.h"
char xdata buffer2[2000];
char *digit_code[13]={num0,num1,num2,num3,num4,num5,num6,num7,num8,num9,num10,num11,num12}; //指针数组,建立数字与字模的联系
//========================================================================
// 函数: void LCD_delay(u16 ms)
// 描述: 延时函数
// 参数: ms 延时时间 1~65535 ms
// 返回: 无
// 版本:
//========================================================================
void LCD_delay(u16 ms)
{
u16 i;
do{
// i = MAIN_Fosc / 14000; //STC12F
// i = MAIN_Fosc / 13000; //STC15F
// i = MAIN_Fosc / 10000; //STC8
i = MAIN_Fosc / 6000; //STC32G
while(--i) ;
}while(--ms);
}
/******************************************************************************
函数说明:LCD串行数据写入函数
入口数据:dat 要写入的串行数据
返回值: 无
******************************************************************************/
void transfer_data(unsigned int data1)//需要传送命令时加DC=0
{
CS=0;//怀疑这里的CS就是SPI的SS
SPSTAT=0xc0;//写一清零指令,最迷惑人的指令,明明在写一,作用是清零
SPDAT=data1;
while(!SPIF)
{
; //等待发送完成
}
}
/*************************************************
函数: void LCD_SetWindows(u16 xStar, u16 yStar,u16 xEnd,u16 yEnd)
功能: 设置lcd显示窗口,在此区域写点数据自动换行. 每行从 xStar开始 到yStar结束, 如果xStar==yStar则只写一点便换行, 可以用于画竖线.
入口: xy起点和终点
返回: 无
*************************************************/
//设置显示窗口函数,是基本函数
void lcd_address(unsigned int x_start,unsigned int y_start,unsigned int x_end,unsigned int y_end)
{
// unsigned short int x = x_start + 2,y=x_end+ 2;//屏参数2,不加参数时屏幕显示出亮边
unsigned int x = x_start ,y=x_end;//屏参数2
DC=0;
transfer_data(0x2a); //Column address set
DC=1;
transfer_data(x>>8); //start column
transfer_data(x);
transfer_data(y>>8); //end column
transfer_data(y);
//x = y_start + 1;//加1为偏移值,屏参数
x = y_start;//加1为偏移值,屏参数
//y=y_end+ 1;
y = y_end;
DC=0;
transfer_data(0x2b); //Row address set
DC=1;
transfer_data(x>>8); //start row
transfer_data(x);
transfer_data(y>>8); //end row
transfer_data(y);
DC=0;
transfer_data(0x2C); //Memory write
DC=1;
}
//====================================================================================
void DMASPI_initial(void)//批量数据传送时需要在命令执行完后先执行一下初始化,方便以后快速调用数据传送指令
{
DMA_SPI_TXAH=0;
DMA_SPI_TXAL=0;//只使用一个缓存数组时,简化该函数的形式,用起来更方便。地址是xdata的起始地址01:0000H
DMA_SPI_AMTH=0;
DMA_SPI_AMT=0;
DMA_SPI_STA=0;//清中断标志位及错误标志位
}
//============================================================================
//刷屏幕图像,把显示缓冲区的数据刷到屏幕上,也叫批量传送函数
void SPI_DMA_test(unsigned int num,char xdata *Q)//num为传送数据个数,受buffer空间限制,Q为使用的在xdata处的缓冲数组地址指针;
{
unsigned long addr;
addr=(unsigned long)(Q);//取地址指针的当前值,一般就是首地址值了
DMA_SPI_TXAH=(addr)>>8;
DMA_SPI_TXAL=addr;//只使用一个缓存数组时,简化该函数的形式,用起来更方便。地址是xdata的起始地址01:0000H
DMA_SPI_AMTH=(num-1)>>8;
DMA_SPI_AMT=(num-1);
DMA_SPI_STA=0;//清中断标志位及错误标志位
DMA_SPI_CR=0xc1;//开始执行,采用主机模式,并清空FIFO,这句明显要跟着程序走的
//使用DMA_SPI显示字符时,首先把数据传到buffer,然后开显示窗口,再传数据就行了。
while(!(DMA_SPI_STA&0x01))
{
; //等待吧。这时可以做其它事,比如去读一个AD值,最佳任务是处理中断。这个模式有可能丢掉数据,导致部分显示图像与原数据不同
}
DMASPI_initial();//
}
//========================================================================
// 函数: void LCD_Fill_XY(u8 x0,u16 y0,u8 x,u16 y,u16 color)
// 描述: 给屏填充开始坐标为x0,y0,长x,高y,以color的数据至各点中
// 参数: x0,y0 开始坐标, x 长, y 高, color: 要填充的颜色数据
// 返回: 无
// 版本: V1.0
//========================================================================
void LCD_Fill_XY(u16 x0,u16 y0,u16 x,u16 y,u16 color)
{
unsigned int i,j;
char xdata *p;
lcd_address(x0,y0,x,y);//示范围
for(j=0; j<64; j++)
{
p=public_buf;
for(i=0; i<1200; i++)
{
*p=(color>>8);
p++;
*p=(color);
p++;
}
SPI_DMA_test(2400,public_buf);
}
}
//=============================================================================================
void word16x16_bydma_spi(unsigned int x,unsigned int y,unsigned char code *p,int16 font_color,int16 back_color,char xdata *Q)
{
unsigned char column=0;
unsigned char tm=0,temp;
unsigned long kee;
// char *point;
char xdata *kkee;
kkee=Q;//这是保留缓冲区指针初值
// point=digit_code[segin];//把要显示的数字(segin)转换成对应的字模地址point
//先把字模数据转换成屏显所用数据存到缓冲区,因为写入缓冲区是并行处理,且没有其它操作。所以比写屏快很多
for(column=0; column<64; column++) //字节数循环,逐个字节进行转换
{
temp=*p;//*point是原字模数据指针,取出原字模数值
//把字节信息换算成屏需要的数据,送到缓冲区
for(tm=0; tm<8; tm++)
{
if(temp&0x01)//注意这是低位先出模式,如果与字模不符,可以考虑改为高位先出模式
{
*Q=(font_color>>8);//Q是缓冲区指针
Q++;
*Q=(font_color);
Q++;
}
else
{
*Q=(back_color>>8);
Q++;
*Q=(back_color);
Q++;
}
temp>>=1;
}
p++;
}
//开始刷屏,因为由DMA_SPI操作,基本不需要占用mcu时间。
lcd_address(x,y,x+15,y+15);
kee=(unsigned int)(kkee);//取缓冲区首地址的值,也就是打算发送给屏幕的数据源地址的值
DMA_SPI_TXAH=(kee)>>8;//把源地值高位赋给地址寄存器
DMA_SPI_TXAL=kee;//地址是xdata的起始地址
DMA_SPI_AMTH=1;//0x01,表示的传送总数据量是15*15*2/255
DMA_SPI_AMT=255;//0xff
Q=kkee;//缓冲区指针复位
DMA_SPI_STA=0;//清中断标志位及错误标志位
DMA_SPI_CR=0xc1;//开始执行,采用主机模式,并清空FIFO,这句明显要跟着程序走的
while(!(DMA_SPI_STA&0x01))
{
; //等待吧。这时可以做其它事,比如去读一个AD值,这个模式有可能丢掉数据,导致部分显示图像与原数据不同
}
DMASPI_initial();//
}
//==========================================================================================
//高级应用之字符显示程序--借助普通字模数组的显示程序,其中带有转换语句。方便显示不常用字符
void word16x32_bydma_spi(unsigned int x,unsigned int y,unsigned char segin,int font_color,int back_color,char *Q)
{
unsigned char column=0;
unsigned char tm=0,temp;
unsigned long kee;
char *point;
char *kkee;
kkee=Q;//这是保留缓冲区指针初值
point=digit_code[segin];//把要显示的数字(segin)转换成对应的字模地址point
//先把字模数据转换成屏显所用数据存到缓冲区,因为写入缓冲区是并行处理,且没有其它操作。所以比写屏快很多
for(column=0; column<64; column++) //字节数循环,逐个字节进行转换
{
temp=*point;//*point是原字模数据指针,取出原字模数值
//把字节信息换算成屏需要的数据,送到缓冲区
for(tm=0; tm<8; tm++)
{
if(temp&0x01)//注意这是低位先出模式,如果与字模不符,可以考虑改为高位先出模式
{
*Q=(font_color>>8);//Q是缓冲区指针
Q++;
*Q=(font_color);
Q++;
}
else
{
*Q=(back_color>>8);
Q++;
*Q=(back_color);
Q++;
}
temp>>=1;
}
point++;
}
//开始刷屏,因为由DMA_SPI操作,基本不需要占用mcu时间。
lcd_address(x,y,x+15,y+31);
kee=(unsigned int)(kkee);//取缓冲区首地址的值,也就是打算发送给屏幕的数据源地址的值
DMA_SPI_TXAH=(kee)>>8;//把源地值高位赋给地址寄存器
DMA_SPI_TXAL=kee;//地址是xdata的起始地址
DMA_SPI_AMTH=3;//0x03,表示的传送总数据量是3ffh+1,也就是1024
DMA_SPI_AMT=255;//0xff
Q=kkee;//缓冲区指针复位
DMA_SPI_STA=0;//清中断标志位及错误标志位
DMA_SPI_CR=0xc1;//开始执行,采用主机模式,并清空FIFO,这句明显要跟着程序走的
while(!(DMA_SPI_STA&0x01))
{
; //等待吧。这时可以做其它事,比如去读一个AD值,这个模式有可能丢掉数据,导致部分显示图像与原数据不同
}
DMASPI_initial();//
}
//=============================================================================================
void word32x32_bydma_spi(unsigned int x,unsigned int y,unsigned char code *p,int font_color,int back_color,char xdata *Q)
{
unsigned char column=0;
unsigned char tm=0,temp;
unsigned long kee;
// char *point;
char xdata *kkee;
kkee=Q;//这是保留缓冲区指针初值
// point=digit_code[segin];//把要显示的数字(segin)转换成对应的字模地址point
//先把字模数据转换成屏显所用数据存到缓冲区,因为写入缓冲区是并行处理,且没有其它操作。所以比写屏快很多
for(column=0; column<128; column++) //字节数循环,逐个字节进行转换
{
temp=*p;//*point是原字模数据指针,取出原字模数值
//把字节信息换算成屏需要的数据,送到缓冲区
for(tm=0; tm<8; tm++)
{
if(temp&0x01)//注意这是低位先出模式,如果与字模不符,可以考虑改为高位先出模式
{
*Q=(font_color>>8);//Q是缓冲区指针
Q++;
*Q=(font_color);
Q++;
}
else
{
*Q=(back_color>>8);
Q++;
*Q=(back_color);
Q++;
}
temp>>=1;
}
p++;
}
//开始刷屏,因为由DMA_SPI操作,基本不需要占用mcu时间。
lcd_address(x,y,x+31,y+31);
kee=(unsigned int)(kkee);//取缓冲区首地址的值,也就是打算发送给屏幕的数据源地址的值
DMA_SPI_TXAH=(kee)>>8;//把源地值高位赋给地址寄存器
DMA_SPI_TXAL=kee;//地址是xdata的起始地址
DMA_SPI_AMTH=7;//0x01,表示的传送总数据量是15*15*2/255
DMA_SPI_AMT=255;//0xff
Q=kkee;//缓冲区指针复位
DMA_SPI_STA=0;//清中断标志位及错误标志位
DMA_SPI_CR=0xc1;//开始执行,采用主机模式,并清空FIFO,这句明显要跟着程序走的
while(!(DMA_SPI_STA&0x01))
{
; //等待吧。这时可以做其它事,比如去读一个AD值,这个模式有可能丢掉数据,导致部分显示图像与原数据不同
}
DMASPI_initial();//
}
/******************************************************************************
函数说明:LCD初始化函数
入口数据:无
返回值: 无
******************************************************************************/
void Lcd_Init(void)
{
// SPI_SCK_1; //特别注意!!
RST=0;
LCD_delay(100);//1000
RST=1;
LCD_delay(100);//1000
//TFT_SEND_CMD(0x11); //Sleep Out
DC=0;
transfer_data(0x11);
DC=1;
LCD_delay(120); //DELAY120ms
//-----------------------ST7789V Frame rate setting-----------------//
//************************************************
// TFT_SEND_CMD(0x3A); //65k mode
DC=0;
transfer_data(0x3a);
DC=1;
transfer_data(0x05);
//TFT_SEND_CMD(0xC5); //VCOM
DC=0;
transfer_data(0xc5);
DC=1;
transfer_data(0x1A);
// TFT_SEND_CMD(0x36); // 屏幕显示方向设置
DC=0;
transfer_data(0x36);
DC=1;
//transfer_data(0x00);//竖屏值
// # if(UPSIDE_LCD==1)
//transfer_data(0xA0);//试验一下,希望是横屏,成功了60,A0旋转180度
//#endif
//# if(UPSIDE_LCD==0)
transfer_data(0x60);//试验一下,希望是横屏,成功了60,A0旋转180度
// #endif
//-------------ST7789V Frame rate setting-----------//
// TFT_SEND_CMD(0xb2); //Porch Setting
DC=0;
transfer_data(0xb2);
DC=1;
transfer_data(0x05);
transfer_data(0x05);
transfer_data(0x00);
transfer_data(0x33);
transfer_data(0x33);
// TFT_SEND_CMD(0xb7); //Gate Control
DC=0;
transfer_data(0xb7);
DC=1;
transfer_data(0x05); //12.2v -10.43v
//--------------ST7789V Power setting---------------//
// TFT_SEND_CMD(0xBB);//VCOM
DC=0;
transfer_data(0xbb);
DC=1;
transfer_data(0x3F);
// TFT_SEND_CMD(0xC0); //Power control
DC=0;
transfer_data(0xc0);
DC=1;
transfer_data(0x2c);
// TFT_SEND_CMD(0xC2); //VDV and VRH Command Enable
DC=0;
transfer_data(0xc2);
DC=1;
transfer_data(0x01);
// TFT_SEND_CMD(0xC3); //VRH Set
DC=0;
transfer_data(0xc3);
DC=1;
transfer_data(0x0F); //4.3+( vcom+vcom offset+vdv)
// TFT_SEND_CMD(0xC4); //VDV Set
DC=0;
transfer_data(0xc4);
DC=1;
transfer_data(0x20); //0v
// TFT_SEND_CMD(0xC6); //Frame Rate Control in Normal Mode
DC=0;
transfer_data(0xc6);
DC=1;
transfer_data(0X01); //111Hz
// TFT_SEND_CMD(0xd0); //Power Control 1
DC=0;
transfer_data(0xd0);
DC=1;
transfer_data(0xa4);
transfer_data(0xa1);
// TFT_SEND_CMD(0xE8); //Power Control 1
DC=0;
transfer_data(0xe8);
DC=1;
transfer_data(0x03);
// TFT_SEND_CMD(0xE9); //Equalize time control
DC=0;
transfer_data(0xe9);
DC=1;
transfer_data(0x09);
transfer_data(0x09);
transfer_data(0x08);
//---------------ST7789V gamma setting-------------//
// TFT_SEND_CMD(0xE0); //Set Gamma
DC=0;
transfer_data(0xe0);
DC=1;
transfer_data(0xD0);
transfer_data(0x05);
transfer_data(0x09);
transfer_data(0x09);
transfer_data(0x08);
transfer_data(0x14);
transfer_data(0x28);
transfer_data(0x33);
transfer_data(0x3F);
transfer_data(0x07);
transfer_data(0x13);
transfer_data(0x14);
transfer_data(0x28);
transfer_data(0x30);
// TFT_SEND_CMD(0XE1); //Set Gamma
DC=0;
transfer_data(0xe1);
DC=1;
transfer_data(0xD0);
transfer_data(0x05);
transfer_data(0x09);
transfer_data(0x09);
transfer_data(0x08);
transfer_data(0x03);
transfer_data(0x24);
transfer_data(0x32);
transfer_data(0x32);
transfer_data(0x3B);
transfer_data(0x14);
transfer_data(0x13);
transfer_data(0x28);
transfer_data(0x2F);
// TFT_SEND_CMD(0x20); //反显
DC=0;
transfer_data(0x20);
DC=1;
// TFT_SEND_CMD(0x29); //开启显示
DC=0;
transfer_data(0x29);
DC=1;
}
/******************************************************************************
函数说明:显示单个16x16汉字
入口数据:x,y显示坐标
*s 要显示的汉字
fc 字的颜色
bc 字的背景色
sizey 字号
返回值: 无
******************************************************************************/
void LCD_ShowChinese16x16(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey)
{
u8 i;
u16 k;
u16 HZnum; //汉字数目
u16 TypefaceNum; //一个字符所占字节大小
u16 x0=x;
TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
HZnum=sizeof(tfont16)/sizeof(typFNT_GB16); //统计汉字数目
for(k=0;k<HZnum;k++)
{
if((tfont16[k].Index[0]==*(s))&&(tfont16[k].Index[1]==*(s+1)))
{
for(i=0;i<TypefaceNum;i++)
{
word16x16_bydma_spi(x,y,&tfont16[k].Index[i],fc,bc,public_buf);//时间
break;
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
}
/******************************************************************************
函数说明:显示单个32x32汉字
入口数据:x,y显示坐标
*s 要显示的汉字
fc 字的颜色
bc 字的背景色
sizey 字号
mode: 0非叠加模式 1叠加模式
返回值: 无
******************************************************************************/
void LCD_ShowChinese32x32(u16 x,u16 y,u8 *s,u16 fc,u16 bc,u8 sizey)
{
u8 i,j,m=0;
u16 k;
u16 HZnum;//汉字数目
u16 TypefaceNum;//一个字符所占字节大小
u16 x0=x;
TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey;
HZnum=sizeof(tfont32)/sizeof(typFNT_GB32); //统计汉字数目
for(k=0; k<HZnum; k++)
{
if ((tfont32[k].Index[0]==*(s))&&(tfont32[k].Index[1]==*(s+1)))
{
for(i=0; i<TypefaceNum; i++)
{
word32x32_bydma_spi( x, y,&tfont32[k].Index[i],fc,bc,public_buf);
break;
}
}
continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响
}
}
/**********************************************************************************/
/******************************************************************************
函数说明:显示汉字串
入口数据:x,y显示坐标
*s 要显示的汉字串
fc 字的颜色
bc 字的背景色
sizey 字号 可选 16 24 32
mode: 0非叠加模式 1叠加模式
返回值: 无
******************************************************************************/
void LCD_ShowChinese(u16 x,u16 y,u8 *s,int16 fc,int16 bc,u8 sizey)
{
while(*s!=0)
{
if(sizey==16)
{
LCD_ShowChinese16x16(x,y,s,fc,bc,sizey);
}
else if(sizey==32)
{
LCD_ShowChinese32x32(x,y,s,fc,bc,sizey);
}
else
{
return;
}
s+=2;
x+=sizey;
}
}
//=======显示===========================
LCD_ShowChinese(100,100,"康佳",LIGHTBLUE,MAGENTA,32);
麻烦帮忙看一下,网站的程序原来数组显示的,改成直接输入汉字显示的,现在汉字的最上面多了一条虚线。
|
|