一、介绍
STEVAL-STWINKT1B开发板虽然没有板载的显示屏,但是预留了40Pin的扩展接口,和一个STMod+的接口,可以很方便地连接一些扩展模块。
本次我们通过40PIN的连接器连接我们的一块LCD屏,通过LCD屏显示之前用到的传感器采集到的信息,本次只做简单的显示功能,并不包含GUI的移植。
GUI又是另外一个大的topic了,不在本次的测评范围内。
二、硬件连接
LCD屏选的是DFROBOT的一款2寸的IPS屏。详细介绍如下:
2.0寸LCD显示模块采用ST7789V驱动芯片,具有320x240个彩色像素点(RGB565)。这是一款IPS显示模块,拥有优秀的可视角度(80/80/80/80);采用SPI(4线)通信方式;支持GDI接口(GDI接口必须和带GDI接口主控配合使用),即插即用。模块具有分辨率高、可视角度广、接线简单等优点,可用于许多显示应用:波形显示器、电子纪念盒、桌面天气摆件等。 2.0寸LCD显示模块支持3.3V和5V,并兼容多个主控:UNO、Leonardo、ESP32、ESP8266、FireBeetle M0等。与M0配合使用GDI接口,即插即用,有效减少接线步骤。模块板载了MicroSD Card卡槽,用户可以显示更多的图片。
引脚说明:
标号 名称 功能描述
1VCC电源正极
2GND电源负极
3SCLK时钟
4MOSI数据(主机发送从机接收)
5MISO数据(主机接收从机发送
6CS屏幕片选
7RES复位
8DC数据/命令
9BL背光。背光设定了默认值,用户不用连接背光引脚也可点亮;此外,连接背光引脚,输入高电平(1)是将背光亮度调到最大,输入低电平(0)是关闭背光
10SDCSSD卡片选
LCD屏与开发板的引脚连接:
序号 | LCD引脚 | MCU引脚 | 备注 | 1 | VCC
| 3.3v | 连接器第40脚(SYS) | 2 | GND | GND | 连接器第5脚(GND) | 3 | SCLK | PB13 | 连接器第1脚(SPI2 SCLK) | 4 | MOSI | PB15 | 连接器第8脚(SPI2 MOSI) | 5 | MISO | PC2 | 连接器第9脚(SPI2 MISO) | 6 | CS | PG12 | 连接器第17脚(GPIO) | 7 | RES | PG9 | 连接器第19脚(GPIO) | 8 | DC | PG10 | 连接器第18脚(GPIO) | 9 | BL | - | 悬空 | 10 | SDCS | - | 悬空 |
因为开发板是FPC接口,但是LCD显示屏是2.54插针的接口,无法直接通过杜邦线连接,所以用了一个FPC转2.54的一个转接板,整体接线如下:
三、程序
因为该LCD是SPI接口的,所以我们需要对开发板的spi进行配置,SPI选的是SPI2,详细的配置如下:
LCD驱动程序如下:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : lcd.c
* Description : Code for lcd application
******************************************************************************
* @attention
*
* Copyright (c) 2023 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include <string.h>
#include "lcd.h"
#include "spi.h"
#include "FONT.H"
/* Private includes ----------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
HAL_StatusTypeDef spi_status = HAL_OK;
/* Private function prototypes -----------------------------------------------*/
/* Private application code --------------------------------------------------*/
/******************************************************************************
函数说明:LCD串行数据写入函数
入口数据:dat 要写入的串行数据
返回值: 无
******************************************************************************/
void LCD_Writ_Bus(uint8_t data)
{
// uint8_t i;
LCD_CS_L;
spi_status = HAL_SPI_Transmit(&hspi2,&data,1,0xff);
//spi_status = HAL_SPI_Transmit_DMA(&hspi1,&data,1);
LCD_CS_H;
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA8(uint8_t dat)
{
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入数据
入口数据:dat 写入的数据
返回值: 无
******************************************************************************/
void LCD_WR_DATA16(uint16_t dat)
{
LCD_Writ_Bus(dat>>8);
LCD_Writ_Bus(dat);
}
/******************************************************************************
函数说明:LCD写入命令
入口数据:dat 写入的命令
返回值: 无
******************************************************************************/
void LCD_WR_CMD(uint8_t dat)
{
LCD_DC_L;//写命令
LCD_Writ_Bus(dat);
LCD_DC_H;//写数据
}
/******************************************************************************
函数说明:设置起始和结束地址
入口数据: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_CMD(0x2a);//列地址设置
LCD_WR_DATA16(x1);
LCD_WR_DATA16(x2);
LCD_WR_CMD(0x2b);//行地址设置
LCD_WR_DATA16(y1);
LCD_WR_DATA16(y2);
LCD_WR_CMD(0x2c);//储存器写
}
else if(USE_HORIZONTAL==1)
{
LCD_WR_CMD(0x2a);//列地址设置
LCD_WR_DATA16(x1);
LCD_WR_DATA16(x2);
LCD_WR_CMD(0x2b);//行地址设置
LCD_WR_DATA16(y1+80);
LCD_WR_DATA16(y2+80);
LCD_WR_CMD(0x2c);//储存器写
}
else if(USE_HORIZONTAL==2)
{
LCD_WR_CMD(0x2a);//列地址设置
LCD_WR_DATA16(x1);
LCD_WR_DATA16(x2);
LCD_WR_CMD(0x2b);//行地址设置
LCD_WR_DATA16(y1);
LCD_WR_DATA16(y2);
LCD_WR_CMD(0x2c);//储存器写
}
else
{
LCD_WR_CMD(0x2a);//列地址设置
LCD_WR_DATA16(x1+80);
LCD_WR_DATA16(x2+80);
LCD_WR_CMD(0x2b);//行地址设置
LCD_WR_DATA16(y1);
LCD_WR_DATA16(y2);
LCD_WR_CMD(0x2c);//储存器写
}
}
/******************************************************************************
函数说明:液晶初始化
入口数据:无
返回值: 无
******************************************************************************/
void LCD_Init(void)
{
// LCD_GPIO_Init();//初始化GPIO
LCD_RES_L;//复位
osDelay(100);
LCD_RES_H;
osDelay(100);
LCD_WR_CMD(0x11); //无此指令,不能正常初始化芯片,无显示
osDelay(120);
LCD_WR_CMD(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_CMD(0x3A); //数据格式,65K色,565
LCD_WR_DATA8(0x05);
LCD_WR_CMD(0xB2); //帧频设置
LCD_WR_DATA8(0x0C);
LCD_WR_DATA8(0x0C);
LCD_WR_DATA8(0x00);
LCD_WR_DATA8(0x33);
LCD_WR_DATA8(0x33);
LCD_WR_CMD(0xC6); //正常模式下的帧速率控制
// LCD_WR_DATA8(0x01); //正常模式下:屏幕刷新率 111Hz
LCD_WR_DATA8(0x1F); //正常模式下:屏幕刷新率 39Hz
LCD_WR_CMD(0xB7); //GATE 设置
LCD_WR_DATA8(0x35);
LCD_WR_CMD(0xBB); //VCOM设置
LCD_WR_DATA8(0x19);
LCD_WR_CMD(0xC0); //LCM设置,默认0x2c
LCD_WR_DATA8(0x2C);
LCD_WR_CMD(0xC2); //VDV&VRH SET ,默认0x01
LCD_WR_DATA8(0x01);
LCD_WR_CMD(0xC3); //VRHS SET,默认0x0b
LCD_WR_DATA8(0x12); //此处根据实际情况修正
LCD_WR_CMD(0xC4); //VDV SET,默认0x20
LCD_WR_DATA8(0x20);
LCD_WR_CMD(0xC6); // FR SET, 默认0x0F
LCD_WR_DATA8(0x0F);
LCD_WR_CMD(0xD0); //电源控制1
LCD_WR_DATA8(0xA4); //该参数不变
LCD_WR_DATA8(0xA1); //此处根据实际情况修改
LCD_WR_CMD(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_CMD(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_CMD(0x21); //反显开,默认是0X20,正常模式
LCD_WR_CMD(0x29); //显示开,等待MCU数传送
}
/******************************************************************************
函数说明:LCD清屏函数
入口数据:无
返回值: 无
******************************************************************************/
void LCD_Clear(uint16_t Color)
{
uint16_t i,j;
LCD_Address_Set(0,0,LCD_WIDTH-1,LCD_HEIGHT-1);
for(i=0;i<LCD_WIDTH;i++)
{
for (j=0;j<LCD_HEIGHT;j++)
{
LCD_WR_DATA16(Color);
}
}
}
/******************************************************************************
函数说明:在指定区域填充颜色
入口数据: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_DATA16(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_DATA16(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显示坐标
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=asc2_1206[num][i]; //调用6x12字体
else if(sizey==16)temp=asc2_1608[num][i]; //调用8x16字体
// else if(sizey==24)temp=asc2_2412[num][i]; //调用12x24字体
// else if(sizey==32)temp=asc2_1206[num][i]; //调用16x32字体
else return;
for(t=0;t<8;t++)
{
if(!mode)//非叠加模式
{
if(temp&(0x01<<t))LCD_WR_DATA16(fc);
else LCD_WR_DATA16(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 char *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++;
}
}
然后在主函数中调用显示函数去更新屏幕显示:
#include "lcd.h"
#include "stts751.h"
#include "lps22hh.h"
#include "hts221.h"
#include <stdio.h>
#define DISPLAY_X_POS (0U)
#define DISPLAY_Y_POS (80U)
#define DISPLAY_X_STEP (0U)
#define DISPLAY_Y_STEP (20U)
#define DISPLAY_Y_BAIS (20U)
void display_data( void )
{
uint8_t str_buffer[100];
// 获取stts751的数据
float temp = stts751_get_temperature();
sprintf((char *)str_buffer, "STTS751 Temp:%3.2f C", temp);
LCD_ShowString(DISPLAY_X_POS, DISPLAY_Y_POS, (char *)str_buffer, BLUE, YELLOW, 16, 0);
// 获取lps22hh的数据
temp = lps22hh_get_temperature();
sprintf((char *)str_buffer, "LPS22HH Temp:%3.2f C", temp);
LCD_ShowString(DISPLAY_X_POS + DISPLAY_X_STEP, DISPLAY_Y_POS + DISPLAY_Y_STEP + DISPLAY_Y_BAIS, (char *)str_buffer, BLUE, YELLOW, 16, 0);
temp = lps22hh_get_pressure();
sprintf((char *)str_buffer, "LPS22HH Press:%3.2f hPa", temp);
LCD_ShowString(DISPLAY_X_POS + DISPLAY_X_STEP * 2 , DISPLAY_Y_POS + DISPLAY_Y_STEP * 2 + DISPLAY_Y_BAIS, (char *)str_buffer, BLUE, YELLOW, 16, 0);
// 获取hts221的数据
temp = hts221_get_humidity();
sprintf((char *)str_buffer, "HTS221 Humi:%3.2f %%", temp);
LCD_ShowString(DISPLAY_X_POS + DISPLAY_X_STEP *3 , DISPLAY_Y_POS + DISPLAY_Y_STEP * 3 + DISPLAY_Y_BAIS * 2, (char *)str_buffer, BLUE, YELLOW, 16, 0);
temp = hts221_get_temperature();
sprintf((char *)str_buffer, "HTS221 Temp:%3.2f C", temp);
LCD_ShowString(DISPLAY_X_POS + DISPLAY_X_STEP * 4 , DISPLAY_Y_POS + DISPLAY_Y_STEP * 4 + DISPLAY_Y_BAIS * 2, (char *)str_buffer, BLUE, YELLOW, 16, 0);
}
四、显示效果
|
此文章已获得独家原创/原创奖标签,著作权归21ic所有,未经允许禁止转载。
共2人点赞
|