物联网之LoRa开发与应用三(Lora人机界面开发)

2024-02-20 23:20

本文主要是介绍物联网之LoRa开发与应用三(Lora人机界面开发),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章要点:

1、TFT液晶屏工作原理

2、TFT液晶屏驱动开发

3、TFT人机界面开发

TFT液晶屏工作原理

内容概要

1、TFT液晶屏显示原理

2、1.44寸TFT液晶屏工作原理

3、1.44寸TFT液晶屏硬件设计

TFT液晶屏如何显示

颜色深度

Color 介绍 :

    ① R,G,B三基色组合形成各种颜色。

    ②能显示的颜色数由RGB的数字信号的位数来决定。(8bit 数字信号刚好能显示16.7M种颜色)

以3bit为例数字信号为例:

 For 3 bit : 23(R) * 23(G) * 23(B) = 256 colors

For 6 bit : 26(R) * 26(G) * 26(B) = 262144 colors(242K)

For8  bit: 28(R) * 28(G) * 28(B) =16777216 colors(16.7M)

For10  bit: 210(R) * 210(G) * 210(B) =1073741824 colors(1 billion)

1.44寸TFT模块

TFT驱动控制器

1.44寸模块电路详解

TFT液晶屏驱动开发(驱动芯片资料下载链接:https://pan.baidu.com/s/1-tOqlGj_qsniN4xrjIp_aA 密码:1och)

内容概要

1、TFT液晶屏硬件接口驱动开发

2、TFT液晶屏取模方式

3、TFT液晶屏显示字符串

硬件接口初始化

根据硬件设计,LoRa与LCD共用SPI总线,且LCD_MISO用于命令/数据模式切换控制。

需要修改gpio初始化源码,让片选接口拉高。

写指令

写数据

初始化

设置显示区域

设置行列起始地址,在此区域内写点数据自动换行

画点和清屏

RGB565颜色对照表:(详细对照表可以百度搜索)

驱动源码移植:(源码下载链接:https://pan.baidu.com/s/1MLheOr6d3KDLRROalrPugg 密码:zdjg)

将源码中的三个文件按照如下位置放入相应的工程文件目录下:

打开工程文件,将lcd.c添加到工程中:

清除警告:

LoRa模块和LCD显示屏都是接到同一个SPI引脚,初始化时片选(NSS)引脚要修改为不使能(高电平):

上电后液晶屏显示黄色屏幕

在main.c函数中添加如下代码:

1、添加头文件

#include "lcd.h"

2、添加初始化函数和清屏函数

 Lcd_Init();//LCD初始化函数Lcd_Clear(YELLOW);//全屏清屏函数,参数是清屏时填充的颜色(16位表示)

取模方式

取模工具:(工具加载链接:https://pan.baidu.com/s/1jwRDjs69i0K9j6ctEFQvtg 密码:yedy)

文字取模软件(该工具在本项目中使用不到,可自行了解)

工程中新建一个.h文件,将生成的子模数据复制到该文件中,将数据修改成如下数组,并在lcd.c中添加显示文字的代码:

图片取模软件

将生成的.h文件复制到工程的相关目录中,并在lcd.c中添加显示图片的代码:

/*************************************************
函数名:showimage
功能:显示一副图片
入口参数:图片缓存
返回值:无
*************************************************/
//因为一副128*128的图片需要32768个8位数组成(数组元素有32768个),很显然数组太大,不能放到内存中,只能放在静态存储区,所以参数使用 const 修饰 
void showimage(const unsigned char *p)             
{	unsigned int i;uint16_t HData,LData;Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);Lcd_WriteIndex(0x2C);for(i = 0;i < 128*128;i++)//因为我们已经设置显示屏显示范围为128*128,所以写满一行会自动换行,不需单独写代码{LData = *(p+i*2);HData = *(p+i*2+1);LCD_WriteData_16Bit(HData<<8|LData);}       
}

将该函数申明添加到lcd.h中:

 

 main.c函数中调用该函数,将图片显示到LCD

showimage_all(0,0,32768, gImage_world);//或者:showimage(gImage_world);

LCD显示字符串

//lcd.c/*************************************************
函数名:Gui_DrawFont_GBK16
功能:显示一个字符串
入口参数:列地址、行地址、字体颜色、背景颜色、要写入的字符串
返回值:无
*************************************************/
void Gui_DrawFont_GBK16(uint16_t x0, uint16_t y0, uint16_t fc, uint16_t bc, uint8_t *s)
{ int i,j,k,x,y,xx;unsigned char qm;long int ulOffset;char  ywbuf[32];// char   temp[2];for(i = 0; i<strlen((char*)s);i++){if(((unsigned char)(*(s+i))) >= 161){
//      temp[0] = *(s+i);
//      temp[1] = '\0';return;}else{qm = *(s+i);ulOffset = (long int)(qm) * 16;for (j = 0; j < 16; j ++){ywbuf[j]=Zk_ASCII8X16[ulOffset+j];}for(y = 0;y < 16;y++){for(x=0;x<8;x++) {k=x % 8;if(ywbuf[y]&(0x80 >> k)){xx=x0+x+i*8;     Gui_DrawPoint(xx,y+y0,fc);}else{xx=x0+x+i*8;     Gui_DrawPoint(xx,y+y0,bc);}  }}}}  
}

TFT液晶屏人机界面开发

开机界面设计

略:讲图片取模软件时已经做过。。。

菜单界面设计

lcd中添加如下函数:(注:必须将函数声明添加到lcd.h中

void show_ssid(uint8_t *s)//将SSID数据显示到屏幕上
{Gui_DrawFont_GBK16(60, 50, BLACK, YELLOW,"      ");Gui_DrawFont_GBK16(60, 50, BLACK, YELLOW, s);
}void show_rx(uint8_t *s)//将RX数据显示到屏幕上
{Gui_DrawFont_GBK16(60, 77, BLACK, YELLOW,"      ");Gui_DrawFont_GBK16(60, 77, BLACK, YELLOW, s);
}void show_tx(uint8_t *s)//将TX数据显示到屏幕上
{Gui_DrawFont_GBK16(60, 104, BLACK, YELLOW,"      ");Gui_DrawFont_GBK16(60, 104, BLACK, YELLOW, s);
}

main.c中添加如下代码:

  Lcd_Clear_xy(0,0,GREEN);Lcd_Clear_xy(0,45,YELLOW);Gui_DrawFont_GBK16(12, 10, RED, GREEN, "LoRa Topology");Gui_DrawFont_GBK16(40, 26, RED, GREEN, "Master");Gui_DrawFont_GBK16(12, 50, BLACK, YELLOW, "SSID:");Gui_DrawFont_GBK16(12, 77, BLACK, YELLOW, "RX:");Gui_DrawFont_GBK16(12, 104, BLACK, YELLOW, "TX:");show_ssid("ERROR");show_rx("ERROR");show_tx("ERROR");Lcd_WriteIndex(0x29);//Display on  打开LCD屏幕显示

实验结果:

lcd.c文件完整代码及分析如下:

#include "gpio.h"
#include "stdint.h"
#include "lcd.h"
#include "font_lcd.h"
#include "string.h"
#include "spi.h"void Delay_ms(int time)
{int i,j;for(i=0;i<time*10;i++){for(j=0;j<100;j++){}}
}void LCD_GPIO_Init(void)
{GPIO_InitTypeDef GPIO_InitStruct;/* GPIO Ports Clock Enable */__HAL_RCC_GPIOB_CLK_ENABLE();/*Configure GPIO pin Output Level */
//  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, GPIO_PIN_RESET);/*Configure GPIO pins : PB4 */GPIO_InitStruct.Pin = GPIO_PIN_4;//根据原理图可知该引脚为spi的SIMO引脚GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//将PB4重新设置为推挽输出模式,之前是SPI模式,现重新设置是为了切换数据和命令模式(使用LCD时)GPIO_InitStruct.Pull = GPIO_PULLUP;GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
}//向液晶屏写一个8位指令
void Lcd_WriteIndex(uint8_t Index)
{//SPI 写命令时序开始               //NSS = 0;LCD_CS_CLR;       //将PA15拉低,使能LCD显示屏LCD_RS_CLR;           //LCD_RS_CLR   将PB4拉低,将LCD设置为写命令模式HAL_SPI_Transmit(&hspi1,&Index,1,0xfff);//NSS = 1;LCD_CS_SET;   //将PA15拉高,关闭LCD显示屏的SPI
}
//向液晶屏写一个8位数据
void Lcd_WriteData(uint8_t Data)
{LCD_CS_CLR;   //将PA15拉低,使能LCD显示屏LCD_RS_SET;    //LCD_RS_CLR   将PB4拉高,将LCD设置为写数据模式HAL_SPI_Transmit(&hspi1,&Data,1,0xfff);LCD_CS_SET;   //将PA15拉高,关闭LCD显示屏的SPI
}void LCD_WriteData_16Bit(uint16_t Data)
{uint8_t Data_H = Data>>8;uint8_t Data_L = Data&0xFF;LCD_CS_CLR;LCD_RS_SET;HAL_SPI_Transmit(&hspi1,&Data_H,1,0xfff); 	//写入高8位数据HAL_SPI_Transmit(&hspi1,&Data_L,1,0xfff); 	//写入低8位数据	LCD_CS_SET;
}//LCD Init For 1.44Inch LCD Panel with ST7735R.
void Lcd_Init(void) //LCD初始化函数
{	LCD_GPIO_Init();//spi的SIMO的初始化HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);//根据原理图可知:PB6引脚为LCD背光设置引脚,这里设置为使能背光Lcd_WriteIndex(0x01);//Sleep  写命令:软复位HAL_Delay(120);//写命令之后需要延时120ms才能写下一个命令Lcd_WriteIndex(0x11);//Sleep exit 退出休眠模式HAL_Delay(120);Lcd_WriteIndex(0x36); //打开0x36寄存器,该寄存器可设置:MX(列扫描), MY(行扫描), RGB mode等Lcd_WriteData(0xC8); //写数据,设置0x36寄存器的值Lcd_WriteIndex(0x3A); //65k mode 颜色深度寄存器Lcd_WriteData(0x05); //设置显示颜色的数据位为16位//Lcd_WriteIndex(0x29);//Display on  打开LCD屏幕显示	
}/*************************************************
函数名:LCD_Set_Region
功能:设置lcd显示区域,在此区域写点数据自动换行
入口参数:xy起点和终点
返回值:无
*************************************************/
void Lcd_SetRegion(uint16_t x_start,uint16_t y_start,uint16_t x_end,uint16_t y_end)
{		Lcd_WriteIndex(0x2a);Lcd_WriteData(0x00);Lcd_WriteData(x_start+2);Lcd_WriteData(0x00);Lcd_WriteData(x_end+2);Lcd_WriteIndex(0x2b);Lcd_WriteData(0x00);Lcd_WriteData(y_start+3);Lcd_WriteData(0x00);Lcd_WriteData(y_end+3);Lcd_WriteIndex(0x2c);}
/*************************************************
函数名:Lcd_Clear
功能:全屏清屏函数
入口参数:填充颜色COLOR
返回值:无
*************************************************/
void Lcd_Clear(uint16_t Color)               
{	unsigned int i,m;Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);Lcd_WriteIndex(0x2C);for(i=0;i<X_MAX_PIXEL;i++)for(m=0;m<Y_MAX_PIXEL;m++){	LCD_WriteData_16Bit(Color);}   
}/****************************************************/
void Lcd_Clear_xy(uint16_t x,uint16_t y,uint16_t Color)               
{	unsigned int i,m;Lcd_SetRegion(x,y,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);Lcd_WriteIndex(0x2C);for(i=x;i<X_MAX_PIXEL;i++)for(m=y;m<Y_MAX_PIXEL;m++){	LCD_WriteData_16Bit(Color);}   
}/*************************************************
函数名:showimage
功能:显示一副图片
入口参数:图片缓存
返回值:无
*************************************************/
//因为一副128*128的图片需要32768个8位数组成(数组元素有32768个),很显然数组太大,不能放到内存中,只能放在静态存储区,所以参数使用 const 修饰 
void showimage(const unsigned char *p)             
{	unsigned int i;uint16_t HData,LData;Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);Lcd_WriteIndex(0x2C);for(i = 0;i < 128*128;i++)//因为我们已经设置显示屏显示范围为128*128,所以写满一行会自动换行,不需单独写代码{LData = *(p+i*2);HData = *(p+i*2+1);LCD_WriteData_16Bit(HData<<8|LData);}       
}/*************************************************
函数名:showimage
功能:任何位置显示任何图片(必须在显示屏显示的范围之内)
入口参数:列的起始地址、行的起始地址、数组的大小、图片缓存
返回值:无
*************************************************/
void showimage_all(uint16_t x,uint16_t y,uint16_t size, const unsigned char *p)             
{	unsigned int i;uint16_t HData,LData;Lcd_SetRegion(x,y,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);Lcd_WriteIndex(0x2C);for(i = 0;i < size/2;i++)//因为我们已经设置显示屏显示范围为128*128,所以写满一行会自动换行,不需单独写代码{LData = *(p+i*2);HData = *(p+i*2+1);LCD_WriteData_16Bit(HData<<8|LData);}       
}/*************************************************
函数名:LCD_DrawPoint
功能:画一个点
入口参数:无
返回值:无
*************************************************/
void Gui_DrawPoint(uint16_t x,uint16_t y,uint16_t Data)
{Lcd_SetRegion(x,y,x+1,y+1);LCD_WriteData_16Bit(Data);}    /*************************************************
函数名:Gui_DrawFont_GBK16
功能:显示一个字符串
入口参数:列地址、行地址、字体颜色、背景颜色、要写入的字符串
返回值:无
*************************************************/
void Gui_DrawFont_GBK16(uint16_t x0, uint16_t y0, uint16_t fc, uint16_t bc, uint8_t *s)
{ int i,j,k,x,y,xx;unsigned char qm;long int ulOffset;char  ywbuf[32];// char   temp[2];for(i = 0; i<strlen((char*)s);i++){if(((unsigned char)(*(s+i))) >= 161){
//      temp[0] = *(s+i);
//      temp[1] = '\0';return;}else{qm = *(s+i);ulOffset = (long int)(qm) * 16;for (j = 0; j < 16; j ++){ywbuf[j]=Zk_ASCII8X16[ulOffset+j];}for(y = 0;y < 16;y++){for(x=0;x<8;x++) {k=x % 8;if(ywbuf[y]&(0x80 >> k)){xx=x0+x+i*8;     Gui_DrawPoint(xx,y+y0,fc);}else{xx=x0+x+i*8;     Gui_DrawPoint(xx,y+y0,bc);}  }}}}  
}void show_ssid(uint8_t *s)//将SSID数据显示到屏幕上
{Gui_DrawFont_GBK16(60, 50, BLACK, YELLOW,"      ");Gui_DrawFont_GBK16(60, 50, BLACK, YELLOW, s);
}void show_rx(uint8_t *s)//将RX数据显示到屏幕上
{Gui_DrawFont_GBK16(60, 77, BLACK, YELLOW,"      ");Gui_DrawFont_GBK16(60, 77, BLACK, YELLOW, s);
}void show_tx(uint8_t *s)//将TX数据显示到屏幕上
{Gui_DrawFont_GBK16(60, 104, BLACK, YELLOW,"      ");Gui_DrawFont_GBK16(60, 104, BLACK, YELLOW, s);
}

 

这篇关于物联网之LoRa开发与应用三(Lora人机界面开发)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/729854

相关文章

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

Java中的Lambda表达式及其应用小结

《Java中的Lambda表达式及其应用小结》Java中的Lambda表达式是一项极具创新性的特性,它使得Java代码更加简洁和高效,尤其是在集合操作和并行处理方面,:本文主要介绍Java中的La... 目录前言1. 什么是Lambda表达式?2. Lambda表达式的基本语法例子1:最简单的Lambda表

Python结合PyWebView库打造跨平台桌面应用

《Python结合PyWebView库打造跨平台桌面应用》随着Web技术的发展,将HTML/CSS/JavaScript与Python结合构建桌面应用成为可能,本文将系统讲解如何使用PyWebView... 目录一、技术原理与优势分析1.1 架构原理1.2 核心优势二、开发环境搭建2.1 安装依赖2.2 验

Java字符串操作技巧之语法、示例与应用场景分析

《Java字符串操作技巧之语法、示例与应用场景分析》在Java算法题和日常开发中,字符串处理是必备的核心技能,本文全面梳理Java中字符串的常用操作语法,结合代码示例、应用场景和避坑指南,可快速掌握字... 目录引言1. 基础操作1.1 创建字符串1.2 获取长度1.3 访问字符2. 字符串处理2.1 子字

使用Python开发一个带EPUB转换功能的Markdown编辑器

《使用Python开发一个带EPUB转换功能的Markdown编辑器》Markdown因其简单易用和强大的格式支持,成为了写作者、开发者及内容创作者的首选格式,本文将通过Python开发一个Markd... 目录应用概览代码结构与核心组件1. 初始化与布局 (__init__)2. 工具栏 (setup_t

SpringShell命令行之交互式Shell应用开发方式

《SpringShell命令行之交互式Shell应用开发方式》本文将深入探讨SpringShell的核心特性、实现方式及应用场景,帮助开发者掌握这一强大工具,具有很好的参考价值,希望对大家有所帮助,如... 目录引言一、Spring Shell概述二、创建命令类三、命令参数处理四、命令分组与帮助系统五、自定

SpringBoot应用中出现的Full GC问题的场景与解决

《SpringBoot应用中出现的FullGC问题的场景与解决》这篇文章主要为大家详细介绍了SpringBoot应用中出现的FullGC问题的场景与解决方法,文中的示例代码讲解详细,感兴趣的小伙伴可... 目录Full GC的原理与触发条件原理触发条件对Spring Boot应用的影响示例代码优化建议结论F

MySQL 分区与分库分表策略应用小结

《MySQL分区与分库分表策略应用小结》在大数据量、复杂查询和高并发的应用场景下,单一数据库往往难以满足性能和扩展性的要求,本文将详细介绍这两种策略的基本概念、实现方法及优缺点,并通过实际案例展示如... 目录mysql 分区与分库分表策略1. 数据库水平拆分的背景2. MySQL 分区策略2.1 分区概念