国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明

這篇具有很好參考價(jià)值的文章主要介紹了21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

本文講解如何配置LTDC驅(qū)動(dòng)LCD的參數(shù)配置,以及CubeMx參數(shù)配置說明
本文使用的是淘寶買的一塊帶電容觸摸的液晶顯示屏:5寸TFT液晶顯示屏高清800*480免驅(qū)40P通用RGBIPS全視角彩屏GT911
說實(shí)話,價(jià)格還是相對(duì)挺便宜的,值得入手,哈哈哈
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
這款屏幕采用的是RGB888格式
這里面也就是常用的引腳:
R0-R7、G0-G7、B0-B7
DCLK–時(shí)鐘線
HSYNC\VSYNC–同步線
DE–數(shù)據(jù)使能

DISP是顯示使能,控制屏幕的哈
背光是通過控制LED+\LED-的電流實(shí)現(xiàn)的
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
由此可以找到,LED需要流過20mA電流,下面是它的推薦電路
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
接著我就繪制了我的PCB,如下所示:我的是電容觸摸屏,所以電阻觸摸引腳位置懸空的
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
接下來,我們就來CubeMx配置LTDC驅(qū)動(dòng)它吧

CubeMx配置LTDC

硬件相關(guān)參數(shù)設(shè)置

21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
注意:這里的HSYNC、VSYNC、DE的有效極性需要和實(shí)際相反
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
由此圖可以看出HSYNC、VSYNC、DE的有效極性都是高,clk的下降沿采樣
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
上面我的LTDC配置取得都是典型值
Pulse Width對(duì)應(yīng)的是HSW和VSW

引腳需要全部高速
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
然后就還有LTDC輸出給LCD的時(shí)鐘信號(hào),由上面的數(shù)據(jù)手冊(cè)給出的典型值配置25MHz,LTDC會(huì)由LTDC_PCLK引腳輸出給LCD
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
到此,LTDC硬件相關(guān)的參數(shù)配置完畢

LTDC圖像層配置

21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
開啟全局中斷,并且優(yōu)先級(jí)可以設(shè)置低點(diǎn)
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
DMA2D在代碼里重新配置過得,可以按此設(shè)置
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
關(guān)于FMC的SDRAM存儲(chǔ)屬性設(shè)置可以參考如下:
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)

調(diào)試

如何判定硬件問題:
在函數(shù)void MX_LTDC_Init(void)中的HAL_LTDC_Init()后如下處理:
21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明,STM32,stm32,單片機(jī),fpga開發(fā)
如果LCD能顯示紅色說明硬件正常,否則有問題
lcd_base_backlight_set是開啟屏幕背光

完整工程下載:(舊版本,不建議使用,LCD顯示刷新沒處理后續(xù)說的cache更新)

鏈接:https://pan.baidu.com/s/1g_VezTfR_-fgqSpPFlvtqQ
提取碼:qqio

補(bǔ)充:

該屏幕GT911驅(qū)動(dòng):

需要注意的是INT引腳禁止上下拉,應(yīng)配置為浮空輸入
觸摸屏手指觸摸時(shí)會(huì)觸摸70ms左右,這段時(shí)間其實(shí)坐標(biāo)是同一點(diǎn),INT引腳持續(xù)輸出方波信號(hào)10ms間隔
所以應(yīng)采集判定坐標(biāo)避免重復(fù)點(diǎn)如下函數(shù):

/****************************************************
@function:觸摸芯片掃描
@param:(x,y)--點(diǎn)
@return:-1--無觸摸,0--觸摸
@note:只讀取一個(gè)點(diǎn),建議10ms執(zhí)行一次
注意:此函數(shù)未處理重復(fù)觸摸點(diǎn),尤其是在兩次點(diǎn)擊相同像素點(diǎn)的情況下,但是概率不大
****************************************************/
int GT911_Scan(uint16_t *x,uint16_t *y)
{
    static uint16_t xlast = 0,ylast = 0;
    
    if(!gt911.Enable)return -1;
    if(!GT911_PenInt())return -1;//沒有觸摸
    GT911_TouchPointRead(x,y);
    if((*x == xlast) && (*y == ylast))return -1;//移除重復(fù)點(diǎn)
    xlast = *x;
    ylast = *y;
    return 0;
}

完整驅(qū)動(dòng)代碼:
GT911_driver.c
GT911_driver.h
i2c_driver.c//模擬IIC
i2c_driver.h
delay_driver.c//定時(shí)器微秒精確延時(shí)
delay_driver.h

GT911_driver.h

#ifndef _GT911_driver_H_
#define _GT911_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"

uint16_t GT911_ScreenWidthGet(void);
uint16_t GT911_ScreenHeigthGet(void);
int GT911_Init(void);
int GT911_Scan(uint16_t *x,uint16_t *y);

#ifdef __cplusplus
}
#endif
#endif

GT911_driver.c

/**********************************************************************
*file:自己編寫的GT911觸摸檢測
*author:殘夢
*versions:V1.0
*date:2023.11.8
*note:
注意GT911的INT引腳會(huì)在觸摸時(shí)出現(xiàn)10ms的方波信號(hào),手指單次觸摸維持在70ms左右,
持續(xù)觸摸會(huì)一直到釋放,默認(rèn)高電平,觸摸低電平,引腳應(yīng)浮空嚴(yán)禁上下拉
**********************************************************************/
#include "GT911_driver.h"
#include "i2c_driver.h"
#include "delay_driver.h"
#include "gpio.h"
#include "stdio.h"

