基于正点原子阿波罗F429开发板:
实验12 TFTLCD(MCU屏)实验项目制作
将发送数据并口改为串行发送:
lcd.c
#include "lcd.h"
#include "stdlib.h"
#include "font.h"
#include "usart.h"
#include "delay.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//2.8寸/3.5寸/4.3寸/7寸 TFT液晶驱动
//支持驱动IC型号包括:ILI9341/NT35310/NT35510/SSD1963/ST7789/ST7796/ILI9806等
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2016/1/16
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//********************************************************************************
//修改说明
//V1.2 20211111
//1,新增对ST7789驱动IC的支持
//V1.3 20211208
//修改NT5510 ID读取方式,改为先发送秘钥,然后读取C500和C501,从而获取正确的ID(0X5510)
//V1.4 20211222
//解决因NT5510 ID读取(发送C501指令)导致SSD1963误触发软件复位进而读取不到ID问题,加延时解决
//V1.5 20230608
//新增对ST7796和ILI9806 IC支持
//
//LCD的画笔颜色和背景色
u32 POINT_COLOR = 0xFF000000; //画笔颜色
u32 BACK_COLOR = 0xFFFFFFFF; //背景色
//管理LCD重要参数
//默认为竖屏
_lcd_dev lcddev;
/****************************/
void LCD_Writ_Bus(char dat) //串行数据写入
{
u8 i;
for(i=0;i<8;i++)
{
OLED_SCLK_Clr();
if(dat&0x80)
OLED_SDIN_Set();
else
OLED_SDIN_Clr();
OLED_SCLK_Set();
dat<<=1;
}
}
/*****************************/
void LCD_WR_DATA8(char da) //发送数据-8位参数
{ //OLED_CS_Clr();
OLED_DC_Set();
LCD_Writ_Bus(da);
//OLED_CS_Set;
}
//写寄存器函数
//regval:寄存器值
void LCD_WR_REG(vu16 regval)
{
// regval = regval; //使用-O2优化的时候,必须插入的延时
// LCD->LCD_REG = regval; //写入要写的寄存器序号
// OLED_CS_Clr();
OLED_DC_Clr();
LCD_Writ_Bus(regval>>8);
LCD_Writ_Bus(regval);
//OLED_CS_Set();
}
//写LCD数据
//data:要写入的值
void LCD_WR_DATA(vu16 data)
{
// data = data; //使用-O2优化的时候,必须插入的延时
// LCD->LCD_RAM = data;
// OLED_CS_Clr();
OLED_DC_Set();
LCD_Writ_Bus(data>>8);
LCD_Writ_Bus(data);
//OLED_CS_Set();
}
//读LCD数据
//返回值:读到的值
u16 LCD_RD_DATA(void)
{
vu16 ram; //防止被优化
return ram;
}
//写寄存器
//LCD_Reg:寄存器地址
//LCD_RegValue:要写入的数据
void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue)
{
// LCD->LCD_REG = LCD_Reg; //写入要写的寄存器序号
// LCD->LCD_RAM = LCD_RegValue;//写入数据
//OLED_CS_Clr();
LCD_WR_REG(LCD_Reg);
LCD_WR_DATA(LCD_RegValue);
//OLED_CS_Set();
}
//读寄存器
//LCD_Reg:寄存器地址
//返回值:读到的数据
u16 LCD_ReadReg(u16 LCD_Reg)
{
LCD_WR_REG(LCD_Reg); //写入要读的寄存器序号
delay_us(5);
return LCD_RD_DATA(); //返回读到的值
}
//开始写GRAM
void LCD_WriteRAM_Prepare(void)
{
LCD_WR_REG(lcddev.wramcmd); //写入要读的寄存器序号
}
//LCD写GRAM
//RGB_Code:颜色值
void LCD_WriteRAM(u16 RGB_Code)
{
LCD_WR_REG(RGB_Code);//写十六位GRAM
}
//从ILI93xx读出的数据为GBR格式,而我们写入的时候为RGB格式。
//通过该函数转换
//c:GBR格式的颜色值
//返回值:RGB格式的颜色值
u16 LCD_BGR2RGB(u16 c)
{
u16 r, g, b, rgb;
b = (c >> 0) & 0x1f;
g = (c >> 5) & 0x3f;
r = (c >> 11) & 0x1f;
rgb = (b << 11) + (g << 5) + (r << 0);
return (rgb);
}
//当mdk -O1时间优化时需要设置
//延时i
void opt_delay(u8 i)
{
while (i--);
}
//LCD开启显示
void LCD_DisplayOn(void)
{
if (lcddev.id == 0X5510) //5510开启显示指令
{
LCD_WR_REG(0X2900); //开启显示
}
else //9341/5310/1963/7789/7796/9806 等发送开启显示指令
{
LCD_WR_REG(0X29); //开启显示
}
}
//LCD关闭显示
void LCD_DisplayOff(void)
{
if (lcddev.id == 0X5510) //5510关闭显示指令
{
LCD_WR_REG(0X2800); //关闭显示
}
else //9341/5310/1963/7789/7796/9806 等发送关闭显示指令
{
LCD_WR_REG(0X28); //关闭显示
}
}
//设置光标位置(对RGB屏无效)
//Xpos:横坐标
//Ypos:纵坐标
void LCD_SetCursor(u16 Xpos, u16 Ypos)
{
// lcddev.setxcmd = 0x2a;
// lcddev.setycmd = 0x2b;
// LCD_WR_REG(lcddev.setxcmd);
// LCD_WR_DATA(Xpos >> 8);
// LCD_WR_DATA(Xpos & 0XFF);
// LCD_WR_REG(lcddev.setycmd);
// LCD_WR_DATA(Ypos >> 8);
// LCD_WR_DATA(Ypos & 0XFF);
LCD_WR_REG(0x2a);
LCD_WR_DATA8(Xpos>>8);
LCD_WR_DATA8(Xpos);
LCD_WR_DATA8(Xpos>>8);
LCD_WR_REG(0x2b);
LCD_WR_DATA8(Ypos>>8);
LCD_WR_DATA8(Ypos);
LCD_WR_DATA8(Ypos>>8);
LCD_WR_DATA8(Ypos);
LCD_WR_REG(0x2C);
}
void Address_set(unsigned int x1,unsigned int y1,unsigned int x2,unsigned int y2)
{
LCD_WR_REG(0x2a);
LCD_WR_DATA8(x1>>8);
LCD_WR_DATA8(x1);
LCD_WR_DATA8(x2>>8);
LCD_WR_DATA8(x2);
LCD_WR_REG(0x2b);
LCD_WR_DATA8(y1>>8);
LCD_WR_DATA8(y1);
LCD_WR_DATA8(y2>>8);
LCD_WR_DATA8(y2);
LCD_WR_REG(0x2C);
}
//设置LCD的自动扫描方向(对RGB屏无效)
//注意:其他函数可能会受到此函数设置的影响(尤其是9341),
//所以,一般设置为L2R_U2D即可,如果设置为其他扫描方式,可能导致显示不正常.
//dir:0~7,代表8个方向(具体定义见lcd.h)
//9341/5310/5510/1963/7789等IC已经实际测试
void LCD_Scan_Dir(u8 dir)
{
LCD_WR_REG(lcddev.setxcmd);
// LCD_WR_DATA(0);
// LCD_WR_DATA(0);
LCD_WR_DATA((lcddev.width - 1) >> 8);
LCD_WR_DATA((lcddev.width - 1) & 0XFF);
LCD_WR_REG(lcddev.setycmd);
// LCD_WR_DATA(0);
// LCD_WR_DATA(0);
LCD_WR_DATA((lcddev.height - 1) >> 8);
LCD_WR_DATA((lcddev.height - 1) & 0XFF);
}
//画点
//x,y:坐标
//POINT_COLOR:此点的颜色
void LCD_DrawPoint(u16 x, u16 y)
{
LCD_SetCursor(x, y); //设置光标位置
// LCD_WriteRAM_Prepare(); //开始写入GRAM
LCD_WR_DATA(POINT_COLOR);
}
//快速画点
//x,y:坐标
//color:颜色
void LCD_Fast_DrawPoint(u16 x, u16 y, u32 color)
{
LCD_SetCursor(x, y); //设置光标位置
// LCD_WriteRAM_Prepare(); //开始写入GRAM
LCD_WR_DATA(color);
}
//SSD1963 背光设置
//pwm:背光等级,0~100.越大越亮.
void LCD_SSD_BackLightSet(u8 pwm)
{
LCD_WR_REG(0xBE); //配置PWM输出
LCD_WR_DATA(0x05); //1设置PWM频率
LCD_WR_DATA(pwm * 2.55); //2设置PWM占空比
LCD_WR_DATA(0x01); //3设置C
LCD_WR_DATA(0xFF); //4设置D
LCD_WR_DATA(0x00); //5设置E
LCD_WR_DATA(0x00); //6设置F
}
//设置LCD显示方向
//dir:0,竖屏;1,横屏
void LCD_Display_Dir(u8 dir)
{
lcddev.dir = dir; //竖屏/横屏
if (dir == 0) //竖屏
{
lcddev.width = 240;
lcddev.height = 320;
}
else //横屏
{
lcddev.width = 320;
lcddev.height = 240;
}
// LCD_Scan_Dir(DFT_SCAN_DIR); //默认扫描方向
}
//设置窗口(对RGB屏无效),并自动设置画点坐标到窗口左上角(sx,sy).
//sx,sy:窗口起始坐标(左上角)
//width,height:窗口宽度和高度,必须大于0!!
//窗体大小:width*height.
void LCD_Set_Window(u16 sx, u16 sy, u16 width, u16 height)
{
u16 twidth, theight;
twidth = sx + width - 1;
theight = sy + height - 1;
if (lcddev.id == 0X1963 && lcddev.dir != 1) //1963竖屏特殊处理
{
sx = lcddev.width - width - sx;
height = sy + height - 1;
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(sx >> 8);
LCD_WR_DATA(sx & 0XFF);
LCD_WR_DATA((sx + width - 1) >> 8);
LCD_WR_DATA((sx + width - 1) & 0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(sy >> 8);
LCD_WR_DATA(sy & 0XFF);
LCD_WR_DATA(height >> 8);
LCD_WR_DATA(height & 0XFF);
}
else if (lcddev.id == 0X5510)
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(sx >> 8);
LCD_WR_REG(lcddev.setxcmd + 1);
LCD_WR_DATA(sx & 0XFF);
LCD_WR_REG(lcddev.setxcmd + 2);
LCD_WR_DATA(twidth >> 8);
LCD_WR_REG(lcddev.setxcmd + 3);
LCD_WR_DATA(twidth & 0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(sy >> 8);
LCD_WR_REG(lcddev.setycmd + 1);
LCD_WR_DATA(sy & 0XFF);
LCD_WR_REG(lcddev.setycmd + 2);
LCD_WR_DATA(theight >> 8);
LCD_WR_REG(lcddev.setycmd + 3);
LCD_WR_DATA(theight & 0XFF);
}
else //9341/5310/7789/1963/7796/9806横屏 等 设置窗口
{
LCD_WR_REG(lcddev.setxcmd);
LCD_WR_DATA(sx >> 8);
LCD_WR_DATA(sx & 0XFF);
LCD_WR_DATA(twidth >> 8);
LCD_WR_DATA(twidth & 0XFF);
LCD_WR_REG(lcddev.setycmd);
LCD_WR_DATA(sy >> 8);
LCD_WR_DATA(sy & 0XFF);
LCD_WR_DATA(theight >> 8);
LCD_WR_DATA(theight & 0XFF);
}
}
//初始化lcd
//该初始化函数可以初始化各种型号的LCD(详见本.c文件最前面的描述)
void LCD_Init(void)
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
//PB6,7,8,9
GPIO_Initure.Pin=GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull=GPIO_PULLUP; //上拉
GPIO_Initure.Speed=GPIO_SPEED_FAST; //快速
HAL_GPIO_Init(GPIOB,&GPIO_Initure);
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,GPIO_PIN_SET); //PB6置1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,GPIO_PIN_SET); //PB7置1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET); //PB8置1
HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET); //PB9置1
printf("\r\n 串行TFFTLCD屏幕引脚: DC:PB6 RES:PB7 SDA:PB8 SCK:PB9 \r\n");
/* 特别注意, 如果在main函数里面屏蔽串口1初始化, 则会卡死在printf
* 里面(卡死在f_putc函数), 所以, 必须初始化串口1, 或者屏蔽掉下面
* 这行 printf 语句 !!!!!!!
*/
printf(" LCD ID:%x\r\n", lcddev.id); //打印LCD ID
//7789初始化
//OLED_CS_Clr(); //打开片选使能
OLED_RST_Clr();
delay_ms(20);
OLED_RST_Set();
delay_ms(20);
// OLED_BLK_Set;
// LCD_WR_REG(0x11);
// delay_ms(120);
LCD_WR_REG(0x36);
LCD_WR_DATA8(0x00);
LCD_WR_REG(0x3A);
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);
LCD_WR_DATA8(0x35);
LCD_WR_REG(0xBB);
LCD_WR_DATA8(0x19);
LCD_WR_REG(0xC0);
LCD_WR_DATA8(0x2C);
LCD_WR_REG(0xC2);
LCD_WR_DATA8(0x01);
LCD_WR_REG(0xC3);
LCD_WR_DATA8(0x12);
LCD_WR_REG(0xC4);
LCD_WR_DATA8(0x20);
LCD_WR_REG(0xC6);
LCD_WR_DATA8(0x0F);
LCD_WR_REG(0xD0);
LCD_WR_DATA8(0xA4);
LCD_WR_DATA8(0xA1);
LCD_WR_REG(0xE0);
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);
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);
LCD_WR_REG(0x11);
//Delay (120);
LCD_WR_REG(0x29);
LCD_Display_Dir(0); //默认为竖屏
LCD_LED = 1; //点亮背光
LCD_Clear(GRED);
}
//清屏函数
//color:要清屏的填充色
void LCD_Clear(u32 color)
{
u32 index = 0;
u32 totalpoint = lcddev.width;
totalpoint *= lcddev.height; //得到总点数
Address_set(0,0,lcddev.width-1,lcddev.height-1);
// LCD_SetCursor(0,0);
for (index = 0; index < totalpoint; index++)
{
LCD_WR_DATA(color);
}
}
//在指定区域内填充单个颜色
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
//color:要填充的颜色
void LCD_Fill(u16 sx, u16 sy, u16 ex, u16 ey, u32 color)
{
u16 i, j;
u16 xlen = 0;
xlen = ex - sx + 1;
for (i = sy; i <= ey; i++)
{
LCD_SetCursor(sx, i); //设置光标位置
// LCD_WriteRAM_Prepare(); //开始写入GRAM
for (j = 0; j < xlen; j++)LCD_WR_DATA(color); //显示颜色
}
}
//在指定区域内填充指定颜色块
//(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)
//color:要填充的颜色
void LCD_Color_Fill(u16 sx, u16 sy, u16 ex, u16 ey, u16 *color)
{
u16 height, width;
u16 i, j;
width = ex - sx + 1; //得到填充的宽度
height = ey - sy + 1; //高度
for (i = 0; i < height; i++)
{
LCD_SetCursor(sx, sy + i); //设置光标位置
// LCD_WriteRAM_Prepare(); //开始写入GRAM
for (j = 0; j < width; j++)LCD_WR_DATA(color[i * width + j]); //写入数据
}
}
//画线
//x1,y1:起点坐标
//x2,y2:终点坐标
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
{
u16 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); //画点
xerr += delta_x ;
yerr += delta_y ;
if (xerr > distance)
{
xerr -= distance;
uRow += incx;
}
if (yerr > distance)
{
yerr -= distance;
uCol += incy;
}
}
}
//画矩形
//(x1,y1),(x2,y2):矩形的对角坐标
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
{
LCD_DrawLine(x1, y1, x2, y1);
LCD_DrawLine(x1, y1, x1, y2);
LCD_DrawLine(x1, y2, x2, y2);
LCD_DrawLine(x2, y1, x2, y2);
}
//在指定位置画一个指定大小的圆
//(x,y):中心点
//r :半径
void LCD_Draw_Circle(u16 x0, u16 y0, u8 r)
{
int a, b;
int di;
a = 0;
b = r;
di = 3 - (r << 1); //判断下个点位置的标志
while (a <= b)
{
LCD_DrawPoint(x0 + a, y0 - b); //5
LCD_DrawPoint(x0 + b, y0 - a); //0
LCD_DrawPoint(x0 + b, y0 + a); //4
LCD_DrawPoint(x0 + a, y0 + b); //6
LCD_DrawPoint(x0 - a, y0 + b); //1
LCD_DrawPoint(x0 - b, y0 + a);
LCD_DrawPoint(x0 - a, y0 - b); //2
LCD_DrawPoint(x0 - b, y0 - a); //7
a++;
//使用Bresenham算法画圆
if (di < 0)di += 4 * a + 6;
else
{
di += 10 + 4 * (a - b);
b--;
}
}
}
//在指定位置显示一个字符
//x,y:起始坐标
//num:要显示的字符:" "--->"~"
//size:字体大小 12/16/24/32
//mode:叠加方式(1)还是非叠加方式(0)
void LCD_ShowChar(u16 x, u16 y, u8 num, u8 size, u8 mode)
{
u8 temp;
u8 pos,t;
u16 x0=x;
u8 csize = (size / 8 + ((size % 8) ? 1 : 0)) * (size / 2); //得到字体一个字符对应点阵集所占的字节数
num=num-' ';//得到偏移后的值
if(!mode) //非叠加方式
{
for(pos=0;pos<csize;pos++)
{
temp=asc2_1608[num][pos]; //调用1608字体
for(t=0;t<8;t++)
{
if(temp&0x01)LCD_Fast_DrawPoint(x, y, POINT_COLOR);
else LCD_Fast_DrawPoint(x, y, BACK_COLOR);
temp>>=1;
x++;
}
x=x0;
y++;
}
}else//叠加方式
{
for(pos=0;pos<16;pos++)
{
temp=asc2_1608[num][pos]; //调用1608字体
for(t=0;t<8;t++)
{
if(temp&0x01)LCD_Fast_DrawPoint(x+t,y+pos, POINT_COLOR);//画一个点
temp>>=1;
}
}
}
}
//m^n函数
//返回值:m^n次方.
u32 LCD_Pow(u8 m, u8 n)
{
u32 result = 1;
while (n--)result *= m;
return result;
}
//显示数字,高位为0,则不显示
//x,y :起点坐标
//len :数字的位数
//size:字体大小
//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 / LCD_Pow(10, len - t - 1)) % 10;
if (enshow == 0 && t < (len - 1))
{
if (temp == 0)
{
LCD_ShowChar(x + (size / 2)*t, y, ' ', size, 0);
continue;
}
else enshow = 1;
}
LCD_ShowChar(x + (size / 2)*t, y, temp + '0', size, 0);
}
}
//显示数字,高位为0,还是显示
//x,y:起点坐标
//num:数值(0~999999999);
//len:长度(即要显示的位数)
//size:字体大小
//mode:
//[7]:0,不填充;1,填充0.
//[6:1]:保留
//[0]:0,非叠加显示;1,叠加显示.
void LCD_ShowxNum(u16 x, u16 y, u32 num, u8 len, u8 size, u8 mode)
{
u8 t, temp;
u8 enshow = 0;
for (t = 0; t < len; t++)
{
temp = (num / LCD_Pow(10, len - t - 1)) % 10;
if (enshow == 0 && t < (len - 1))
{
if (temp == 0)
{
if (mode & 0X80)LCD_ShowChar(x + (size / 2)*t, y, '0', size, mode & 0X01);
else LCD_ShowChar(x + (size / 2)*t, y, ' ', size, mode & 0X01);
continue;
}
else enshow = 1;
}
LCD_ShowChar(x + (size / 2)*t, y, temp + '0', size, mode & 0X01);
}
}
//显示字符串
//x,y:起点坐标
//width,height:区域大小
//size:字体大小
//*p:字符串起始地址
void LCD_ShowString(u16 x, u16 y, u16 width, u16 height, u8 size, u8 *p)
{
u8 x0 = x;
width += x;
height += y;
while ((*p <= '~') && (*p >= ' ')) //判断是不是非法字符!
{
if (x >= width)
{
x = x0;
y += size;
}
if (y >= height)break; //退出
LCD_ShowChar(x, y, *p, size, 0);
x += size / 2;
p++;
}
}
串口发送可以直接使用SPI进行发送,为了以后使用DMA进行发送,使用SPI记得提前做好引脚配置。
void SPI_LCD_Writ_Bus_ex(u8 dat,u8 channel) //串行数据写入
{
// u8 i;
//
// for(i=0;i<8;i++)
// {
// SPI_OLED_SCLK_Clr;
// if(dat&0x80)
// SPI_OLED_SDIN_Set;
// else
// SPI_OLED_SDIN_Clr;
// SPI_OLED_SCLK_Set;
// dat<<=1;
// }
if(channel == 0 ){ //串口发出
SPI2_WriteByte(dat);
}
if(channel == 1){ //spi发出,为未来DMA发送做准备
LCD_Writ_Bus_ex(dat);
}
}
lcd.h
#ifndef __LCD_H
#define __LCD_H
#include "sys.h"
#include "stdlib.h"
//
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板
//2.8寸/3.5寸/4.3寸/7寸 TFT液晶驱动
//支持驱动IC型号包括:ILI9341/NT35310/NT35510/SSD1963/ST7789/ST7796/ILI9806等
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//创建日期:2015/12/9
//版本:V1.5
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2014-2024
//All rights reserved
//********************************************************************************
//修改说明
//V1.2 20211111
//1,新增对ST7789驱动IC的支持
//V1.3 20211208
//修改NT5510 ID读取方式,改为先发送秘钥,然后读取C500和C501,从而获取正确的ID(0X5510)
//V1.4 20211222
//解决因NT5510 ID读取(发送C501指令)导致SSD1963误触发软件复位进而读取不到ID问题,加延时解决
//V1.5 20230608
//新增对ST7796和ILI9806 IC支持
//
//LCD重要参数集
typedef struct
{
u16 width; //LCD 宽度
u16 height; //LCD 高度
u16 id; //LCD ID
u8 dir; //横屏还是竖屏控制:0,竖屏;1,横屏。
u16 wramcmd; //开始写gram指令
u16 setxcmd; //设置x坐标指令
u16 setycmd; //设置y坐标指令
}_lcd_dev;
//LCD参数
extern _lcd_dev lcddev; //管理LCD重要参数
//LCD的画笔颜色和背景色
extern u32 POINT_COLOR;//默认红色
extern u32 BACK_COLOR; //背景颜色.默认为白色
//
//-----------------MCU屏 LCD端口定义----------------
#define LCD_LED PBout(5) //LCD背光 PB5
//
//扫描方向定义
#define L2R_U2D 0 //从左到右,从上到下
#define L2R_D2U 1 //从左到右,从下到上
#define R2L_U2D 2 //从右到左,从上到下
#define R2L_D2U 3 //从右到左,从下到上
#define U2D_L2R 4 //从上到下,从左到右
#define U2D_R2L 5 //从上到下,从右到左
#define D2U_L2R 6 //从下到上,从左到右
#define D2U_R2L 7 //从下到上,从右到左
#define DFT_SCAN_DIR L2R_U2D //默认的扫描方向
//画笔颜色
#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 //灰色
//GUI颜色
#define DARKBLUE 0X01CF //深蓝色
#define LIGHTBLUE 0X7D7C //浅蓝色
#define GRAYBLUE 0X5458 //灰蓝色
//以上三色为PANEL的颜色
#define LIGHTGREEN 0X841F //浅绿色
//#define LIGHTGRAY 0XEF5B //浅灰色(PANNEL)
#define LGRAY 0XC618 //浅灰色(PANNEL),窗体背景色
#define LGRAYBLUE 0XA651 //浅灰蓝色(中间层颜色)
#define LBBLUE 0X2B12 //浅棕蓝色(选择条目的反色)
void LCD_Init(void); //初始化
void LCD_DisplayOn(void); //开显示
void LCD_DisplayOff(void); //关显示
void LCD_Clear(u32 Color); //清屏
void LCD_SetCursor(u16 Xpos, u16 Ypos); //设置光标
void LCD_DrawPoint(u16 x,u16 y); //画点
void LCD_Fast_DrawPoint(u16 x,u16 y,u32 color); //快速画点
u32 LCD_ReadPoint(u16 x,u16 y); //读点
void LCD_Draw_Circle(u16 x0,u16 y0,u8 r); //画圆
void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2); //画线
void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2); //画矩形
void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u32 color); //填充单色
void LCD_Color_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 *color); //填充指定颜色
void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode); //显示一个字符
void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size); //显示一个数字
void LCD_ShowxNum(u16 x,u16 y,u32 num,u8 len,u8 size,u8 mode); //显示 数字
void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p); //显示一个字符串,12/16字体
void LCD_WriteReg(u16 LCD_Reg, u16 LCD_RegValue);
u16 LCD_ReadReg(u16 LCD_Reg);
void LCD_WriteRAM_Prepare(void);
void LCD_WriteRAM(u16 RGB_Code);
void LCD_SSD_BackLightSet(u8 pwm); //SSD1963 背光控制
void LCD_Scan_Dir(u8 dir); //设置屏扫描方向
void LCD_Display_Dir(u8 dir); //设置屏幕显示方向
void LCD_Set_Window(u16 sx,u16 sy,u16 width,u16 height); //设置窗口
//LCD分辨率设置
#define SSD_HOR_RESOLUTION 240 //LCD水平分辨率
#define SSD_VER_RESOLUTION 320 //LCD垂直分辨率
//-----------------OLED端口定义----------------
#define OLED_SCLK_Clr() PBout(9)=0 //PB9置0 //CLK
#define OLED_SCLK_Set() PBout(9)=1 //PB9置1
#define OLED_SDIN_Clr() PBout(8)=0//DIN
#define OLED_SDIN_Set() PBout(8)=1
#define OLED_RST_Clr() PBout(7)=0//RES
#define OLED_RST_Set() PBout(7)=1
#define OLED_DC_Clr() PBout(6)=0//DC
#define OLED_DC_Set() PBout(6)=1
#endif
main.c
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
/************************************************
ALIENTEK 阿波罗STM32F429开发板实验12
TFTLCD显示实验--HAL库函数版
技术支持:www.openedv.com
淘宝店铺:http://eboard.taobao.com
关注微信公众平台微信号:"正点原子",免费获取STM32资料。
广州市星翼电子科技有限公司
作者:正点原子 @ALIENTEK
************************************************/
int main(void)
{
u8 zf_h = 16;
u32 tt=0;
HAL_Init(); //初始化HAL库
Stm32_Clock_Init(360,25,2,8); //设置时钟,180Mhz
delay_init(180); //初始化延时函数
uart_init(115200); //初始化USART
LED_Init(); //初始化LED
// lcddev.setxcmd = 0x2a;
// lcddev.setycmd = 0x2b;
LCD_Init(); //初始化LCD
POINT_COLOR=RED;
LCD_Clear(WHITE);
LCD_ShowString(10,110,SSD_HOR_RESOLUTION,zf_h,zf_h,"ATOM@ALIENTEK");
LCD_ShowString(10,150,SSD_HOR_RESOLUTION,zf_h,zf_h,"2025/1/6");
while(1)
{
tt= tt+1;
LCD_ShowxNum(10,10,tt,8,zf_h,0);
LED0=!LED0;
delay_ms(100);
}
}
