历史上的今天
今天是:2024年10月27日(星期日)
2021年10月27日 | stm32专题二十一:FSMC液晶显示和扫描方向
2021-10-27 来源:eefocus
液晶屏连接原理图:

其中值得注意的是,LCD_RESET复位引脚和LCD_BL背光,可以选择普通的GPIO来进行控制。而左侧的FSMC数据线,就直接按照编号连接到液晶屏。右侧LCD_CS片选、RD、WE都是FSMC固定占用的,而命令 / 数据线使用的是地址线A16。
如果程序跑飞了导致下载器无法下载,先按住复位键,再点下载,然后松开复位键就能下载成功。
接下来是代码说明:
初始化GPIO和FMSC,这里一个值得注意点地方就是,我们模拟8080时序使用的是FSMC模式B,这其中有一些时序参数。在操作SRAM时,这些参数可以通过SRAM提供的数据手册来得到。而在驱动液晶屏时,因为提供的参数并没有严格对应,需要使用实验测试参数。多测试几组参数,来获得一个相对稳定且速度较快的参数值。
void ILI9341_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
// 打开 GPIO的时钟
RCC_APB2PeriphClockCmd(ILI9341_CS_CLK | ILI9341_DC_CLK | ILI9341_WR_CLK | ILI9341_RD_CLK | ILI9341_BK_CLK |
ILI9341_RST_CLK | ILI9341_D0_CLK | ILI9341_D1_CLK | ILI9341_D2_CLK | ILI9341_D3_CLK | ILI9341_D4_CLK |
ILI9341_D5_CLK | ILI9341_D6_CLK | ILI9341_D7_CLK |ILI9341_D8_CLK | ILI9341_D9_CLK | ILI9341_D10_CLK |
ILI9341_D11_CLK | ILI9341_D12_CLK | ILI9341_D13_CLK | ILI9341_D14_CLK| ILI9341_D15_CLK, ENABLE);
// 初始化背光和复位引脚(通用推挽模式)
/* 控制引脚 */
GPIO_InitStructure.GPIO_Pin = ILI9341_RST_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ILI9341_RST_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_BK_PIN;
GPIO_Init(ILI9341_BK_PORT, &GPIO_InitStructure);
// 初始化其他引脚(复用推挽模式)
/* 控制引脚 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Pin = ILI9341_CS_PIN;
GPIO_Init(ILI9341_CS_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN;
GPIO_Init(ILI9341_RD_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_RD_PIN;
GPIO_Init(ILI9341_RD_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_WR_PIN;
GPIO_Init(ILI9341_WR_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_DC_PIN;
GPIO_Init(ILI9341_DC_PORT, &GPIO_InitStructure);
/* 数据引脚 */
GPIO_InitStructure.GPIO_Pin = ILI9341_D0_PIN;
GPIO_Init(ILI9341_D0_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D1_PIN;
GPIO_Init(ILI9341_D1_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D2_PIN;
GPIO_Init(ILI9341_D2_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D3_PIN;
GPIO_Init(ILI9341_D3_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D4_PIN;
GPIO_Init(ILI9341_D4_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D5_PIN;
GPIO_Init(ILI9341_D5_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D6_PIN;
GPIO_Init(ILI9341_D6_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D7_PIN;
GPIO_Init(ILI9341_D7_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D8_PIN;
GPIO_Init(ILI9341_D8_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D9_PIN;
GPIO_Init(ILI9341_D9_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D10_PIN;
GPIO_Init(ILI9341_D10_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D11_PIN;
GPIO_Init(ILI9341_D11_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D12_PIN;
GPIO_Init(ILI9341_D12_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D13_PIN;
GPIO_Init(ILI9341_D13_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D14_PIN;
GPIO_Init(ILI9341_D14_PORT, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = ILI9341_D15_PIN;
GPIO_Init(ILI9341_D15_PORT, &GPIO_InitStructure);
}
void ILI9341_FSMC_Config(void)
{
FSMC_NORSRAMInitTypeDef FSMC_NORSRAMInitStructure;
FSMC_NORSRAMTimingInitTypeDef readWriteTiming;
/*使能FSMC外设时钟*/
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC,ENABLE);
/* 这里地址建立时间和数据保持时间,在ILI9341数据手册中没有明确的给出来,
我们实际上是通过实验的方式,来直接测试几个参数,如果可以用就ok
如果把数据改大一点,就不容易出错,但数据改小一点的话,速度就会变快 */
//地址建立时间(ADDSET)
readWriteTiming.FSMC_AddressSetupTime = 0x01; // 数据是试出来的,且有一定余量
//数据保持时间(DATAST)
readWriteTiming.FSMC_DataSetupTime = 0x04; // 数据是试出来的,且有一定余量
//地址保持时间(ADDHLD)模式B未用到
readWriteTiming.FSMC_AddressHoldTime = 0x00;
//设置总线转换周期,仅用于复用模式的NOR操作
readWriteTiming.FSMC_BusTurnAroundDuration = 0x00;
//设置时钟分频,仅用于同步类型的存储器
readWriteTiming.FSMC_CLKDivision = 0x00;
//数据保持时间,仅用于同步型的NOR
readWriteTiming.FSMC_DataLatency = 0x00;
//选择匹配SRAM的模式
readWriteTiming.FSMC_AccessMode = FSMC_AccessMode_B;
// 选择FSMC映射的存储区域: Bank1 sram1
FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM1;
//设置地址总线与数据总线是否复用,仅用于NOR
FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
//设置要控制的存储器类型:NOR类型
FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_NOR;
//存储器数据宽度:16位
FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
//设置是否使用突发访问模式,仅用于同步类型的存储器
FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode =FSMC_BurstAccessMode_Disable;
//设置是否使能等待信号,仅用于同步类型的存储器
FSMC_NORSRAMInitStructure.FSMC_AsynchronousWait=FSMC_AsynchronousWait_Disable;
//设置等待信号的有效极性,仅用于同步类型的存储器
FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
//设置是否支持把非对齐的突发操作,仅用于同步类型的存储器
FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
//设置等待信号插入的时间,仅用于同步类型的存储器
FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
//存储器写使能
FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
//不使用等待信号
FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
// 不使用扩展模式,读写使用相同的时序
FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
//突发写操作
FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
//读写时序配置
FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &readWriteTiming;
//读写同样时序,使用扩展模式时这个配置才有效
FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &readWriteTiming;
FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure); //初始化FSMC配置
FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM1, ENABLE); // 使能BANK
}
读写数据的函数:
#define ILI9341_CMD_ADDR ((volatile uint16_t *)(0X60000000))
#define ILI9341_DATA_ADDR ((volatile uint16_t *)(0X60020000))
/**
* @brief 向ILI9341写入命令
* @param usCmd :要写入的命令(表寄存器地址)
* @retval 无
*/
__inline void ILI9341_Write_Cmd ( uint16_t usCmd )
{
*ILI9341_CMD_ADDR = usCmd;
}
/**
* @brief 向ILI9341写入数据
* @param usData :要写入的数据
* @retval 无
*/
__inline void ILI9341_Write_Data ( uint16_t usData )
{
*ILI9341_DATA_ADDR = usData;
}
/**
* @brief 从ILI9341读取数据
* @param 无
* @retval 读取到的数据
*/
__inline uint16_t ILI9341_Read_Data ( void )
{
return (*ILI9341_DATA_ADDR);
}
设置背光的函数(起始就是把背光的IO口置成高低电平):
/**
* @brief ILI9341背光LED控制
* @param enumState :决定是否使能背光LED
* 该参数为以下值之一:
* @arg ENABLE :使能背光LED
* @arg DISABLE :禁用背光LED
* @retval 无
*/
void ILI9341_BackLed_Control ( FunctionalState enumState )
{
if ( enumState )
GPIO_ResetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN );
else
GPIO_SetBits ( ILI9341_BK_PORT, ILI9341_BK_PIN );
}
同理,复位函数就是把接复位引脚的IO口置高低电平:
/**
* @brief ILI9341 软件复位
* @param 无
* @retval 无
*/
void ILI9341_Rst ( void )
{
GPIO_ResetBits ( ILI9341_RST_PORT, ILI9341_RST_PIN ); //低电平复位
ILI9341_Delay ( 0xAFF );
GPIO_SetBits ( ILI9341_RST_PORT, ILI9341_RST_PIN );
ILI9341_Delay ( 0xAFF );
}
初始化寄存器:
这其中值得关注的有三个地方,其他的配置不用过于纠结。
设置列的开始和结束坐标(0X2A):

设置行的开始和结束坐标(0X2B):

显存数据写入:

举个例子如下:

整个设置范围到写入数据的流程图如下:

看一下代码中的列设置:
/* column address control set */
ILI9341_Write_Cmd ( CMD_SetCoordinateX );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0xEF );
起始列为0,结束列为00EF,EF转成10进制为239,那么列的范围就是0 ~ 239,共240列。

行设置代码:
/* page address control set */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( CMD_SetCoordinateY );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x01 );
ILI9341_Write_Data ( 0x3F );
起始行为0,结束列为013F,EF转成10进制为319,那么行的范围就是0 ~ 319,共320行。

我们使用的屏幕,就正好是 320行 + 240列。
像素格式设置:
/* Pixel Format Set (3Ah) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0x3a );
ILI9341_Write_Data ( 0x55 );
命令解析:首先发送命令0X3A,这个是用来设置像素格式的(多少位颜色数据),实际上我们希望使用的是RGB565,正好是16位数据对应2字节。对应的正好是0X55。

完整的配置ILI9341寄存器的代码如下:
/**
* @brief 初始化ILI9341寄存器
* @param 无
* @retval 无
*/
static void ILI9341_REG_Config ( void )
{
/* Power control B (CFh) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xCF );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x81 );
ILI9341_Write_Data ( 0x30 );
/* Power on sequence control (EDh) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xED );
ILI9341_Write_Data ( 0x64 );
ILI9341_Write_Data ( 0x03 );
ILI9341_Write_Data ( 0x12 );
ILI9341_Write_Data ( 0x81 );
/* Driver timing control A (E8h) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xE8 );
ILI9341_Write_Data ( 0x85 );
ILI9341_Write_Data ( 0x10 );
ILI9341_Write_Data ( 0x78 );
/* Power control A (CBh) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xCB );
ILI9341_Write_Data ( 0x39 );
ILI9341_Write_Data ( 0x2C );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x34 );
ILI9341_Write_Data ( 0x02 );
/* Pump ratio control (F7h) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xF7 );
ILI9341_Write_Data ( 0x20 );
/* Driver timing control B */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xEA );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x00 );
/* Frame Rate Control (In Normal Mode/Full Colors) (B1h) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xB1 );
ILI9341_Write_Data ( 0x00 );
ILI9341_Write_Data ( 0x1B );
/* Display Function Control (B6h) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xB6 );
ILI9341_Write_Data ( 0x0A );
ILI9341_Write_Data ( 0xA2 );
/* Power Control 1 (C0h) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xC0 );
ILI9341_Write_Data ( 0x35 );
/* Power Control 2 (C1h) */
DEBUG_DELAY ();
ILI9341_Write_Cmd ( 0xC1 );
ILI9341_Write_Data ( 0x11 );
史海拾趣
|
ATM监控专业评标标准!!! 资质审查1. 数字录像设备和微型摄像机同时获得公安部安全防范报警系统产品质量监督检验测试中心出具的型式检验报告。 依据标准: A. 公安部关于贯彻实施《安全技术防范产品管理办法》有关问题的补充通知第二条 B. 《 ...… 查看全部问答> |
|
使用是HHARM2410的开发板。NFS服务器配置操作是正确的,PC与开发板之间相互能ping通,但是开发板正常启动后mount 不了PC机。我已经关了防火墙。我主机IP为192.168.2.222。/etc/exports文件设置的是(rw)。在minnicon里执行mount 192.168.2.222:/ /m ...… 查看全部问答> |
|
如题,本人两个月的经验~~希望对后来者有所帮助 总结STM32的I2C的缺陷与使用.pdf (92.94 KB) 下载次数:672 2010-12-1 08:49 … 查看全部问答> |
|
verilog中,一个always中如果含有好几个case语句,那么这些case语句是并发执行,还是顺序执行呢??如下 always begin case(a) ………… case(b) ………… case(c) ………… end … 查看全部问答> |
|
MSP430G2553串口连接12864显示,只用连接三个引脚,大大节省资源 #include <msp430g2553.h>#define uint unsigned int#define uchar unsigned char#define ulong unsigned longunsigned char a[]={\"波天神终于把12864学会了!\"};#define SID BIT1#define SCLK BIT2#define CS BIT3#define ...… 查看全部问答> |