/* 定義觸筆中斷INT的GPIO端口 */
#define TP_INT_GPIO_CLK_ENABLE()	__HAL_RCC_GPIOD_CLK_ENABLE()
#define TP_INT_GPIO_PORT              GPIOD
#define TP_INT_PIN                    GPIO_PIN_4
#define TP_RST_GPIO_CLK_ENABLE()	__HAL_RCC_GPIOD_CLK_ENABLE()
#define TP_RST_GPIO_PORT              GPIOD
#define TP_RST_PIN                    GPIO_PIN_5

//#define GT911_I2C_ADDR1		 0xBA
#define GT911_READ_XY_REG    0x814E /* 坐標(biāo)寄存器 */ 
#define GT911_CLEARBUF_REG   0x814E /* 清除坐標(biāo)寄存器 */ 
#define GT911_CONFIG_REG     0x8047 /* 配置參數(shù)寄存器 */ 
#define GT911_COMMAND_REG    0x8040 /* 實(shí)時(shí)命令 */ 
#define GT911_PRODUCT_ID_REG 0x8140 /* 芯片ID */ 
#define GT911_VENDOR_ID_REG  0x814A /* 當(dāng)前模組選項(xiàng)信息 */ 
#define GT911_CONFIG_VERSION_REG   0x8047 /* 配置文件版本號(hào) */ 
#define GT911_CONFIG_CHECKSUM_REG  0x80FF /* 配置文件校驗(yàn)碼 */ 
#define GT911_FIRMWARE_VERSION_REG 0x8144 /* 固件版本號(hào) */ 

typedef struct
{
    //芯片參數(shù)
	uint8_t	i2cAddress;//i2c地址
	uint16_t width;//屏幕寬度
	uint16_t height;//屏幕高度

    //用戶變量
	uint8_t Enable;//使能狀態(tài),初始化成功則為1,失敗為0
}GT911_StructDef;

static GT911_StructDef gt911 = \
{
    .Enable = 0,
};//觸摸屏結(jié)構(gòu)體變量
static void GT911_WriteReg(uint16_t _usRegAddr, uint8_t *_pRegBuf, uint8_t _ucLen);
static void GT911_ReadReg(uint16_t _usRegAddr, uint8_t *_pRegBuf, uint8_t _ucLen);
static void GT911_ReadMaxXY(uint16_t *_X, uint16_t *_Y);
static void GT911_InitPin(void);
static uint32_t GT911_ReadID(void);
static int GT911_DetectID(void);
static uint8_t GT911_PenInt(void);
static void GT911_TouchPointRead(uint16_t *x,uint16_t *y);

/****************************************************
@function:寫1個(gè)或連續(xù)的多個(gè)寄存器
@param: _usRegAddr : 寄存器地址
        _pRegBuf : 寄存器數(shù)據(jù)緩沖區(qū)
        _ucLen : 數(shù)據(jù)長度
@return:void
@note:
****************************************************/
static void GT911_WriteReg(uint16_t _usRegAddr, uint8_t *_pRegBuf, uint8_t _ucLen)
{
	uint8_t i;

    i2c_Start();					/* 總線開始信號(hào) */

    i2c_SendByte(gt911.i2cAddress);	/* 發(fā)送設(shè)備地址+寫信號(hào) */
	i2c_WaitAck();

    i2c_SendByte(_usRegAddr >> 8);	/* 地址高8位 */
	i2c_WaitAck();

    i2c_SendByte(_usRegAddr);		/* 地址低8位 */
	i2c_WaitAck();

	for (i = 0; i < _ucLen; i++)
	{
	    i2c_SendByte(_pRegBuf[i]);		/* 寄存器數(shù)據(jù) */
		i2c_WaitAck();
	}

    i2c_Stop();                   			/* 總線停止信號(hào) */
}

/****************************************************
@function:讀1個(gè)或連續(xù)的多個(gè)寄存器
@param: _usRegAddr : 寄存器地址
        _pRegBuf : 寄存器數(shù)據(jù)緩沖區(qū)
        _ucLen : 數(shù)據(jù)長度
@return:void
@note:
****************************************************/
static void GT911_ReadReg(uint16_t _usRegAddr, uint8_t *_pRegBuf, uint8_t _ucLen)
{
	uint8_t i;
	
	{
		i2c_Start();					/* 總線開始信號(hào) */

		i2c_SendByte(gt911.i2cAddress);	/* 發(fā)送設(shè)備地址+寫信號(hào) */
		i2c_WaitAck();

		i2c_SendByte(_usRegAddr >> 8);	/* 地址高8位 */
		i2c_WaitAck();

		i2c_SendByte(_usRegAddr);		/* 地址低8位 */
		i2c_WaitAck();

		i2c_Start();
		i2c_SendByte(gt911.i2cAddress + 0x01);	/* 發(fā)送設(shè)備地址+讀信號(hào) */

		i2c_WaitAck();
	}
	
	for (i = 0; i < 30; i++);

	for (i = 0; i < _ucLen - 1; i++)
	{
	    _pRegBuf[i] = i2c_ReadByte();	/* 讀寄存器數(shù)據(jù) */
		i2c_Ack();
	}

	/* 最后一個(gè)數(shù)據(jù) */
	 _pRegBuf[i] = i2c_ReadByte();		/* 讀寄存器數(shù)據(jù) */
	i2c_NAck();

    i2c_Stop();							/* 總線停止信號(hào) */
}

/****************************************************
@function:獲得GT911觸摸板的分辨率,X、Y最大值+1.
@param: *_X : 水平分辨率
		*_Y : 垂直分辨率
@return:void
@note:
****************************************************/
static void GT911_ReadMaxXY(uint16_t *_X, uint16_t *_Y)
{
	uint8_t buf[4];
	
	GT911_ReadReg(0x8048, buf, 4);
	
	*_X = buf[0] + buf[1] * 256;
	*_Y = buf[2] + buf[3] * 256;
}

