做毕设的时候遇到了难题,某宝买的一个小小的TFT LCD送的例程无法实现非填充模式,例如我想在显示屏上显示传感器获取到的数值,第一遍是正常的,但是后面显示的数值会在原来的基础上叠加,导致屏幕一团团的。
某宝的显示屏如下:
未修改显示函数效果如下:
查了好多帖子,最后在openedv论坛的某个大佬分享的源码和原子本来的例程中才找到了解决这个问题的办法,下面就是需要修改成非填充模式的操作。
函数原型为淘宝店家给的函数,就不全部列出来了,就仅仅把需要修改的地方写出来。
//******************************************************************
//函数名: LCD_ShowChar
//功能: 显示单个英文字符
//输入参数:(x,y):字符显示位置起始坐标
// fc:前置画笔颜色
// bc:背景颜色
// num:数值(0-94)
// size:字体大小
// mode:模式 0,非叠加模式;1,叠加模式
//返回值: 无
//修改记录:无
//******************************************************************
void LCD_ShowChar(u16 x,u16 y,u16 fc, u16 bc, u8 num,u8 size,u8 mode)
{
u8 temp,t1,t;
u8 csize=(size/8+((size%8)?1:0))*(size/2); //得到字体一个字符对应点阵集所占的字节数
num=num-' ';//得到偏移后的值
LCD_SetWindows(x,y,x+size/2-1,y+size-1);//设置单个文字显示窗口
for(t=0;t<csize;t++)
{
if(size==12)temp=asc2_1206[num][t];//调用1206字体
else temp=asc2_1608[num][t]; //调用1608字体
for(t1=0;t1<csize/2;t1++)
{
if(temp&0x01)
{
LCD_DrawPoint(x+t1,y+t);
LCD_WR_DATA_16Bit(POINT_COLOR);
}
else
{
if(mode==0)
{
LCD_DrawPoint(x+t1,y+t);
LCD_WR_DATA_16Bit(BACK_COLOR);
}
}
temp>>=1;
}
}
LCD_SetWindows(0,0,lcddev.width-1,lcddev.height-1);//恢复窗口为全屏
}
叠加模式不多说,非叠加模式就是当mode=0时,调用LCD_DrawPoint()进行画点,然后再在8位总线下写入一个16位数据,该数据位背景颜色BLACK_COLOR,后temp右移遍历。
//******************************************************************
//函数名: LCD_ShowNum
//功能: 显示单个数字变量值
//输入参数:x,y :起点坐标
// len :指定显示数字的位数
// size:字体大小(12,16)
// color:颜色
// num:数值(0~4294967295)
//返回值: 无
//修改记录:无
//******************************************************************
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
{
u8 t,temp;
u8 enshow=0;
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+(size/2)*t,y,POINT_COLOR,BACK_COLOR,' ',size,0);
continue;
}else enshow=1;
}
LCD_ShowChar(x+(size/2)*t,y,POINT_COLOR,BACK_COLOR,temp+'0',size,0);
}
}
其实这个函数最好还是在u8 size后面添加一个参数u8 mode,就可以在调用函数的时候方便修改模式,这里我偷懒为了使用该函数实现非填充模式就直接在函数调用LCD_ShowChar()函数的时候直接写参数0,固定成了非填充模式。
/****************************************************************************************************
//=======================================液晶屏数据线接线==========================================//
//CS 接PB12 //片选信号
//CLK 接PB13 //SPI时钟信号
//SDI(DIN) 接PB15 //SPI总线数据信号
//=======================================液晶屏控制线接线==========================================//
//RS(D/C) 接PB1 //寄存器/数据选择信号(RS=0数据总线发送的是指令;RS=1数据总线发送的是像素数据)
//RST 接系统复位NRST //液晶屏复位信号,低电平复位
/
//==================================如何精简到只需要3个IO=======================================//
//1.CS信号可以精简,不作SPI复用片选可将CS接地常低,节省1个IO
//2.LED背光控制信号可以接高电平3.3V背光常亮,节省1个IO
//3.RST复位信号可以接到单片机的复位端,利用系统上电复位,节省1个IO
//==================================如何切换横竖屏显示=======================================//
//打开lcd.h头文件,修改宏#define USE_HORIZONTAL 值为0使用竖屏模式.1,使用横屏模式
//===========================如何切换模拟SPI总线驱动和硬件SPI总线驱动=========================//
//打开lcd.h头文件,修改宏#define USE_HARDWARE_SPI 值为0使用模拟SPI总线.1,使用硬件SPI总线
**************************************************************************************************/
#include "delay.h"
#include "sys.h"
#include "lcd.h"
#include "gui.h"
#include "usart.h"
#include "led.h"
#include "usmart.h"
//LED 状态设置函数
void led_set(u8 sta)
{
LED0=sta;
}
//函数参数调用测试函数
void test_fun(void(*ledset)(u8),u8 sta)
{
ledset(sta);
}
__align(4) u8 dtbuf[50];
int main(void)
{
int x;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
uart_init(9600); //串口初始化为9600
delay_init(); //延时函数初始化
LED_Init();
SystemInit(); //初始化RCC 设置系统主频为72MHZ
LCD_Init(); //液晶屏初始化
usmart_dev.init(72); //初始化USMART
LCD_Clear(BLACK);
POINT_COLOR=RED;
while(1)
{
for(x=0;x<60;x++)
{
//LCD_ShowNum(52,52,x,2,16);
sprintf((char *)dtbuf,"%d",x);
//LCD_ShowString(10+38,10,16,dtbuf,0);
Gui_StrCenter(0,50,BLUE,YELLOW,dtbuf,16,0);//居中显示
delay_ms(1000);
}
if(x==60)
{
x=0;
}
}
}
主函数就是在屏幕上显示一个累加计时的功能,没什么特别的。具体的效果忘了拍图保存,下一篇帖子做MPU6050的时候有一张类似的效果图,可以参考那个。
需要源码的话看我简介取吧,项目代码都放那里,就不直接挂网盘了。