先上图
这个图片我是没法了我太菜了只能用别人的软件绿色太多不知道是不是我人的问题还是软件的锅
还有滚动的功能没写暂时没用后面用了加
先上头文件
这个我为了以后方便移植用了宏定义
还有这个颜色是用windows上的画板看rgb的十进制然后用计算机转化顺序是RGB
#ifndef _ST7735_H
#define _ST7735_H
#include "main.h"
#include <stdio.h>
#define USE_CS 0 //只有一个设备就定义为一避免片选影响速度(为1时要多按下复位键不知道为啥)
#define PINK 0xD2F5
#define BLUE 0X03bD
#define RED 0xF882
#define YELLOW 0xFFE0
#define WHITE 0xffff
#define BLACK 0x0000
#define X_MAX_PIXEL 160
#define Y_MAX_PIXEL 80
#define LCD_DC_1() HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_SET)
#define LCD_DC_0() HAL_GPIO_WritePin(LCD_DC_GPIO_Port, LCD_DC_Pin, GPIO_PIN_RESET)
#define LCD_REST_1() HAL_GPIO_WritePin(LCD_REST_GPIO_Port, LCD_REST_Pin, GPIO_PIN_SET)
#define LCD_REST_0() HAL_GPIO_WritePin(LCD_REST_GPIO_Port, LCD_REST_Pin, GPIO_PIN_RESET)
#define LCD_BLK_1() HAL_GPIO_WritePin(LCD_BLK_GPIO_Port, LCD_BLK_Pin, GPIO_PIN_SET)
#define LCD_BLK_0() HAL_GPIO_WritePin(LCD_BLK_GPIO_Port, LCD_BLK_Pin, GPIO_PIN_RESET)
#define LCD_CS_1() HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_SET)
#define LCD_CS_0() HAL_GPIO_WritePin(LCD_CS_GPIO_Port, LCD_CS_Pin, GPIO_PIN_RESET)
#define LCD_Cmd() LCD_DC_0()
#define LCD_Dat() LCD_DC_1()
uint8_t St7735_InitPort(SPI_HandleTypeDef hspi);
void Lcd_SetPosPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, uint8_t x_end, uint8_t y_end);
void Lcd_ClearPort(SPI_HandleTypeDef hspi, uint16_t Color);
void Lcd_ClearPartPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, uint8_t x_end, uint8_t y_end, uint16_t Color);
void Lcd_AllWin(SPI_HandleTypeDef hspi);
void Lcd_WindowsPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t x_end);
void Color_Set(uint16_t FontColor, uint16_t BackColor);
void Lcd_ShowASCIIPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, char *Buffer, uint8_t size, uint8_t xy);
void Lcd_PicturePort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, uint8_t x_end, uint8_t y_end, uint8_t *Buffer,uint16_t len);
//freeRTOS里学到的
extern SPI_HandleTypeDef hspi2;
#define St7735_Init() St7735_InitPort(hspi2)
#define Lcd_SetPos(x_start, y_start, x_end, y_end) Lcd_SetPosPort(hspi2, (x_start), (y_start), (x_end), (y_end))
#define Lcd_Clear(Color) Lcd_ClearPort(hspi2, (Color));
#define Lcd_ClearPart(x_start, y_start, x_end, y_end, Color) Lcd_ClearPartPort(hspi2, (x_start), (y_start), (x_end), (y_end), (Color))
#define Lcd_AllWIn() Lcd_AllWin(hspi2)
#define Lcd_Windows(x_start, x_end) Lcd_WindowsPort(hspi2, (x_start), (x_end))
#define Lcd_ShowASCII_x(x_start, y_start, Buffer, size) Lcd_ShowASCIIPort(hspi2, (x_start), (y_start), (Buffer), (size), 0);
#define Lcd_ShowASCII_Y(x_start, y_start, Buffer, size) Lcd_ShowASCIIPort(hspi2, (x_start), (y_start), (Buffer), (size), 1);
#define Lcd_Picture(x_start, y_start, x_end, y_end, Buffer,len) Lcd_PicturePort(hspi2, (x_start), (y_start), (x_end), (y_end), (Buffer),(len));
#endif
注意下反演21H你也许不知的软件取出来的颜色是反演还是反演的反演多试试
36H是选择刷新方向还有RGB的顺序的与自己计算颜色时有关系
RGB代表红绿蓝。大多数情况下,RGB颜色存储在结构或无符号整数中,蓝色占据最不重要的“区域”(32位和24位格式的字节),绿色第二少,红色第三少。
BGR是相同的,除了区域顺序颠倒。红色占据最不重要的区域,绿色占第二位(静止),蓝色占第三位。
注意右下角那个宽X高才是我们要在图片函数里填的刚开始把我坑的还有注意xy的结尾特别是x详细的看我注释
#include "st7735.h"
#include "font.h"
uint16_t Font_Color = WHITE;
uint16_t Back_Color = BLACK;
/*修改全局变量point的颜色*/
void Color_Set(uint16_t FontColor, uint16_t BackColor)
{
Font_Color = FontColor;
Back_Color = BackColor;
}
static void LCD_SendCmd(SPI_HandleTypeDef hspi, uint8_t Cmd)
{
#if (USE_CS == 1)
{
LCD_Cmd();
HAL_SPI_Transmit(&hspi, &Cmd, 1, 0xffff);
}
#else
{
LCD_Cmd();
LCD_CS_0();
HAL_SPI_Transmit(&hspi, &Cmd, 1, 0xffff);
LCD_CS_1();
}
#endif
}
static void LCD_SendDat(SPI_HandleTypeDef hspi, uint8_t Dat)
{
#if (USE_CS == 1)
{
LCD_Dat();
HAL_SPI_Transmit(&hspi, &Dat, 1, 0xffff);
}
#else
LCD_Dat();
LCD_CS_0();
HAL_SPI_Transmit(&hspi, &Dat, 1, 0xfff);
LCD_CS_1();
#endif
}
static void LCD_ReadDat(SPI_HandleTypeDef hspi, uint8_t *ReBuffer, uint8_t size)
{
#if (USE_CS == 1)
{
LCD_Dat();
HAL_SPI_Receive(&hspi, ReBuffer, size, 0xffff);
}
#else
{
LCD_Dat();
LCD_CS_0();
HAL_SPI_Receive(&hspi, ReBuffer, size, 0xffff);
LCD_CS_1();
}
#endif
}
//发送像素点
static void LCD_SendPointPort(SPI_HandleTypeDef hspi, uint16_t Color)
{
uint8_t Dat[2] = {0};
Dat[0] = Color >> 4 & 0xFF;
Dat[1] = Color & 0x00FF;
#if (USE_CS == 1)
{
LCD_Dat();
HAL_SPI_Transmit(&hspi, Dat, 2, 0xfff);
}
#else
{
LCD_Dat();
LCD_CS_0();
HAL_SPI_Transmit(&hspi, Dat, 2, 0xfff);
LCD_CS_1();
}
#endif
}
uint8_t St7735_InitPort(SPI_HandleTypeDef hspi)
{
uint8_t test = 0xFF;
LCD_BLK_0(); //背光
LCD_CS_0(); //片选
HAL_Delay(120);
LCD_REST_1();
HAL_Delay(5);
LCD_REST_1();
HAL_Delay(120);
LCD_SendCmd(hspi, 0x11); //sleep out
HAL_Delay(120);
LCD_SendCmd(hspi, 0x0F); //简单的检查
LCD_ReadDat(hspi, &test, 1);
if (test != 0)
{
printf("erroe");
return 0;
}
else
{
LCD_SendCmd(hspi, 0xB1); //帧率
LCD_SendDat(hspi, 0x05);
LCD_SendDat(hspi, 0x3A);
LCD_SendDat(hspi, 0x3A);
LCD_SendCmd(hspi, 0xB2); //帧率
LCD_SendDat(hspi, 0x05);
LCD_SendDat(hspi, 0x3A);
LCD_SendDat(hspi, 0x3A);
LCD_SendCmd(hspi, 0xB3); //帧率
LCD_SendDat(hspi, 0x05);
LCD_SendDat(hspi, 0x3A);
LCD_SendDat(hspi, 0x3A);
LCD_SendDat(hspi, 0x05);
LCD_SendDat(hspi, 0x3A);
LCD_SendDat(hspi, 0x3A);
LCD_SendCmd(hspi, 0x21); //开反演(用的是电脑的画板自己转化的RGB565所以开反演)
LCD_SendCmd(hspi, 0xB4); //反演control
LCD_SendDat(hspi, 0x03);
LCD_SendCmd(hspi, 0xC0); //功率 control
LCD_SendDat(hspi, 0x62);
LCD_SendDat(hspi, 0x02);
LCD_SendDat(hspi, 0x04);
LCD_SendCmd(hspi, 0xC1);
LCD_SendDat(hspi, 0xC0);
LCD_SendCmd(hspi, 0xC2);
LCD_SendDat(hspi, 0x0D);
LCD_SendDat(hspi, 0x00);
LCD_SendCmd(hspi, 0xC3);
LCD_SendDat(hspi, 0x8D);
LCD_SendDat(hspi, 0x6A);
LCD_SendCmd(hspi, 0xC4);
LCD_SendDat(hspi, 0x8D);
LCD_SendDat(hspi, 0x6A);
LCD_SendCmd(hspi, 0xC5); //VCOM
LCD_SendDat(hspi, 0x0E);
LCD_SendCmd(hspi, 0xE0);
LCD_SendDat(hspi, 0x10);
LCD_SendDat(hspi, 0x0E);
LCD_SendDat(hspi, 0x02);
LCD_SendDat(hspi, 0x03);
LCD_SendDat(hspi, 0x0E);
LCD_SendDat(hspi, 0x07);
LCD_SendDat(hspi, 0x02);
LCD_SendDat(hspi, 0x07);
LCD_SendDat(hspi, 0x0A);
LCD_SendDat(hspi, 0x12);
LCD_SendDat(hspi, 0x27);
LCD_SendDat(hspi, 0x37);
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, 0x0D);
LCD_SendDat(hspi, 0x0E);
LCD_SendDat(hspi, 0x10);
LCD_SendCmd(hspi, 0xE1);
LCD_SendDat(hspi, 0x10);
LCD_SendDat(hspi, 0x0E);
LCD_SendDat(hspi, 0x03);
LCD_SendDat(hspi, 0x03);
LCD_SendDat(hspi, 0x0F);
LCD_SendDat(hspi, 0x06);
LCD_SendDat(hspi, 0x02);
LCD_SendDat(hspi, 0x08);
LCD_SendDat(hspi, 0x0A);
LCD_SendDat(hspi, 0x13);
LCD_SendDat(hspi, 0x26);
LCD_SendDat(hspi, 0x36);
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, 0x0D);
LCD_SendDat(hspi, 0x0E);
LCD_SendDat(hspi, 0x10);
LCD_SendCmd(hspi, 0x3A); //与硬件配合选择模式
LCD_SendDat(hspi, 0x05);
LCD_SendCmd(hspi, 0x36); //刷新方向
LCD_SendDat(hspi, 0x78);
LCD_SendCmd(hspi, 0x13); //复位是默认开启的
// LCD_SendCmd(hspi, 0xB4); //显示方向
// LCD_SendDat(hspi, 0x00);
LCD_SendCmd(hspi, 0x29); //display on
LCD_BLK_1();
return 1;
}
}
//设置光标并且规定了结束位置
void Lcd_SetPosPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, uint8_t x_end, uint8_t y_end)
{
LCD_SendCmd(hspi, 0x2A);
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, x_start + 1); //1~160不是0~159 实际传进的参数是0~159
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, x_end + 1);
LCD_SendCmd(hspi, 0x2B);
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, y_start + 26); //这个26与硬件有关
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, y_end + 26);
LCD_SendCmd(hspi, 0x2C);
}
//清屏
void Lcd_ClearPort(SPI_HandleTypeDef hspi, uint16_t Color)
{
uint16_t i;
Lcd_SetPosPort(hspi, 0, 0, 160, 80);
for (i = 0; i < X_MAX_PIXEL * (Y_MAX_PIXEL + 1); i++)
{
LCD_SendPointPort(hspi, Color);
}
}
//部分清屏
void Lcd_ClearPartPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, uint8_t x_end, uint8_t y_end, uint16_t Color)
{
uint16_t i;
Lcd_SetPosPort(hspi, x_start, y_start, x_end, y_end);
for (i = 0; i < (x_end - x_start) * (y_end - y_start + 1); i++)
{
LCD_SendPointPort(hspi, Color);
}
}
//还原到正常模式
void Lcd_AllWin(SPI_HandleTypeDef hspi)
{
LCD_SendCmd(hspi, 0x28);
LCD_SendCmd(hspi, 0x13);
LCD_SendCmd(hspi, 0x29);
}
//开窗没啥用建议用Lcd_SetPosPort
void Lcd_WindowsPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t x_end)
{
LCD_SendCmd(hspi, 0x12);
LCD_SendCmd(hspi, 0x30);
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, x_start + 1); //1~160不是0~159 实际传进的参数是0~159
LCD_SendDat(hspi, 0x00);
LCD_SendDat(hspi, x_end + 1);
}
// //显示ASSII8x16由size决定为以后扩展准备
// //ASCII中的0~31为控制字符;32~126为打印字符;127为Delete(删除)命令
// //Lcd_SetPosPort(hspi, x_start, y_start, len * 8 + x_start - 1, len * 16 + y_start - 1);
// //-1 是因为 假如len=1 1*8=8 0~8是9个数 1~160不是0~159 实际传进的参数是0~159(反正相当于转了两个弯)
// //len = sizeof(Buffer)/sizeof(uint8_t)-1没有\0 size = 字体型号的宽这只有16
// void Lcd_ShowASCIIPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, char *Buffer, uint8_t len, uint8_t size)
// {
// uint8_t i,j, k;
// Lcd_SetPosPort(hspi, x_start, y_start, len * size / 2 + x_start - 1, len * size + y_start - 1);
// while (*Buffer != '\0')
// {
// if (*Buffer < 32 && *Buffer > 126)
// {
// Buffer++; //跳过防止意外出现
// }
// else
// {
// i =*Buffer-32; //与ASCII对齐
// for (j = 0; j < 16; j++)
// {
// for (k = 0; k < 8; k++)
// {
// if (0x80 >> k & ASCII[i*size+j])
// {
// LCD_SendPointPort(hspi, Font_Color);
// }
// else
// {
// LCD_SendPointPort(hspi, Back_Color);
// }
// }
// }
// Buffer++;
// }
// }
// }
//上面的是第一代不行具体原因是我是先开窗但是点横着扫要满有行才换行这是没考虑到的显示单个可以两个就不行了
//还有就是要自己填写buffer长度智能能程序搞定干嘛动脑子在函数cd_ShowASCIIPort内用sizeof是计算的指针也许可以用strlen
//所以有了第二版保留思考过程上面没删除
void Lcd_ShowASCIIPort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, char *Buffer, uint8_t size, uint8_t xy)
{
uint8_t i, j, k, len;
len = 0;
while (*Buffer != '\0')
{
if (*Buffer < 32 && *Buffer > 126)
{
Buffer++; //跳过防止意外出现
}
else
{
if (xy == 1)
{
Lcd_SetPosPort(hspi, x_start, y_start + size * len, x_start + size / 2 - 1, y_start + size * (len + 1) - 1);
}
else
{
Lcd_SetPosPort(hspi, x_start + size / 2 * len, y_start, x_start + size / 2 * (len + 1) - 1, y_start + size - 1);
}
i = *Buffer - 32; //与ASCII对齐
for (j = 0; j < 16; j++)
{
for (k = 0; k < 8; k++)
{
if (0x80 >> k & ASCII[i * size + j])
{
LCD_SendPointPort(hspi, Font_Color);
}
else
{
LCD_SendPointPort(hspi, Back_Color);
}
}
}
Buffer++;
len++;
}
}
}
//注意x_end,y_end -1
void Lcd_PicturePort(SPI_HandleTypeDef hspi, uint8_t x_start, uint8_t y_start, uint8_t x_end, uint8_t y_end, uint8_t *Buffer,uint16_t len)
{
uint16_t i,Dat;
Lcd_SetPosPort(hspi, x_start, y_start, x_end, y_end);
for (i=0; i<len; i+=2)
{
Dat = *(Buffer+i);
Dat =(Dat<<4)&(*(Buffer+i+1));
LCD_SendPointPort(hspi,Dat);
}
}
最后说明下这个驱动是从右至左从上到下的自动换行所以取模就好办了吧
通向取模软件的们
https://blog.csdn.net/qq_15560295/article/details/105209478
这是屏幕上的本体你能信?