/****************************************************
@function:配置觸摸芯片初始化引腳
@param:void
@return:void
@note:
****************************************************/
static void GT911_InitPin(void)
{
	GPIO_InitTypeDef gpio_init;

	/* 第1步:打開GPIO時(shí)鐘 */
	TP_INT_GPIO_CLK_ENABLE();
    TP_RST_GPIO_CLK_ENABLE();
	
	/* 第2步:配置所有的按鍵GPIO為浮動(dòng)輸入模式 */
	gpio_init.Mode = GPIO_MODE_INPUT;   		/* 設(shè)置輸入 */
	gpio_init.Pull = GPIO_NOPULL;                 /* 浮空:嚴(yán)禁上下拉 */
	
	gpio_init.Speed = GPIO_SPEED_FREQ_LOW;  /* GPIO速度等級(jí) */
	gpio_init.Pin = TP_INT_PIN;
	HAL_GPIO_Init(TP_INT_GPIO_PORT, &gpio_init);

	gpio_init.Mode = GPIO_MODE_OUTPUT_PP;
	gpio_init.Pull = GPIO_NOPULL;
	gpio_init.Speed = GPIO_SPEED_FREQ_LOW;  /* GPIO速度等級(jí) */
	gpio_init.Pin = TP_RST_PIN;
	HAL_GPIO_Init(TP_RST_GPIO_PORT, &gpio_init);
    HAL_GPIO_WritePin(TP_RST_GPIO_PORT,TP_RST_PIN,GPIO_PIN_SET);//使能觸摸芯片
}

/****************************************************
@function:獲得GT911的芯片ID
@param:void
@return:void
@note:16位版本
****************************************************/
static uint32_t GT911_ReadID(void)
{
	uint8_t buf[4]; 

	GT911_ReadReg(GT911_PRODUCT_ID_REG, buf, 4); 

	return ((uint32_t)buf[3] << 24) + ((uint32_t)buf[2] << 16) + ((uint32_t)buf[1] <<8) + buf[0]; 
}

/****************************************************
@function:設(shè)置GT911芯片屏幕的寬度
@param:void
@return:void
@note:
****************************************************/
uint16_t GT911_ScreenWidthGet(void)
{
	return gt911.width;
}

/****************************************************
@function:設(shè)置GT911芯片屏幕的高度
@param:void
@return:void
@note:
****************************************************/
uint16_t GT911_ScreenHeigthGet(void)
{
	return gt911.height;
}

/****************************************************
@function:觸摸芯片識(shí)別
@param:void
@return:-1--識(shí)別失敗,0--成功
@note:
****************************************************/
static int GT911_DetectID(void)
{
	uint8_t i = 0,address = 0;
	uint32_t id = 0;
	uint16_t MaxX = 0, MaxY = 0;

	HAL_Delay(50);//50ms,等待GT811復(fù)位就緒,才能探測GT811芯片 ID
	printf("開始識(shí)別觸摸屏型號(hào)...\r\n");
	address = 0x28;
	for(i=0;i < 5;i++)//GT811電容觸摸板和GT911的I2C地址相同,一般就 0x28 、 0xBA 兩種,通過讀取觸摸IC的芯片ID來識(shí)別
	{
		address = (address == 0x28)?0xBA:0x28;
		if(i2c_CheckDevice(address) == 0)
		{
			delay_us(500);
			gt911.i2cAddress = address;
			id = GT911_ReadID();
			if(id == 0x00313139)
			{
				GT911_ReadMaxXY(&MaxX, &MaxY);//讀取屏幕寬度、高度
				gt911.width = MaxX;
				gt911.height = MaxY;
				if (MaxX == 480 && MaxY == 272){printf("檢測到4.3寸電容觸摸屏GT911(0x28) 480x272\r\n");}				
				else{printf("檢測到7.0寸電容觸摸屏GT911(0x28) 800x480\r\n");}
				return 0;
			}
			else
			{
				printf("檢測到7.0寸電容觸摸屏GT811(0x28) 800x480\r\n");
				return -1;
			}
		}
		HAL_Delay(10);
	}

	printf("未識(shí)別出顯示模塊\r\n");
	return -1;
}

/****************************************************
@function:配置觸摸芯片初始化
@param:void
@return:-1--識(shí)別失敗,0--成功
@note:調(diào)用此函數(shù)初始化觸摸芯片需初始化IIC引腳i2c_Init()
****************************************************/
int GT911_Init(void)
{
	gt911.Enable = 0;
	i2c_Init();//主函數(shù)中已經(jīng)初始化
	GT911_InitPin();
	if(GT911_DetectID() < 0)return -1;
	gt911.Enable = 1;
	return 0;
}

/****************************************************
@function:判斷觸摸按下
@param:void
@return:0表示無觸筆按下,1表示有觸筆按下
@note:
****************************************************/
static uint8_t GT911_PenInt(void)
{
    //if(HAL_GPIO_ReadPin(TP_INT_GPIO_PORT,TP_INT_PIN) == GPIO_PIN_RESET)return 1;
	if ((TP_INT_GPIO_PORT->IDR & TP_INT_PIN) == 0)return 1;
	return 0;
}

/****************************************************
@function:讀取觸摸點(diǎn)
@param:x,y--點(diǎn)
@return:-1--參數(shù)錯(cuò)誤,0--成功
@note:讀取GT911觸摸數(shù)據(jù);讀取全部8個(gè)點(diǎn)的數(shù)據(jù),需要 720us左右
****************************************************/
static void GT911_TouchPointRead(uint16_t *x,uint16_t *y)
{
	uint8_t clear_flag = 0;
	uint8_t buf[48];//一個(gè)點(diǎn)8個(gè)字節(jié),5點(diǎn)*8=40
	GT911_ReadReg(GT911_READ_XY_REG, buf, 8);
	GT911_WriteReg(GT911_READ_XY_REG, &clear_flag,	1);//讀完坐標(biāo)后必須寫0清除

    //TouchpointFlag = buf[0];
    //Touchkeystate = buf[1];
    *x = ((uint16_t)buf[3] << 8) + buf[2];
    *y = ((uint16_t)buf[5] << 8) + buf[4];
    //p = ((uint16_t)buf[7] << 8) + buf[6];
}

/****************************************************
@function:觸摸芯片掃描
@param:(x,y)--點(diǎn)
@return:-1--無觸摸,0--觸摸
@note:只讀取一個(gè)點(diǎn),建議10ms執(zhí)行一次
注意:此函數(shù)未處理重復(fù)觸摸點(diǎn),尤其是在兩次點(diǎn)擊相同像素點(diǎn)的情況下,但是概率不大
****************************************************/
int GT911_Scan(uint16_t *x,uint16_t *y)
{
    static uint16_t xlast = 0,ylast = 0;
    
    if(!gt911.Enable)return -1;
    if(!GT911_PenInt())return -1;//沒有觸摸
    GT911_TouchPointRead(x,y);
    if((*x == xlast) && (*y == ylast))return -1;//移除重復(fù)點(diǎn)
    xlast = *x;
    ylast = *y;
    return 0;
}

i2c_driver.h

#ifndef _i2c_driver_H_
#define _i2c_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"

#define I2C_WR	0		/* 寫控制bit */
#define I2C_RD	1		/* 讀控制bit */

void i2c_Init(void);
void i2c_Start(void);
void i2c_Stop(void);
void i2c_SendByte(uint8_t _ucByte);
uint8_t i2c_ReadByte(void);
uint8_t i2c_WaitAck(void);
void i2c_Ack(void);
void i2c_NAck(void);
uint8_t i2c_CheckDevice(uint8_t _Address);

#ifdef __cplusplus
}
#endif
#endif

i2c_driver.c

/**********************************************************************
*file:GPIO引腳模擬IIC文件
*author:殘夢
*versions:V1.1
*date:2023.07.30
*note:
**********************************************************************/
#include "i2c_driver.h"
#include "delay_driver.h"
#include "gpio.h"

//宏定義
/* 定義I2C總線連接的GPIO端口, 用戶只需要修改下面4行代碼即可任意改變SCL和SDA的引腳 */
#define I2C_SCL_GPIO	GPIOB			/* 連接到SCL時(shí)鐘線的GPIO */
#define I2C_SDA_GPIO	GPIOB			/* 連接到SDA數(shù)據(jù)線的GPIO */

#define I2C_SCL_PIN		GPIO_PIN_6			/* 連接到SCL時(shí)鐘線的GPIO */
#define I2C_SDA_PIN		GPIO_PIN_7			/* 連接到SDA數(shù)據(jù)線的GPIO */

#define ALL_I2C_GPIO_CLK_ENABLE()	__HAL_RCC_GPIOB_CLK_ENABLE()


/* 定義讀寫SCL和SDA的宏 */
#define I2C_SCL_1()  I2C_SCL_GPIO->BSRR = I2C_SCL_PIN				    /* SCL = 1 */
#define I2C_SCL_0()  I2C_SCL_GPIO->BSRR = ((uint32_t)I2C_SCL_PIN << 16U)/* SCL = 0 */

#define I2C_SDA_1()  I2C_SDA_GPIO->BSRR = I2C_SDA_PIN				    /* SDA = 1 */
#define I2C_SDA_0()  I2C_SDA_GPIO->BSRR = ((uint32_t)I2C_SDA_PIN << 16U)/* SDA = 0 */

#define I2C_SDA_READ()  ((I2C_SDA_GPIO->IDR & I2C_SDA_PIN) != 0)	/* 讀SDA口線狀態(tài) */
#define I2C_SCL_READ()  ((I2C_SCL_GPIO->IDR & I2C_SCL_PIN) != 0)	/* 讀SCL口線狀態(tài) */

static void i2c_Delay(void);

/****************************************************
@function:配置I2C總線的GPIO,采用模擬IO的方式實(shí)現(xiàn)
@param:void
@return:void
@note:
****************************************************/
void i2c_Init(void)
{
	GPIO_InitTypeDef gpio_init;

	/* 第1步:打開GPIO時(shí)鐘 */
	ALL_I2C_GPIO_CLK_ENABLE();
	
	gpio_init.Mode = GPIO_MODE_OUTPUT_OD;	/* 設(shè)置開漏輸出 */
	gpio_init.Pull = GPIO_NOPULL;			/* 上下拉電阻不使能 */
	gpio_init.Speed = GPIO_SPEED_FREQ_LOW;	// GPIO_SPEED_FREQ_HIGH;  /* GPIO速度等級(jí) */
	
	gpio_init.Pin = I2C_SCL_PIN;	
	HAL_GPIO_Init(I2C_SCL_GPIO, &gpio_init);	
	
	gpio_init.Pin = I2C_SDA_PIN;	
	HAL_GPIO_Init(I2C_SDA_GPIO, &gpio_init);	

	/* 給一個(gè)停止信號(hào), 復(fù)位I2C總線上的所有設(shè)備到待機(jī)模式 */
	i2c_Stop();
}

