首发极术社区。如对兆易创新GD32F310 MCU感兴趣,欢迎添加微信 aijishu2020 加入GD32技术讨论群。
代码篇幅比较多,看测试结果请直接拉到最后。
一、硬件介绍
1. 屏幕介绍
-
屏幕驱动 ST7735
-
屏幕分辨率 135x240
-
驱动接口 SPI
2. 开发板连接
对应引脚
// GND 电源地
// VCC 接5V或3.3v电源
// SCL 接PA5(SCL)
// SDA 接PA7(SDA)
// CS 接PA4//可以直接接地
// RES 接PA3
// DC 接PA2
// BLK 接PA1
实物图
注意事项
这里使用的是硬件的SPI0,也就是用到了PA5和PA7这两个引脚,但是这块开发板的PA5是没有直接连接到外扩的引脚,中间这个排针需要跳一下,
![[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-U2kSatGX-1649642692184)(/img/bVbt1n “image.png”)](https://img-blog.csdnimg.cn/dcd3811d968941d5818142eea8466a7c.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5p6B5pyv56S-5Yy6,size_19,color_FFFFFF,t_70,g_se,x_16)
二、软件介绍
1. 开发环境
-
keil 5.36版本 编写程序
-
Image2Lcd 2.9 图片取模
-
PCtoLCD2002 字符取模
2. 代码
1.st7735.h
#ifndef _St7735_H #define _St7735_H #include "gd32f3x0.h" #include "systick.h" // GND 电源地 // VCC 接5V或3.3v电源 // SCL 接PA5(SCL) // SDA 接PA7(SDA) // CS 接PA4//可以直接接地 // RES 接PA3 // DC 接PA2 // BLK 接PA1 #define USE_HORIZONTAL 3 //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏 #define USE_HARDWARESPI // 设置使用硬件SPI还是软件SPI #if USE_HORIZONTAL==0||USE_HORIZONTAL==1 #define LCD_W 135 #define LCD_H 240 #else #define LCD_W 240 #define LCD_H 135 #endif //-----------------LCD端口定义---------------- #ifndef USE_HARDWARESPI #define LCD_SCLK_RCU RCU_GPIOA #define LCD_SCLK_PORT GPIOA #define LCD_SCLK_PIN GPIO_PIN_5 #define LCD_MOSI_RCU RCU_GPIOA #define LCD_MOSI_PORT GPIOA #define LCD_MOSI_PIN GPIO_PIN_7 #define LCD_SCLK_Clr() gpio_bit_reset(LCD_SCLK_PORT,LCD_SCLK_PIN)//SCL=SCLK #define LCD_SCLK_Set() gpio_bit_set(LCD_SCLK_PORT,LCD_SCLK_PIN) #define LCD_MOSI_Clr() gpio_bit_reset(LCD_MOSI_PORT,LCD_MOSI_PIN)//SDA=MOSI #define LCD_MOSI_Set() gpio_bit_set(LCD_MOSI_PORT,LCD_MOSI_PIN) #endif #define LCD_CS_RCU RCU_GPIOA #define LCD_CS_PORT GPIOA #define LCD_CS_PIN GPIO_PIN_4 #define LCD_RES_RCU RCU_GPIOA #define LCD_RES_PORT GPIOA #define LCD_RES_PIN GPIO_PIN_3 #define LCD_DC_RCU RCU_GPIOA #define LCD_DC_PORT GPIOA #define LCD_DC_PIN GPIO_PIN_2 #define LCD_BLK_RCU RCU_GPIOA #define LCD_BLK_PORT GPIOA #define LCD_BLK_PIN GPIO_PIN_1 #define LCD_CS_Clr() gpio_bit_reset(LCD_CS_PORT,LCD_CS_PIN)//CS #define LCD_CS_Set() gpio_bit_set(LCD_CS_PORT,LCD_CS_PIN) #define LCD_RES_Clr() gpio_bit_reset(LCD_RES_PORT,LCD_RES_PIN)//RES #define LCD_RES_Set() gpio_bit_set(LCD_RES_PORT,LCD_RES_PIN) #define LCD_DC_Clr() gpio_bit_reset(LCD_DC_PORT,LCD_DC_PIN)//DC #define LCD_DC_Set() gpio_bit_set(LCD_DC_PORT,LCD_DC_PIN) #define LCD_BLK_Clr() gpio_bit_reset(LCD_BLK_PORT,LCD_BLK_PIN)//BLK #define LCD_BLK_Set() gpio_bit_set(LCD_BLK_PORT,LCD_BLK_PIN) void LCD_GPIO_Init(void);//初始化GPIO void LCD_Writ_Bus(uint8_t dat);//模拟SPI时序 void LCD_WR_DATA8(uint8_t dat);//写入一个字节 void LCD_WR_DATA(uint16_t dat);//写入两个字节 void LCD_WR_REG(uint8_t dat);//写入一个指令 void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2);//设置坐标函数 void LCD_Init(void);//LCD初始化 #endif
2.st7735.c
#include "St7735.h" #include "GUI.h" #include "spi.h" void LCD_GPIO_Init(void) { #ifndef USE_HARDWARESPI /* SCLK */ rcu_periph_clock_enable(LCD_SCLK_RCU); gpio_mode_set(LCD_SCLK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_SCLK_PIN); gpio_output_options_set(LCD_SCLK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_SCLK_PIN); /* MOSI */ rcu_periph_clock_enable(LCD_MOSI_RCU); gpio_mode_set(LCD_MOSI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_MOSI_PIN); gpio_output_options_set(LCD_MOSI_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_MOSI_PIN); #endif /* CS */ rcu_periph_clock_enable(LCD_CS_RCU); gpio_mode_set(LCD_CS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_CS_PIN); gpio_output_options_set(LCD_CS_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_CS_PIN); gpio_bit_set(LCD_CS_PORT,LCD_CS_PIN); /* RES */ rcu_periph_clock_enable(LCD_RES_RCU); gpio_mode_set(LCD_RES_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_RES_PIN); gpio_output_options_set(LCD_RES_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_RES_PIN); gpio_bit_set(LCD_RES_PORT,LCD_RES_PIN); /* DC */ rcu_periph_clock_enable(LCD_DC_RCU); gpio_mode_set(LCD_DC_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_DC_PIN); gpio_output_options_set(LCD_DC_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_DC_PIN); gpio_bit_set(LCD_DC_PORT,LCD_DC_PIN); /* BLK */ rcu_periph_clock_enable(LCD_BLK_RCU); gpio_mode_set(LCD_BLK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LCD_BLK_PIN); gpio_output_options_set(LCD_BLK_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, LCD_BLK_PIN); } #ifdef USE_HARDWARESPI /****************************************************************************** 函数说明:LCD串行数据写入函数 入口数据:dat 要写入的串行数据 返回值: 无 ******************************************************************************/ void LCD_Writ_Bus(uint8_t dat) { LCD_CS_Clr(); spi_ReadWriteByte(dat); //delay_1ms(1); LCD_CS_Set(); } #else /****************************************************************************** 函数说明:LCD串行数据写入函数 入口数据:dat 要写入的串行数据 硬件SPI 返回值: 无 ******************************************************************************/ void LCD_Writ_Bus(uint8_t dat) { uint8_t i; LCD_CS_Clr(); for(i=0;i<8;i++) { LCD_SCLK_Clr(); if(dat&0x80) { LCD_MOSI_Set(); } else { LCD_MOSI_Clr(); } LCD_SCLK_Set(); dat<<=1; } LCD_CS_Set(); } #endif /****************************************************************************** 函数说明:LCD写入数据 入口数据:dat 写入的数据 返回值: 无 ******************************************************************************/ void LCD_WR_DATA8(uint8_t dat) { LCD_Writ_Bus(dat); } /****************************************************************************** 函数说明:LCD写入数据 入口数据:dat 写入的数据 返回值: 无 ******************************************************************************/ void LCD_WR_DATA(uint16_t dat) { LCD_Writ_Bus(dat>>8); LCD_Writ_Bus(dat); } /****************************************************************************** 函数说明:LCD写入命令 入口数据:dat 写入的命令 返回值: 无 ******************************************************************************/ void LCD_WR_REG(uint8_t dat) { LCD_DC_Clr();//写命令 LCD_Writ_Bus(dat); LCD_DC_Set();//写数据 } /****************************************************************************** 函数说明:设置起始和结束地址 入口数据:x1,x2 设置列的起始和结束地址 y1,y2 设置行的起始和结束地址 返回值: 无 ******************************************************************************/ void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2) { if(USE_HORIZONTAL==0) { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+52); LCD_WR_DATA(x2+52); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+40); LCD_WR_DATA(y2+40); LCD_WR_REG(0x2c);//储存器写 } else if(USE_HORIZONTAL==1) { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+53); LCD_WR_DATA(x2+53); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+40); LCD_WR_DATA(y2+40); LCD_WR_REG(0x2c);//储存器写 } else if(USE_HORIZONTAL==2) { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+40); LCD_WR_DATA(x2+40); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+53); LCD_WR_DATA(y2+53); LCD_WR_REG(0x2c);//储存器写 } else { LCD_WR_REG(0x2a);//列地址设置 LCD_WR_DATA(x1+40); LCD_WR_DATA(x2+40); LCD_WR_REG(0x2b);//行地址设置 LCD_WR_DATA(y1+52); LCD_WR_DATA(y2+52); LCD_WR_REG(0x2c);//储存器写 } } void LCD_Init(void) { LCD_GPIO_Init();//初始化GPIO LCD_RES_Clr();//复位 delay_1ms(100); LCD_RES_Set(); delay_1ms(50); LCD_BLK_Set();//打开背光 delay_1ms(100); LCD_WR_REG(0x11); //无此指令,不能正常初始化芯片,无显示 delay_1ms(120); LCD_WR_REG(0x36); //设置内存扫描方向,0X00正常扫描,从上往下,从左往右,RGB方式 if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00); else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0); else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70); else LCD_WR_DATA8(0xA0); LCD_WR_REG(0x3A); //数据格式,65K色,565 LCD_WR_DATA8(0x05); LCD_WR_REG(0xB2); //帧频设置 LCD_WR_DATA8(0x0C); LCD_WR_DATA8(0x0C); LCD_WR_DATA8(0x00); LCD_WR_DATA8(0x33); LCD_WR_DATA8(0x33); LCD_WR_REG(0xB7); //GATE 设置 LCD_WR_DATA8(0x35); LCD_WR_REG(0xBB); //VCOM设置 LCD_WR_DATA8(0x19); LCD_WR_REG(0xC0); //LCM设置,默认0x2c LCD_WR_DATA8(0x2C); LCD_WR_REG(0xC2); //VDV&VRH SET ,默认0x01 LCD_WR_DATA8(0x01); LCD_WR_REG(0xC3); //VRHS SET,默认0x0b LCD_WR_DATA8(0x12); //此处根据实际情况修正 LCD_WR_REG(0xC4); //VDV SET,默认0x20 LCD_WR_DATA8(0x20); LCD_WR_REG(0xC6); // FR SET, 默认0x0F LCD_WR_DATA8(0x0F); LCD_WR_REG(0xD0); //电源控制1 LCD_WR_DATA8(0xA4); //该参数不变 LCD_WR_DATA8(0xA1); //此处根据实际情况修改 LCD_WR_REG(0xE0); //正极性GAMMA调整 LCD_WR_DATA8(0xD0); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x0D); LCD_WR_DATA8(0x11); LCD_WR_DATA8(0x13); LCD_WR_DATA8(0x2B); LCD_WR_DATA8(0x3F); LCD_WR_DATA8(0x54); LCD_WR_DATA8(0x4C); LCD_WR_DATA8(0x18); LCD_WR_DATA8(0x0D); LCD_WR_DATA8(0x0B); LCD_WR_DATA8(0x1F); LCD_WR_DATA8(0x23); LCD_WR_REG(0xE1); //负极性GAMMA调整 LCD_WR_DATA8(0xD0); LCD_WR_DATA8(0x04); LCD_WR_DATA8(0x0C); LCD_WR_DATA8(0x11); LCD_WR_DATA8(0x13); LCD_WR_DATA8(0x2C); LCD_WR_DATA8(0x3F); LCD_WR_DATA8(0x44); LCD_WR_DATA8(0x51); LCD_WR_DATA8(0x2F); LCD_WR_DATA8(0x1F); LCD_WR_DATA8(0x1F); LCD_WR_DATA8(0x20); LCD_WR_DATA8(0x23); LCD_WR_REG(0x21); //反显开,默认是0X20,正常模式 LCD_WR_REG(0x29); //显示开,等待MCU数传送 }
3.GUI.h
#ifndef _GUI_H #define _GUI_H #include "gd32f3x0.h" #include "systick.h" //画笔颜色 #define bg 0xE73D #define WHITE 0xFFFF #define BLACK 0x0000 #define BLUE 0x001F #define BRED 0XF81F #define GRED 0XFFE0 #define GBLUE 0X07FF #define RED 0xF800 #define MAGENTA 0xF81F #define GREEN 0x07E0 #define CYAN 0x7FFF #define YELLOW 0xFFE0 #define BROWN 0XBC40 //棕色 #define BRRED 0XFC07 //棕红色 #define GRAY 0X8430 //灰色 #define DARKBLUE 0X01CF //深蓝色 #define LIGHTBLUE 0X7D7C //浅蓝色 #define GRAYBLUE 0X5458 //灰蓝色 #define LIGHTGREEN 0X841F //浅绿色 #define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色 #define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色) #define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色) void LCD_Fill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t color);//指定区域填充颜色 void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color);//在指定位置画一个点 void LCD_DrawLine(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t color);//在指定位置画一条线 void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color);//在指定位置画一个矩形 void Draw_Circle(uint16_t x0,uint16_t y0,uint8_t r,uint16_t color);//在指定位置画一个圆 void LCD_ShowChinese(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);//显示汉字串 void LCD_ShowChinese12x12(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);//显示单个12x12汉字 void LCD_ShowChinese16x16(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);//显示单个16x16汉字 void LCD_ShowChinese24x24(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);//显示单个24x24汉字 void LCD_ShowChinese32x32(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);//显示单个32x32汉字 void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);//显示一个字符 void LCD_ShowString(uint16_t x,uint16_t y,const uint8_t *p,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode);//显示字符串 uint32_t mypow(uint8_t m,uint8_t n);//求幂 void LCD_ShowIntNum(uint16_t x,uint16_t y,uint16_t num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey);//显示整数变量 void LCD_ShowFloatNum1(uint16_t x,uint16_t y,float num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey);//显示两位小数变量 void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[]);//显示图片 #endif
4.GUI.c
#include "GUI.h" #include "lcdfont.h" #include "St7735.h" /****************************************************************************** 函数说明:在指定区域填充颜色 入口数据:xsta,ysta 起始坐标 xend,yend 终止坐标 color 要填充的颜色 返回值: 无 ******************************************************************************/ void LCD_Fill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t color) { uint16_t i,j; LCD_Address_Set(xsta,ysta,xend-1,yend-1);//设置显示范围 for(i=ysta;i<yend;i++) { for(j=xsta;j<xend;j++) { LCD_WR_DATA(color); } } } /****************************************************************************** 函数说明:在指定位置画点 入口数据:x,y 画点坐标 color 点的颜色 返回值: 无 ******************************************************************************/ void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color) { LCD_Address_Set(x,y,x,y);//设置光标位置 LCD_WR_DATA(color); } /****************************************************************************** 函数说明:画线 入口数据:x1,y1 起始坐标 x2,y2 终止坐标 color 线的颜色 返回值: 无 ******************************************************************************/ void LCD_DrawLine(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2,uint16_t color) { 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+1;t++) { LCD_DrawPoint(uRow,uCol,color);//画点 xerr+=delta_x; yerr+=delta_y; if(xerr>distance) { xerr-=distance; uRow+=incx; } if(yerr>distance) { yerr-=distance; uCol+=incy; } } } /****************************************************************************** 函数说明:画矩形 入口数据:x1,y1 起始坐标 x2,y2 终止坐标 color 矩形的颜色 返回值: 无 ******************************************************************************/ void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color) { LCD_DrawLine(x1,y1,x2,y1,color); LCD_DrawLine(x1,y1,x1,y2,color); LCD_DrawLine(x1,y2,x2,y2,color); LCD_DrawLine(x2,y1,x2,y2,color); } /****************************************************************************** 函数说明:画圆 入口数据:x0,y0 圆心坐标 r 半径 color 圆的颜色 返回值: 无 ******************************************************************************/ void Draw_Circle(uint16_t x0,uint16_t y0,uint8_t r,uint16_t color) { int a,b; a=0;b=r; while(a<=b) { LCD_DrawPoint(x0-b,y0-a,color); //3 LCD_DrawPoint(x0+b,y0-a,color); //0 LCD_DrawPoint(x0-a,y0+b,color); //1 LCD_DrawPoint(x0-a,y0-b,color); //2 LCD_DrawPoint(x0+b,y0+a,color); //4 LCD_DrawPoint(x0+a,y0-b,color); //5 LCD_DrawPoint(x0+a,y0+b,color); //6 LCD_DrawPoint(x0-b,y0+a,color); //7 a++; if((a*a+b*b)>(r*r))//判断要画的点是否过远 { b--; } } } /****************************************************************************** 函数说明:显示汉字串 入口数据:x,y显示坐标 *s 要显示的汉字串 fc 字的颜色 bc 字的背景色 sizey 字号 可选 16 24 32 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode) { while(*s!=0) { if(sizey==12) LCD_ShowChinese12x12(x,y,s,fc,bc,sizey,mode); else if(sizey==16) LCD_ShowChinese16x16(x,y,s,fc,bc,sizey,mode); else if(sizey==24) LCD_ShowChinese24x24(x,y,s,fc,bc,sizey,mode); else if(sizey==32) LCD_ShowChinese32x32(x,y,s,fc,bc,sizey,mode); else return; s+=2; x+=sizey; } } /****************************************************************************** 函数说明:显示单个12x12汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese12x12(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode) { uint8_t i,j,m=0; uint16_t k; uint16_t HZnum;//汉字数目 uint16_t TypefaceNum;//一个字符所占字节大小 uint16_t x0=x; TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey; HZnum=sizeof(tfont12)/sizeof(typFNT_GB12); //统计汉字数目 for(k=0;k<HZnum;k++) { if((tfont12[k].Index[0]==*(s))&&(tfont12[k].Index[1]==*(s+1))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont12[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont12[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个16x16汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese16x16(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode) { uint8_t i,j,m=0; uint16_t k; uint16_t HZnum;//汉字数目 uint16_t TypefaceNum;//一个字符所占字节大小 uint16_t 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))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont16[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont16[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个24x24汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese24x24(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode) { uint8_t i,j,m=0; uint16_t k; uint16_t HZnum;//汉字数目 uint16_t TypefaceNum;//一个字符所占字节大小 uint16_t x0=x; TypefaceNum=(sizey/8+((sizey%8)?1:0))*sizey; HZnum=sizeof(tfont24)/sizeof(typFNT_GB24); //统计汉字数目 for(k=0;k<HZnum;k++) { if ((tfont24[k].Index[0]==*(s))&&(tfont24[k].Index[1]==*(s+1))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont24[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont24[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个32x32汉字 入口数据:x,y显示坐标 *s 要显示的汉字 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChinese32x32(uint16_t x,uint16_t y,uint8_t *s,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode) { uint8_t i,j,m=0; uint16_t k; uint16_t HZnum;//汉字数目 uint16_t TypefaceNum;//一个字符所占字节大小 uint16_t 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))) { LCD_Address_Set(x,y,x+sizey-1,y+sizey-1); for(i=0;i<TypefaceNum;i++) { for(j=0;j<8;j++) { if(!mode)//非叠加方式 { if(tfont32[k].Msk[i]&(0x01<<j))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizey==0) { m=0; break; } } else//叠加方式 { if(tfont32[k].Msk[i]&(0x01<<j)) LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizey) { x=x0; y++; break; } } } } } continue; //查找到对应点阵字库立即退出,防止多个汉字重复取模带来影响 } } /****************************************************************************** 函数说明:显示单个字符 入口数据:x,y显示坐标 num 要显示的字符 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowChar(uint16_t x,uint16_t y,uint8_t num,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode) { uint8_t temp,sizex,t,m=0; uint16_t i,TypefaceNum;//一个字符所占字节大小 uint16_t x0=x; sizex=sizey/2; TypefaceNum=(sizex/8+((sizex%8)?1:0))*sizey; num=num-' '; //得到偏移后的值 LCD_Address_Set(x,y,x+sizex-1,y+sizey-1); //设置光标位置 for(i=0;i<TypefaceNum;i++) { if(sizey==12)temp=ascii_1206[num][i]; //调用6x12字体 else if(sizey==16)temp=ascii_1608[num][i]; //调用8x16字体 else if(sizey==24)temp=ascii_2412[num][i]; //调用12x24字体 else if(sizey==32)temp=ascii_3216[num][i]; //调用16x32字体 else return; for(t=0;t<8;t++) { if(!mode)//非叠加模式 { if(temp&(0x01<<t))LCD_WR_DATA(fc); else LCD_WR_DATA(bc); m++; if(m%sizex==0) { m=0; break; } } else//叠加模式 { if(temp&(0x01<<t))LCD_DrawPoint(x,y,fc);//画一个点 x++; if((x-x0)==sizex) { x=x0; y++; break; } } } } } /****************************************************************************** 函数说明:显示字符串 入口数据:x,y显示坐标 *p 要显示的字符串 fc 字的颜色 bc 字的背景色 sizey 字号 mode: 0非叠加模式 1叠加模式 返回值: 无 ******************************************************************************/ void LCD_ShowString(uint16_t x,uint16_t y,const uint8_t *p,uint16_t fc,uint16_t bc,uint8_t sizey,uint8_t mode) { while(*p!='\0') { LCD_ShowChar(x,y,*p,fc,bc,sizey,mode); x+=sizey/2; p++; } } /****************************************************************************** 函数说明:显示数字 入口数据:m底数,n指数 返回值: 无 ******************************************************************************/ uint32_t mypow(uint8_t m,uint8_t n) { uint32_t result=1; while(n--)result*=m; return result; } /****************************************************************************** 函数说明:显示整数变量 入口数据:x,y显示坐标 num 要显示整数变量 len 要显示的位数 fc 字的颜色 bc 字的背景色 sizey 字号 返回值: 无 ******************************************************************************/ void LCD_ShowIntNum(uint16_t x,uint16_t y,uint16_t num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey) { uint8_t t,temp; uint8_t enshow=0; uint8_t sizex=sizey/2; for(t=0;t<len;t++) { temp=(num/mypow(10,len-t-1))%10; if(enshow==0&&t<(len-1)) { if(temp==0) { LCD_ShowChar(x+t*sizex,y,' ',fc,bc,sizey,0); continue; }else enshow=1; } LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0); } } /****************************************************************************** 函数说明:显示两位小数变量 入口数据:x,y显示坐标 num 要显示小数变量 len 要显示的位数 fc 字的颜色 bc 字的背景色 sizey 字号 返回值: 无 ******************************************************************************/ void LCD_ShowFloatNum1(uint16_t x,uint16_t y,float num,uint8_t len,uint16_t fc,uint16_t bc,uint8_t sizey) { uint8_t t,temp,sizex; uint16_t num1; sizex=sizey/2; num1=num*100; for(t=0;t<len;t++) { temp=(num1/mypow(10,len-t-1))%10; if(t==(len-2)) { LCD_ShowChar(x+(len-2)*sizex,y,'.',fc,bc,sizey,0); t++; len+=1; } LCD_ShowChar(x+t*sizex,y,temp+48,fc,bc,sizey,0); } } /****************************************************************************** 函数说明:显示图片 入口数据:x,y起点坐标 length 图片长度 width 图片宽度 pic[] 图片数组 返回值: 无 ******************************************************************************/ void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[]) { uint16_t i,j; uint32_t k=0; LCD_Address_Set(x,y,x+length-1,y+width-1); for(i=0;i<length;i++) { for(j=0;j<width;j++) { LCD_WR_DATA8(pic[k*2]); LCD_WR_DATA8(pic[k*2+1]); k++; } } }
5.main.c
/*! \file main.c \brief led spark with systick, USART print and key example \version 2017-06-06, V1.0.0, firmware for GD32F3x0 \version 2019-06-01, V2.0.0, firmware for GD32F3x0 \version 2020-09-30, V2.1.0, firmware for GD32F3x0 \version 2022-01-06, V2.2.0, firmware for GD32F3x0 */ /* Copyright (c) 2022, GigaDevice Semiconductor Inc. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "gd32f3x0.h" #include "systick.h" #include <stdio.h> #include "main.h" #include "led.h" #include "St7735.h" #include "spi.h" #include "GUI.h" #include "pic.h" /*! \brief main function \param[in] none \param[out] none \retval none */ int main(void) { /* configure systick */ systick_config(); led_init(); // led初始化 #ifdef USE_HARDWARESPI spi_config(); #endif LCD_Init();//LCD初始化 LCD_Fill(0,0,LCD_W,LCD_H,RED); while(1) { // LED1_ON; // 亮 // delay_1ms(1000); // // LED1_OFF; // 灭 // delay_1ms(1000); LCD_ShowChinese(50,0,"测试",YELLOW,RED,32,0);// LCD_ShowString(50+32*2,0,"GD32",YELLOW,RED,32,0); LCD_ShowString(40,40,"LCD_W:",BLUE,RED,16,0); LCD_ShowIntNum(40 + 48,40,LCD_W,3,BLACK,RED,16); LCD_ShowString(40 + 80,40,"LCD_H:",BLUE,RED,16,0); LCD_ShowIntNum(40 +128,40,LCD_H,3,BLACK,RED,16); LCD_ShowPicture(50,60,140,67,gImage_GD32_logo_140x67); } }
6.lcdfont.h
太多了。
7.pic.h
太多了,请自行取模。
3.可调配置
1.横屏和竖屏
在st7735头文件中有一个宏 USE_HORIZONTAL
配置为0和1 为竖屏显示 配置为2和3位横屏显示
2. 软件SPI和硬件SPI
在st7735头文件中有一个宏USE_HARDWARESPI
当定义这个宏的时候使用硬件SPI,注释掉这个宏使用软件SPI
三、测试结果
可以显示字符,汉字和图片。
特写: