模拟8080时序,IO口配置为推挽输出模式
写时序
引脚说明
cs:片选线,低电平有效
res:复位线,一般与开发板复位按键相连,或者连接任意引脚
d/c:数据命令控制线 命令(0) 数据(1)
wr:写时钟线,从机在wr上升沿读走数据
rd:读时钟线,在写操作时,rd一直置高电平
dx:数据线:在wr上升沿之前把数据放好
写数据代码
//宏定义部分,使代码更容易理解
#define LCD_CS_LOW() HAL_GPIO_WritePin(LCD_cs_GPIO_Port,LCD_cs_Pin,GPIO_PIN_RESET)
#define LCD_CS_HIGH() HAL_GPIO_WritePin(LCD_cs_GPIO_Port,LCD_cs_Pin,GPIO_PIN_SET)
#define LCD_COMMAND() HAL_GPIO_WritePin(LCD_dc_GPIO_Port,LCD_dc_Pin,GPIO_PIN_RESET)
#define LCD_DATA() HAL_GPIO_WritePin(LCD_dc_GPIO_Port,LCD_dc_Pin,GPIO_PIN_SET)
#define LCD_R_DATA_ENABLE() HAL_GPIO_WritePin(LCD_read_GPIO_Port,LCD_read_Pin,GPIO_PIN_RESET)
#define LCD_R_DATA_DISABLE() HAL_GPIO_WritePin(LCD_read_GPIO_Port,LCD_read_Pin,GPIO_PIN_SET)
#define LCD_W_DATA_ENABLE() HAL_GPIO_WritePin(LCD_write_GPIO_Port,LCD_write_Pin,GPIO_PIN_RESET)
#define LCD_W_DATA_DISABLE() HAL_GPIO_WritePin(LCD_write_GPIO_Port,LCD_write_Pin,GPIO_PIN_SET)
void lcd_write_data(uint16_t data)
{
LCD_CS_LOW(); //拉低片选
LCD_DATA(); //dc数据命令控制线拉高,表示操作数据
LCD_R_DATA_DISABLE(); //rd读数据线失能
DATAOUT(data); //写时钟上升沿前放置数据
LCD_W_DATA_ENABLE(); //写使能 (拉低写时钟,制造上升沿开始)
LCD_W_DATA_DISABLE(); //写失能(拉高写时钟,制造上升沿完成)
LCD_CS_HIGH(); //拉高片选
}
写命令代码
void lcd_write_command(uint16_t command)
{
LCD_CS_LOW(); //拉低片选
LCD_COMMAND(); //dc数据命令线拉低,选择发送数据为命令
LCD_R_DATA_DISABLE(); //读时钟线失能
DATAOUT(command); //在写时钟上升沿之前放置命令数据
LCD_W_DATA_ENABLE(); //写时钟使能(拉低写时钟制造上升沿开始)
LCD_W_DATA_DISABLE(); //写时钟失能(拉高写时钟制造上升沿完成)
LCD_CS_HIGH(); //拉高片选
}
读时序
引脚说明
cs:片选线,低电平有效
res:复位线,一般与开发板复位按键相连,或者连接任意引脚
d/c:数据命令控制线 命令(0) 数据(1)
wr:写时钟线,读数据时不写拉高失能
rd:读时钟线,rd时钟线上升沿读数据
dx:数据线被从机控制
读数据代码
uint16_t lcd_read_data(void)
{
uint16_t data=0;
LCD_IN_out(GPIO_MODE_INPUT); //切换IO口状态
LCD_CS_LOW(); //拉低片选
LCD_DATA(); //DC数据命令控制线拉高,表示操作数据
LCD_W_DATA_DISABLE(); //写时钟失能
LCD_R_DATA_ENABLE(); //读时钟使能
data=DATAIN(); //读取数据
LCD_R_DATA_DISABLE(); //读时钟失能
LCD_CS_HIGH(); //拉高片选
LCD_IN_out(GPIO_MODE_OUTPUT_PP); //恢复io口状态
return data;
}
被调用函数实现
DATAOUT()
在写时钟上升沿之前完成DATAOUT()操作,把要写的数据放到io上
依次读引脚电平,拼成16位数据
void DATAOUT(uint16_t x)
{
HAL_GPIO_WritePin(D0_GPIO_Port,D0_Pin,x>>0&0x0001);
HAL_GPIO_WritePin(D1_GPIO_Port,D1_Pin,x>>1&0x0001);
HAL_GPIO_WritePin(D2_GPIO_Port,D2_Pin,x>>2&0x0001);
HAL_GPIO_WritePin(D3_GPIO_Port,D3_Pin,x>>3&0x0001);
HAL_GPIO_WritePin(D4_GPIO_Port,D4_Pin,x>>4&0x0001);
HAL_GPIO_WritePin(D5_GPIO_Port,D5_Pin,x>>5&0x0001);
HAL_GPIO_WritePin(D6_GPIO_Port,D6_Pin,x>>6&0x0001);
HAL_GPIO_WritePin(D7_GPIO_Port,D7_Pin,x>>7&0x0001);
HAL_GPIO_WritePin(D8_GPIO_Port,D8_Pin,x>>8&0x0001);
HAL_GPIO_WritePin(D9_GPIO_Port,D9_Pin,x>>9&0x0001);
HAL_GPIO_WritePin(D10_GPIO_Port,D10_Pin,x>>10&0x0001);
HAL_GPIO_WritePin(D11_GPIO_Port,D11_Pin,x>>11&0x0001);
HAL_GPIO_WritePin(D12_GPIO_Port,D12_Pin,x>>12&0x0001);
HAL_GPIO_WritePin(D13_GPIO_Port,D13_Pin,x>>13&0x0001);
HAL_GPIO_WritePin(D14_GPIO_Port,D14_Pin,x>>14&0x0001);
HAL_GPIO_WritePin(D15_GPIO_Port,D15_Pin,x>>15&0x0001);
}
DATAIN()
在读操作时,数据线由从机控制,所以此操作必须放在读时钟线拉低拉高之间。
DATAIN()实现
uint16_t DATAIN()
{
uint16_t data = 0;
data |= HAL_GPIO_ReadPin(D15_GPIO_Port,D15_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D14_GPIO_Port,D14_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D13_GPIO_Port,D13_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D12_GPIO_Port,D12_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D11_GPIO_Port,D11_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D10_GPIO_Port,D10_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D9_GPIO_Port,D9_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D8_GPIO_Port,D8_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D7_GPIO_Port,D7_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D6_GPIO_Port,D6_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D5_GPIO_Port,D5_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D4_GPIO_Port,D4_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D3_GPIO_Port,D3_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D2_GPIO_Port,D2_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D1_GPIO_Port,D1_Pin);data <<= 1;
data |= HAL_GPIO_ReadPin(D0_GPIO_Port,D0_Pin);
return data;
}
IO口 状态切换
static void LCD_DATA_CHANGE_MOD(GPIO_TypeDef *GPIOx,uint32_t PIN,uint32_t mod)
{
GPIO_InitTypeDef gpio;
gpio.Mode=mod;
gpio.Pull=GPIO_NOPULL;
gpio.Speed=GPIO_SPEED_FREQ_HIGH;
gpio.Pin=PIN;
HAL_GPIO_Init(GPIOx,&gpio);
}
//mod为io口模式
static void LCD_IN_out(uint32_t mod)
{
LCD_DATA_CHANGE_MOD(D0_GPIO_Port,D0_Pin,mod);
LCD_DATA_CHANGE_MOD(D1_GPIO_Port,D1_Pin,mod);
LCD_DATA_CHANGE_MOD(D2_GPIO_Port,D2_Pin,mod);
LCD_DATA_CHANGE_MOD(D3_GPIO_Port,D3_Pin,mod);
LCD_DATA_CHANGE_MOD(D4_GPIO_Port,D4_Pin,mod);
LCD_DATA_CHANGE_MOD(D5_GPIO_Port,D5_Pin,mod);
LCD_DATA_CHANGE_MOD(D6_GPIO_Port,D6_Pin,mod);
LCD_DATA_CHANGE_MOD(D7_GPIO_Port,D7_Pin,mod);
LCD_DATA_CHANGE_MOD(D8_GPIO_Port,D8_Pin,mod);
LCD_DATA_CHANGE_MOD(D9_GPIO_Port,D9_Pin,mod);
LCD_DATA_CHANGE_MOD(D10_GPIO_Port,D10_Pin,mod);
LCD_DATA_CHANGE_MOD(D11_GPIO_Port,D11_Pin,mod);
LCD_DATA_CHANGE_MOD(D12_GPIO_Port,D12_Pin,mod);
LCD_DATA_CHANGE_MOD(D13_GPIO_Port,D13_Pin,mod);
LCD_DATA_CHANGE_MOD(D14_GPIO_Port,D14_Pin,mod);
LCD_DATA_CHANGE_MOD(D15_GPIO_Port,D15_Pin,mod);
}
测试
实现一个读取ID的函数,若ID号为9341,则时序正确
uint16_t ILI9341_Read_ID(void)
{
uint16_t id = 0;
lcd_write_command(0xD3);
lcd_read_data();
lcd_read_data();
id = lcd_read_data();
id<<=8;
id|=lcd_read_data();
return id;
}
调用该函数,如输出9341,时序配置完成