/****************************************************
@function:I2C總線位延遲,最快400KHz
@param:void
@return:void
@note:
****************************************************/
static void i2c_Delay(void)
{
	delay_us(2);
}

/****************************************************
@function:發(fā)起I2C總線啟動(dòng)信號(hào)
@param:void
@return:void
@note:
****************************************************/
void i2c_Start(void)
{
	/* 當(dāng)SCL高電平時(shí),SDA出現(xiàn)一個(gè)下跳沿表示I2C總線啟動(dòng)信號(hào) */
	I2C_SDA_1();
	I2C_SCL_1();
	i2c_Delay();
	I2C_SDA_0();
	i2c_Delay();
	
	I2C_SCL_0();
	i2c_Delay();
}

/****************************************************
@function:發(fā)起I2C總線停止信號(hào)
@param:void
@return:void
@note:
****************************************************/
void i2c_Stop(void)
{
	/* 當(dāng)SCL高電平時(shí),SDA出現(xiàn)一個(gè)上跳沿表示I2C總線停止信號(hào) */
	I2C_SDA_0();
	i2c_Delay();
	I2C_SCL_1();
	i2c_Delay();
	I2C_SDA_1();
	i2c_Delay();
}

/****************************************************
@function:向I2C總線設(shè)備發(fā)送8bit數(shù)據(jù)
@param:_ucByte : 等待發(fā)送的字節(jié)
@return:void
@note:
****************************************************/
void i2c_SendByte(uint8_t _ucByte)
{
	uint8_t i;

	/* 先發(fā)送字節(jié)的高位bit7 */
	for (i = 0; i < 8; i++)
	{
		if (_ucByte & 0x80)
		{
			I2C_SDA_1();
		}
		else
		{
			I2C_SDA_0();
		}
		i2c_Delay();
		I2C_SCL_1();
		i2c_Delay();
		I2C_SCL_0();
		I2C_SCL_0();	/* 2019-03-14 針對(duì)GT811電容觸摸,添加一行,相當(dāng)于延遲幾十ns */
		if (i == 7)
		{
			 I2C_SDA_1(); // 釋放總線
		}
		_ucByte <<= 1;	/* 左移一個(gè)bit */	
	}
}

/****************************************************
@function:從I2C總線設(shè)備讀取8bit數(shù)據(jù)
@param:void
@return:讀到的數(shù)據(jù)
@note:
****************************************************/
uint8_t i2c_ReadByte(void)
{
	uint8_t i;
	uint8_t value;

	/* 讀到第1個(gè)bit為數(shù)據(jù)的bit7 */
	value = 0;
	for (i = 0; i < 8; i++)
	{
		value <<= 1;
		I2C_SCL_1();
		i2c_Delay();
		if (I2C_SDA_READ())
		{
			value++;
		}
		I2C_SCL_0();
		i2c_Delay();
	}
	return value;
}

/****************************************************
@function:產(chǎn)生一個(gè)時(shí)鐘,并讀取器件的ACK應(yīng)答信號(hào)
@param:void
@return:返回0表示正確應(yīng)答,1表示無器件響應(yīng)
@note:
****************************************************/
uint8_t i2c_WaitAck(void)
{
	uint8_t re;

	I2C_SDA_1();	/* CPU釋放SDA總線 */
	i2c_Delay();
	I2C_SCL_1();	/* CPU驅(qū)動(dòng)SCL = 1, 此時(shí)器件會(huì)返回ACK應(yīng)答 */
	i2c_Delay();
	if (I2C_SDA_READ())	/* CPU讀取SDA口線狀態(tài) */
	{
		re = 1;
	}
	else
	{
		re = 0;
	}
	I2C_SCL_0();
	i2c_Delay();
	return re;
}

/****************************************************
@function:產(chǎn)生一個(gè)ACK信號(hào)
@param:void
@return:void
@note:
****************************************************/
void i2c_Ack(void)
{
	I2C_SDA_0();	/* CPU驅(qū)動(dòng)SDA = 0 */
	i2c_Delay();
	I2C_SCL_1();	/* CPU產(chǎn)生1個(gè)時(shí)鐘 */
	i2c_Delay();
	I2C_SCL_0();
	i2c_Delay();
	I2C_SDA_1();	/* CPU釋放SDA總線 */
	
	i2c_Delay();
}

/****************************************************
@function:產(chǎn)生1個(gè)NACK信號(hào)
@param:void
@return:void
@note:
****************************************************/
void i2c_NAck(void)
{
	I2C_SDA_1();	/* CPU驅(qū)動(dòng)SDA = 1 */
	i2c_Delay();
	I2C_SCL_1();	/* CPU產(chǎn)生1個(gè)時(shí)鐘 */
	i2c_Delay();
	I2C_SCL_0();
	i2c_Delay();
}

/****************************************************
@function:檢測I2C總線設(shè)備,CPU向發(fā)送設(shè)備地址,然后讀取設(shè)備應(yīng)答來判斷該設(shè)備是否存在
@param:_Address:設(shè)備的I2C總線地址
@return:返回值 0 表示正確, 返回1表示未探測到
@note:
****************************************************/
uint8_t i2c_CheckDevice(uint8_t _Address)
{
	uint8_t ucAck;

	if (I2C_SDA_READ() && I2C_SCL_READ())
	{
		i2c_Start();		/* 發(fā)送啟動(dòng)信號(hào) */

		/* 發(fā)送設(shè)備地址+讀寫控制bit(0 = w, 1 = r) bit7 先傳 */
		i2c_SendByte(_Address | I2C_WR);
		ucAck = i2c_WaitAck();	/* 檢測設(shè)備的ACK應(yīng)答 */

		i2c_Stop();			/* 發(fā)送停止信號(hào) */

		return ucAck;
	}
	return 1;	/* I2C總線異常 */
}


delay_driver.h

#ifndef _delay_driver_H_
#define _delay_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdlib.h"

void delay_Init(void);
void delay_us(unsigned int us);

#ifdef __cplusplus
}
#endif
#endif

delay_driver.h

/**********************************************************************
*file:微秒級(jí)精確延時(shí)
*author:殘夢
*versions:V1.0
*date:2023.10.17
*note:基礎(chǔ)時(shí)基是0.1us
1、修改dDelayTIM和dDelayTIM_Handle
配置定時(shí)器參數(shù)參考delay_Init()
**********************************************************************/
#include "delay_driver.h"
#include "tim.h"

#define dDelayTIM TIM24
#define dDelayTIM_Handle htim24
#define dTIM_Bit (32) //定時(shí)器位數(shù);32位定時(shí)器時(shí)0xFFFFFFFF,16位定時(shí)器0xFFFF
#define dTIM_Period_MAX ((uint32_t )((dTIM_Bit == 16)?0xFFFF:0xFFFFFFFF))
//TIM_HandleTypeDef htim24;//CubeMx配置了,就不重復(fù)定義


/******************************
@function:初始化延時(shí)
@param:void
@return:void
@remark:CubeMx配置了,就不重復(fù)配置
******************************/
void delay_Init(void)
{
    TIM_ClockConfigTypeDef sClockSourceConfig = {0};
    TIM_MasterConfigTypeDef sMasterConfig = {0};

    dDelayTIM_Handle.Instance = dDelayTIM;
    dDelayTIM_Handle.Init.Prescaler = 275-1;
    dDelayTIM_Handle.Init.CounterMode = TIM_COUNTERMODE_UP;
    dDelayTIM_Handle.Init.Period = dTIM_Period_MAX;
    dDelayTIM_Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    dDelayTIM_Handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
    if (HAL_TIM_Base_Init(&dDelayTIM_Handle) != HAL_OK)
    {
        Error_Handler();
    }
    sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
    if (HAL_TIM_ConfigClockSource(&dDelayTIM_Handle, &sClockSourceConfig) != HAL_OK)
    {
        Error_Handler();
    }
    sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
    sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
    if (HAL_TIMEx_MasterConfigSynchronization(&dDelayTIM_Handle, &sMasterConfig) != HAL_OK)
    {
        Error_Handler();
    }
}

/******************************
@function:us延時(shí)
@param:us--待延時(shí)的時(shí)間
@return:void
@remark:
******************************/
void delay_us(uint32_t us)
{
  if(!us){return;}
  us = (us > (dTIM_Period_MAX))?dTIM_Period_MAX:us;
  //us *= 1;//基礎(chǔ)是1us
  dDelayTIM_Handle.Instance->CNT = 0;
  HAL_TIM_Base_Start(&dDelayTIM_Handle);
  while(dDelayTIM_Handle.Instance->CNT < us);
  HAL_TIM_Base_Stop(&dDelayTIM_Handle);
}

該屏幕LCD驅(qū)動(dòng)說明:

在使用DMA2D刷新SDRAM數(shù)據(jù)時(shí)應(yīng)根據(jù)自己內(nèi)存區(qū)屬性是否添加CACHE更新

SCB_CleanInvalidateDCache();//注意,此處需要讓Cache內(nèi)容更新

如H7開啟MPU和Cache后使用0x24000000做數(shù)顯,配置為透寫或回寫,不添加此句更新cache就會(huì)出現(xiàn)隨機(jī)花屏
填充函數(shù)和復(fù)制顏色塊函數(shù)

/****************************************************
@function:通過DMA2D對(duì)于指定區(qū)域進(jìn)行顏色填充(固定顏色)
@param:
    LayerIndex    圖層
    pDst          顏色數(shù)據(jù)目的地址
    xSize         要復(fù)制區(qū)域的X軸大小,即每行像素?cái)?shù)
    ySize         要復(fù)制區(qū)域的Y軸大小,即行數(shù)
    OffLine       前景層圖像的行偏移
    ColorIndex    要填充的顏色值
@return:void
@note:
****************************************************/
static void lcd_base_DMA2D_FillBuffer(uint32_t LayerIndex, void * pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLine, uint32_t ColorIndex) 
{
	uint32_t PixelFormat;

	PixelFormat = LTDC_PIXEL_FORMAT_RGB565;

	/* 顏色填充 */
	DMA2D->CR      = 0x00030000UL | (1 << 9);        
	DMA2D->OCOLR   = ColorIndex;                     

	/* 設(shè)置填充的顏色目的地址 */
	DMA2D->OMAR    = (uint32_t)pDst;                      

	/* 目的行偏移地址 */
	DMA2D->OOR     = OffLine;                        

	/* 設(shè)置顏色格式 */
	DMA2D->OPFCCR  = PixelFormat;                    

	/* 設(shè)置填充大小 */
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;

      SCB_CleanInvalidateDCache();//注意,此處需要讓Cache內(nèi)容更新
	DMA2D->CR     |= DMA2D_CR_START; 

	/* 等待DMA2D傳輸完成 */
	while (DMA2D->CR & DMA2D_CR_START) 
	{
	}
}

