FMC驱动LCD

news2024/11/24 3:55:34

硬件简介

主控:STM32H750

LCD屏幕为16位并口屏幕

CubeMX配置

FMC配置

chip select: 选择起始地址块号,ADDR[27:26]

Memory type: 内存类型,选择LCD Interface

LCD Register Select: 根据选择计算映射地址, FSNC_A[25]

Data: 数据宽度

NOR/PSRAM timing: 调整时间,能够提升屏幕刷新的速率

代码

2.1 获取LCD屏幕驱动源码

获取到一份能够正常使用的屏幕驱动源码

2.2 计算地址

#define Bank1_LCD_DATA ((uint32_t)0x60080000) /* display data address */
#define Bank1_LCD_REG ((uint32_t)0X60000000)  /* display register addres
2.3.1 根据chip select计算 register addres

NE1 -NE4分别对应ADDR[27:26]对应00 - 11

对应的为映射起始地址

image-20231104135511377

2.3.2 根据Memory type和LCD Register Select计算data address

image-20231104140534952

对于8位数据宽度的地址为:

Bank1_LCD_DATA = Bank1_LCD_REG + 1 << 18(LCD Register Select + 0)

对于16位数据宽度的地址为:

Bank1_LCD_DATA = Bank1_LCD_REG + 1 << (18 + 1)(LCD Register Select + 1)

所以

#define Bank1_LCD_DATA ((uint32_t)0x60080000) /* display data address */

驱动代码

lcd.h

#ifndef __LCD_H
#define __LCD_H

/* BEGIN Includes */
#include "main.h"
/* END Includes */

void LCD_Fill(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint16_t color);
void LCD_Fill_1(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint8_t color);
void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color);
void LCD_DrawRectangle(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint16_t color);
//void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint8_t pic[]);
void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint16_t pic[]);

#endif /* __LCD_H */

lcd.c

/* BEGIN Includes */

#include "lcd.h"
#include "Lcd_init.h"
#include <string.h>
#include "dma.h"
/* END Includes */