/**********************************************************************************************************
*	函 數(shù) 名: _DMA2D_Copy
*	功能說明: 通過DMA2D從前景層復(fù)制指定區(qū)域的顏色數(shù)據(jù)到目標(biāo)區(qū)域
*	形    參: pSrc          顏色數(shù)據(jù)源地址
*             pDst          顏色數(shù)據(jù)目的地址
*             xSize         目的區(qū)域的X軸大小,即每行像素?cái)?shù)
*             ySize         目的區(qū)域的Y軸大小,即行數(shù)
*             OffLineSrc    前景層圖像的行偏移
*             OffLineDst    輸出的行偏移
*             PixelFormat   目標(biāo)區(qū)顏色格式
*	返 回 值: 無
**********************************************************************************************************/
static void lcd_base_DMA2D_Copy(void * pSrc, void * pDst, uint32_t xSize, uint32_t ySize, uint32_t OffLineSrc, uint32_t OffLineDst, uint32_t PixelFormat) 
{

	/* DMA2D采用存儲(chǔ)器到存儲(chǔ)器模式, 這種模式是前景層作為DMA2D輸入 */  
	DMA2D->CR      = 0x00000000UL | (1 << 9);
	DMA2D->FGMAR   = (uint32_t)pSrc;
	DMA2D->OMAR    = (uint32_t)pDst;
	DMA2D->FGOR    = OffLineSrc;
	DMA2D->OOR     = OffLineDst;
	
	/* 前景層和輸出區(qū)域都采用的RGB565顏色格式 */
	DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
	DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;
	
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;
      
      SCB_CleanInvalidateDCache();//注意,此處需要讓Cache內(nèi)容更新
	/* 啟動(dòng)傳輸 */
	DMA2D->CR   |= DMA2D_CR_START;   

	/* 等待DMA2D傳輸完成 */
	while (DMA2D->CR & DMA2D_CR_START) {} 
}

/****************************************************
@function:通過DMA2D對(duì)于指定區(qū)域進(jìn)行顏色復(fù)制(圖像復(fù)制)
@param:
    LayerIndex    圖層
    pDst          顏色數(shù)據(jù)目的地址
    xSize         要復(fù)制區(qū)域的X軸大小,即每行像素?cái)?shù)
    ySize         要復(fù)制區(qū)域的Y軸大小,即行數(shù)
    OffLine       前景層圖像的行偏移
    ColorIndex    要填充的顏色值
@return:void
@note:只支持橫屏
****************************************************/
void lcd_base_DMA2D_CopyBuffer(uint16_t x,uint16_t y,uint32_t xSize, uint32_t ySize,void * color)
{
    if((color == NULL) || (xSize == 0) || (ySize == 0))return;

	lcd_base_DMA2D_Copy((uint32_t *)color,                                        /* 位圖地址 */
			    (uint32_t *)(s_CurrentFrameBuffer + g_LcdWidth*y*2 + x*2),       /* 顯示起始地址(328, 20) */  
			    xSize,                                                          /* 位圖長 */
			    ySize,                                                          /* 位圖高 */
			    0,                                                            /* 位圖行偏移 */
			    g_LcdWidth-xSize,                                               /* 目標(biāo)區(qū)行偏移 */
			    LTDC_PIXEL_FORMAT_RGB565);                                    /* 目標(biāo)區(qū)顏色格式 */
}

完整工程:(最新)

鏈接:https://pan.baidu.com/s/1I64wD4Ft7PBI0cIogGp45A
提取碼:qpxx
文章來源地址http://www.zghlxwxcb.cn/news/detail-752811.html

到了這里,關(guān)于21.1 stm32使用LTDC驅(qū)動(dòng)LCD--配置說明的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • STM32F1基于STM32CubeMX配置硬件SPI驅(qū)動(dòng)1.8寸TFT LCD128X160 ST7735S屏幕

    STM32F1基于STM32CubeMX配置硬件SPI驅(qū)動(dòng)1.8寸TFT LCD128X160 ST7735S屏幕

    ??相關(guān)篇《【STM32CubeIDE】STM32F103硬件SPI驅(qū)動(dòng)1.8寸TFT LCD128X160 ST7735S屏幕》 ?驅(qū)動(dòng)效果就不做演示了,和上面的相關(guān)篇一樣,主要是為了方便使用MDK Keil開發(fā)的使用。所以花了點(diǎn)時(shí)間從上面的工程當(dāng)中做了分離,重新使用STM32CubeMX配置一個(gè)方便二次開發(fā)移植使用和配置的工程。本

    2024年02月03日
    瀏覽(27)
  • 一文讀懂使用STM32驅(qū)動(dòng) LCD1602 液晶顯示屏(基于Mbed Studio平臺(tái))

    一文讀懂使用STM32驅(qū)動(dòng) LCD1602 液晶顯示屏(基于Mbed Studio平臺(tái))

    LCD (Liquid Crystal Display) 液晶顯示屏是一種廣泛使用的一種字符型液晶顯示模塊。其中型號(hào)1602表示每行顯示16個(gè)字符、一共2行。LCD1602相比于OLED最大的好處就是不用使用SPI或I2C等任何通信協(xié)議,而是由mbed直接將命令傳給LCD從而實(shí)現(xiàn)控制。 LCD1602主要參數(shù)如下: 顯示字符:16×2個(gè)

    2024年02月05日
    瀏覽(26)
  • 【STM32篇】驅(qū)動(dòng)LCD顯示屏

    【STM32篇】驅(qū)動(dòng)LCD顯示屏

    本次使用的硬件設(shè)備為野火的霸道V2開發(fā)板,顯示器控制芯片型號(hào)為ILI9341,實(shí)際型號(hào)為ST7789V。在編寫代碼時(shí)參考的是ILI9341數(shù)據(jù)手冊(cè),二者差別不大,都是240*320分辨率。 ????????ILI9341是一個(gè)用于TFT液晶顯示的單芯片控制驅(qū)動(dòng)器,具有262144色的240RGB x 320像素顯示解決方案。

    2024年02月12日
    瀏覽(23)
  • STM32MP157驅(qū)動(dòng)開發(fā)——Linux LCD驅(qū)動(dòng)(上)

    STM32MP157驅(qū)動(dòng)開發(fā)——Linux LCD驅(qū)動(dòng)(上)

    ??LCD 是很常用的一個(gè)外設(shè),通過 LCD 可以顯示圖片、界面UI等,提高人機(jī)交互的效率。STM32MP1 提供了一個(gè) LTDC 接口用于連接 RGB 接口的液晶屏。本節(jié)就來學(xué)習(xí)如何使用這個(gè)接口。 ??LCD 全稱是 Liquid Crystal Display,也就是液晶顯示器,是現(xiàn)在最常用到的顯示器。網(wǎng)上對(duì)于 LCD

    2024年02月08日
    瀏覽(19)
  • 【STM32】驅(qū)動(dòng)LCD1602液晶8線并、4線并

    【STM32】驅(qū)動(dòng)LCD1602液晶8線并、4線并

    目錄 LCD1602液晶 引腳定義說明 字庫概述? LCD1602原理圖 ?LCD1602時(shí)序圖 LCD1602代碼 接線圖 用結(jié)構(gòu)體的方式顯示字符 LCD1602動(dòng)態(tài)顯示數(shù)字 4線驅(qū)動(dòng)LCD1602 液晶模塊和數(shù)碼管相比,液晶模塊會(huì)顯得更加專業(yè)、漂亮。液晶顯示器以其體積小、功耗低、超薄、輕巧、顯示內(nèi)容豐富、使用方

    2024年02月16日
    瀏覽(18)
  • STM32直接驅(qū)動(dòng)TFT LCD,在LCD上根據(jù)數(shù)據(jù)繪制曲線

    快速畫點(diǎn)函數(shù)和繪制直線函數(shù)可以根據(jù)自己屏幕來編寫, void Port_DrawCurve(u8 x ,u16 value) 1、繪制曲線函數(shù)中的形參x,相當(dāng)于時(shí)間軸,每一次進(jìn)入函數(shù),x就會(huì)++; 2、在繪制曲線之前需要先清除3列,這樣繪制曲線就不用到最后了再整屏幕擦除。

    2024年02月15日
    瀏覽(20)
  • STM32 驅(qū)動(dòng)4.3寸TFT LCD 觸摸屏

    STM32 驅(qū)動(dòng)4.3寸TFT LCD 觸摸屏

    STM32的FSMC接口是并行總線接口,可以用于驅(qū)動(dòng)存儲(chǔ)芯片如FLASH/SRAM等,也可以用于驅(qū)動(dòng)并口LCD屏。觸摸屏是在顯示屏上覆蓋一層觸摸感應(yīng)的外屏,有單獨(dú)的接口輸出坐標(biāo)數(shù)據(jù)。 這里以STM32F103VET6開發(fā)板連接4.3寸TFT LCD觸摸屏,將正點(diǎn)原子的參考代碼,移植到STM32CUBEIDE開發(fā)環(huán)境,實(shí)

    2024年02月11日
    瀏覽(22)
  • stm32驅(qū)動(dòng)st7789 TFT-LCD屏幕顯示

    stm32驅(qū)動(dòng)st7789 TFT-LCD屏幕顯示

    一切程序以最后百度網(wǎng)盤鏈接的程序?yàn)闇?zhǔn),可能在寫文章的時(shí)候有些地方有改動(dòng)。 主控:STM32F103C8T6 1.69 TFT-LCD(st7789驅(qū)動(dòng)) 1.1接線說明 1.2硬件初始化 TFT-LCD是采用SPI通信的,這里使用stm32f103c8t6的SPI1,初始化代碼如下 1.3驅(qū)動(dòng)初始化 在原有的驅(qū)動(dòng)基礎(chǔ)上增加了幾個(gè)宏去控制顯

    2024年02月16日
    瀏覽(34)
  • STM32 FSMC接口驅(qū)動(dòng)4.3寸TFT LCD屏

    STM32 FSMC接口驅(qū)動(dòng)4.3寸TFT LCD屏

    STM32的FSMC接口是并行總線接口,可以用于驅(qū)動(dòng)存儲(chǔ)芯片如FLASH/SRAM等,也可以用于驅(qū)動(dòng)并口LCD屏。 這里以STM32F103VET6開發(fā)板連接4.3寸TFT LCD屏,將正點(diǎn)原子的參考代碼,移植到STM32CUBEIDE開發(fā)環(huán)境,實(shí)現(xiàn)TFT LCD屏的顯示。 TFT LCD模塊的管腳連接: 其中: LCD_CS是總線片選, WR/CLK是寫使

    2024年02月10日
    瀏覽(28)
  • STM32驅(qū)動(dòng)0.96寸TFT 彩色LCD模塊顯示

    STM32驅(qū)動(dòng)0.96寸TFT 彩色LCD模塊顯示

    小型的彩色LCD模塊如一款0.96寸模塊,由ST7735S驅(qū)動(dòng)芯片和LCD屏幕組成。STM32通過驅(qū)動(dòng)ST7735S,從而實(shí)現(xiàn)對(duì)彩色LCD的驅(qū)動(dòng)。 這里將STM32通過硬件SPI驅(qū)動(dòng)0.96寸TFT彩色LCD的參考代碼,移植到STM32CUBEIDE開發(fā)環(huán)境。以STM32G030F6P6為例,可以用于采用ST7735S驅(qū)動(dòng)芯片的其它尺寸LCD屏幕驅(qū)動(dòng)。 LC

    2024年02月16日
    瀏覽(23)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包