/******************************************************************************
    函数说明:在指定区域填充颜色
    入口数据:   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_DATA(color);
        }
    }
}

static uint8_t buf[240*10*2] __attribute__((section(".ARM.__at_0x38000400")));
void LCD_Fill_1(uint16_t xsta,uint16_t ysta,uint16_t xend,uint16_t yend,uint8_t color)
{
   
	memset(buf, color, sizeof(buf));
    LCD_Address_Set(xsta,ysta,xend-1,yend-1);
	HAL_DMA_Start_IT(&hdma_memtomem_dma1_stream0, (uint32_t)0x38000400, Bank1_LCD_DATA, ((yend + 1) - ysta) * ((xend + 1) - xsta) * 2);

}
/******************************************************************************
      函数说明:在指定位置画点
      入口数据:x,y 画点坐标
                color 点的颜色
      返回值:  无
******************************************************************************/
void LCD_DrawPoint(uint16_t x,uint16_t y,uint16_t color)
{
    LCD_Address_Set(x,y,x,y);//
    LCD_WR_DATA(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起点坐标
                length 图片长度
                width  图片宽度
                pic[]  图片数组    
      返回值:  无
******************************************************************************/

void LCD_ShowPicture(uint16_t x,uint16_t y,uint16_t length,uint16_t width,const uint16_t pic[])
{
	uint16_t i,j;  
	uint32_t k=0;
	LCD_Address_Set(x,y,x+length-1,y+width-1);
	for(i=0;i<length;i++)
	{
		for(j=0;j<width;j++)
		{
			LCD_WR_DATA(pic[k]);
			k++;
		}
	}

}

Lcd_init.h

#ifndef __LCD_INIT_H
#define __LCD_INIT_H

/* BEGIN Includes */
#include "main.h"
/* END Includes */

#define USE_HORIZONTAL 1  //设置横屏或者竖屏显示 0或1为竖屏 2或3为横屏

#if USE_HORIZONTAL==0||USE_HORIZONTAL==1

#define LCD_W 320
#define LCD_H 240

#else
#define LCD_W 320
#define LCD_H 240
#endif

//#define Bank1_LCD_DATA ((uint32_t)0x60108CA0) /* display data address */
#define Bank1_LCD_DATA ((uint32_t)0x6010fff0) /* display data address */
#define Bank1_LCD_REG ((uint32_t)0X60000000)  /* display register address */

#define LCD_FMC_DATA(value) ((*(__IO uint8_t  *)(Bank1_LCD_DATA)) = ((uint8_t )(value))) // 写数据寄存器
#define LCD_FMC_REG(index) ((*(__IO uint8_t  *)(Bank1_LCD_REG)) = ((uint8_t )index))

#define LCD_SCLK_Clr 	//HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,0)//SCL=SCLK
#define LCD_SCLK_Set 	//HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,1)

#define LCD_MOSI_Clr	//HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,0)//SDA=MOSI
#define LCD_MOSI_Set	//HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,1)

#define LCD_RES_Clr		HAL_GPIO_WritePin(GPIOE,GPIO_PIN_1,0)//RES
#define LCD_RES_Set		HAL_GPIO_WritePin(GPIOE,GPIO_PIN_1,1)

#define LCD_DC_Clr		HAL_GPIO_WritePin(GPIOE,GPIO_PIN_4,0)//DC
#define LCD_DC_Set		HAL_GPIO_WritePin(GPIOE,GPIO_PIN_4,1)

#define LCD_CS_Clr		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,0)//CS
#define LCD_CS_Set		HAL_GPIO_WritePin(GPIOC,GPIO_PIN_7,1)

#define LCD_BLK_Clr() //HAL_GPIO_WritePin(GPIOE,GPIO_PIN_9,0)//BLK
#define LCD_BLK_Set() //HAL_GPIO_WritePin(GPIOE,GPIO_PIN_7,1)

void LCD_Writ_Bus(uint8_t dat);//
void LCD_WR_DATA8(uint8_t dat);//
void LCD_WR_DATA(uint16_t dat);//
void LCD_WR_REG(uint8_t dat);//
void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2);//
void LCD_Init(void);//

#endif /* __LCD_INIT_H */

Lcd_init_.c

/* BEGIN Includes */

#include "Lcd_init.h"
#include "lcd.h"

/* END Includes */

void LCD_Writ_Bus(uint8_t dat) 
{

	LCD_FMC_DATA(dat);
}
void LCD_WR_DATA8(uint8_t dat)
{
	LCD_FMC_DATA(dat);
}

void LCD_WR_DATA(uint16_t dat)
{
	LCD_FMC_DATA(dat >> 8);
	LCD_FMC_DATA(dat);
}

void LCD_WR_REG(uint8_t dat)
{
	LCD_FMC_REG(dat);
}
void LCD_Address_Set(uint16_t x1,uint16_t y1,uint16_t x2,uint16_t y2)
{
		LCD_WR_REG(0x2a);//
		LCD_Writ_Bus(x1>>8);
		LCD_Writ_Bus(x1);
		LCD_Writ_Bus(x2>>8);
		LCD_Writ_Bus(x2);
		LCD_WR_REG(0x2b);//
	
		LCD_Writ_Bus(y1>>8);
		LCD_Writ_Bus(y1);
		LCD_Writ_Bus(y2>>8);
		LCD_Writ_Bus(y2);
		LCD_WR_REG(0x2c);//
}
void LCD_Init(void)
{

	
	LCD_RES_Clr;//
	HAL_Delay(100);
	LCD_RES_Set;
	HAL_Delay(100);
	
	LCD_BLK_Set();//
	HAL_Delay(100);
	
	//************* Start Initial Sequence **********//
       LCD_WR_REG(0x11);
		HAL_Delay(1000); //Delay 120ms
	  LCD_WR_REG(0X36);// Memory Access Control

		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_REG(0X3A);
		LCD_WR_DATA8(0X05);
	//--------------------------------ST7789S Frame rate setting-------------------------

	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);
	//---------------------------------ST7789S Power setting-----------------------------

	LCD_WR_REG(0xbb);
	LCD_WR_DATA8(0x35);
	LCD_WR_REG(0xc0);
	LCD_WR_DATA8(0x2c);
	LCD_WR_REG(0xc2);
	LCD_WR_DATA8(0x01);
	LCD_WR_REG(0xc3);
	LCD_WR_DATA8(0x13);
	LCD_WR_REG(0xc4);
	LCD_WR_DATA8(0x20);
	LCD_WR_REG(0xc6);
	LCD_WR_DATA8(0x0f);
	LCD_WR_REG(0xca);
	LCD_WR_DATA8(0x0f);
	LCD_WR_REG(0xc8);
	LCD_WR_DATA8(0x08);
	LCD_WR_REG(0x55);
	LCD_WR_DATA8(0x90);
	LCD_WR_REG(0xd0);
	LCD_WR_DATA8(0xa4);
	LCD_WR_DATA8(0xa1);
	//--------------------------------ST7789S gamma setting------------------------------
	LCD_WR_REG(0xe0);
	LCD_WR_DATA8(0xd0);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x06);
	LCD_WR_DATA8(0x09);
	LCD_WR_DATA8(0x0b);
	LCD_WR_DATA8(0x2a);
	LCD_WR_DATA8(0x3c);
	LCD_WR_DATA8(0x55);
	LCD_WR_DATA8(0x4b);
	LCD_WR_DATA8(0x08);
	LCD_WR_DATA8(0x16);
	LCD_WR_DATA8(0x14);
	LCD_WR_DATA8(0x19);
	LCD_WR_DATA8(0x20);
	LCD_WR_REG(0xe1);
	LCD_WR_DATA8(0xd0);
	LCD_WR_DATA8(0x00);
	LCD_WR_DATA8(0x06);
	LCD_WR_DATA8(0x09);
	LCD_WR_DATA8(0x0b);
	LCD_WR_DATA8(0x29);
	LCD_WR_DATA8(0x36);
	LCD_WR_DATA8(0x54);
	LCD_WR_DATA8(0x4b);
	LCD_WR_DATA8(0x0d);
	LCD_WR_DATA8(0x16);
	LCD_WR_DATA8(0x14);
	LCD_WR_DATA8(0x21);
	LCD_WR_DATA8(0x20);
	LCD_WR_REG(0x29);
		
		
	//	LCD_WR_REG(0x21);			//´򿪑Չ«·´ת	
} 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1171458.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RISC-V与RISC Zero zkVM的关系

1. 引言 本文基本结构为&#xff1a; 编程语言背景介绍RISC-V虚拟机作为zkVM电路为何选择RISC-V&#xff1f; 2. 编程语言背景介绍 高级编程语言不专门针对某个架构&#xff0c;其便于人类编写。高级编程语言代码&#xff0c;经编译器编译后&#xff0c;会生成针对专门某架…

Azure 机器学习 - 设置 AutoML 训练时序预测模型

目录 一、环境准备二、训练和验证数据三、配置试验支持的模型配置设置特征化步骤自定义特征化 四、可选配置频率和目标数据聚合启用深度学习目标滚动窗口聚合短时序处理非稳定时序检测和处理 五、运行试验六、用最佳模型进行预测用滚动预测评估模型精度预测未来 七、大规模预测…

网络基础扫盲--TCP/UDP

博客内容&#xff1a;TCP/UDP 文章目录 一、TCP与UDP二、tcp可靠性如何保证&#xff1f;1、三次握手2、TCP报头3、TCP四次挥手 一、TCP与UDP tcp与udp都是传输层的协议&#xff0c;用于数据的传输。 对于tcp而言数据的传输会比较可靠&#xff0c;主要依赖于tcp面向链接的&…

openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期

文章目录 openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期114.1 注意事项114.2 操作步骤 openGauss学习笔记-114 openGauss 数据库管理-设置安全策略-设置帐号有效期 114.1 注意事项 创建新用户时&#xff0c;需要限制用户的操作期限&#xff08;有…

Prompt 设计与大语言模型微调,没有比这篇更详细的了吧!

本文主要介绍了Prompt设计、大语言模型SFT和LLM在手机天猫AI导购助理项目应用。 ChatGPT基本原理 “会说话的AI”&#xff0c;“智能体” 简单概括成以下几个步骤&#xff1a; 预处理文本&#xff1a;ChatGPT的输入文本需要进行预处理。 输入编码&#xff1a;ChatGPT将经过预…

如何使用Python和matplotlib绘制机器人运动偏差路径图——实用教程与代码解析

前言 科研论文中需要绘制一个精美的机器人运动路径图&#xff08;其中包含了机器人的期望运动路径和实际运动路径&#xff09;。我的期望路径是是一个方形&#xff0c;用Python代码是这样表示的&#xff1a; n_list [n1,n2,n3,n4] e_list [e1,e2,e3,e4] #n_list和e_list的各…

C++笔记之动态数组的申请和手动实现一个简单的vector

C笔记之动态数组的申请和手动实现一个简单的vector code review! 文章目录 C笔记之动态数组的申请和手动实现一个简单的vector1.C语言中动态数组的申请与使用1.动态数组的申请使用new和delete使用std::vector 1.std::vector的底层实现2.手动实现一个简单的vector:使用一个指向…

项目实战:展示第一页数据

1、在FruitDao接口中添加查询第一页数据和查询总记录条数 package com.csdn.fruit.dao; import com.csdn.fruit.pojo.Fruit; import java.util.List; //dao &#xff1a;Data Access Object 数据访问对象 //接口设计 public interface FruitDao {void addFruit(Fruit fruit);vo…

文件复制加密、文件落地加密、文件移动加密如何设置?

文件加密在保护信息安全方面具有重要作用。合格、好用的文件加密软件可以帮助企业保护商业机密、更遵守法律法规、提高企业核心竞争力、防止数据泄密等。 一般的加密都是对文件本身加密&#xff0c;比如加密某个WORD /PPT之类的&#xff0c;很少有能够加密某个文件夹的。今天就…

单链表基本操作的实现,初始化,头插,尾插,判空,获取个数,查找,删除,获取前置和后置位,清空,销毁

目录 一.单链表的设计 二.单链表的实现 三.单链表的总结 一.单链表的设计 1.单链表的结构定义: typedef struct Node{int data;//数据域struct Node* next;//后继指针}Node,*List; 2.单链表的设计示意图: 3.注意,单链表的最后一个节点的next域为NULL; 4.为什么要有一个头…

唯一ID如何生成,介绍一下目前技术领域最常使用的几种方法

纵使十面大山&#xff0c;又如何&#xff0c;无妨… 概述 唯一ID&#xff08;Unique Identifier&#xff09;是在计算机科学和信息技术领域中用于标识某个实体或数据的唯一标识符。生成唯一ID的方法可以根据具体需求和应用场景的不同而有所不同。以下是一些目前技术领域中常用…

2023-mac rz sz 安装

之前安装过一次&#xff0c;没问题&#xff0c;这次按照之前教程装了就不管上传下载都会卡住&#xff1b; step1: brew install lrzsz step2&#xff1a;在/usr/local/bin 路径下配置两个sh,之前从网上找到的直接用都不对&#xff0c;下面这个是调试过的正式可用的 iterm2…

【C语言进阶】之动态内存管理

【C语言进阶】之动态内存管理 1.为什么我们需要动态内存管理2.动态内存管理的函数介绍2.1malloc函数和free函数2.1.1malloc函数2.1.2 free函数 2.2calloc函数2.3realloc函数 3.动态内存管理中经常出现的一些问题总结。3.1 越界访问3.2 对空指针进行解引用操作3.3 对同一片空间进…

安全防御——二、ENSP防火墙实验学习

安全防御 一、防火墙接口以及模式配置1、untrust区域2、trust区域3、DMZ区域4、接口对演示 二、防火墙的策略1、定义与原理2、防火墙策略配置2.1 安全策略工作流程2.2 查询和创建会话 3、实验策略配置3.1 trust-to-untrust3.2 trust-to-dmz3.3 untrust-to-dmz 三、防火墙的区域…

归并排序--C语言实现

1. 简述 归并排序的原理是将&#xff0c;两个较大的数组分为大小几乎一致的两个数组。 再将两个数组进行合并成新的有序数组。 合并两个数组的时候需要额外的一个数组的空间。 2. 实现 上图说明过程 代码 #include <stdio.h>void Merge(int *arr, int *tmp, int …

freertos入门(stm32f10c8t6版闪烁灯)

首先到官网下载freertos源码&#xff0c;然后找一个stm32f10c8t6的空模板&#xff0c;这个空模板实现点灯之类的都行。 然后在这个空模板的工程下新建一个FreeRtos文件夹 接着在FreeRtos文件夹下新建三个文件夹&#xff0c;分别是src存放源码 inc 存放头文件&#xff0c;port …

Linux下查看文件夹大小命令

在Vscode上连接服务器&#xff0c;想查看文件夹大小&#xff1b; du -h path

4 个最常见的自动化测试挑战及应对措施

有人说&#xff1a;“杂乱无章的自动化只会带来更快的混乱。”不仅更快&#xff0c;而且是更严重、更大的混乱。如果使用得当&#xff0c;自动化可以成为测试团队中令人惊叹的生产力助推器和系统的质量增强器。自动化测试的关键是要正确运用&#xff0c;这是初始最困难的部分。…

动态路由协议OSPF优化提速特性

1.OSPF协议通信过程与部署&#xff1b; 2.OSPF协议在项目上的应用场景&#xff1b; 3.OSPF有哪些优化特性&#xff1f; - OSPF - 开放式最短路径优先 - 一个动态路由协议 - 路由协议 - 理解魏 运行在路由器的一个软件 - 目的&#xff1a;为了帮助路由器和路由器彼…

短期经济波动:均衡国民收入决定理论(二)

短期经济波动:国民收入决定理论(二) 文章目录 短期经济波动:国民收入决定理论(二)[toc]1 IS曲线1.1 IS曲线的代数推导1.1.1 代数法&#xff1a;计划支出等于实际支出1.1.2 代数法&#xff1a;计划投资等于储蓄1.1.3 代数法&#xff1a;非计划存货等于0 1.2 IS曲线的几何推导1.2…