In this experiment, we use FSMC to drive LCD. From the previous introduction, we know that the RS of TFTLCD is connected to A6 of FSMC, CS is connected to FSMC_NE4, and it is a 16-bit data bus. That is, we use the 4th area of FSMC memory 1. We define the following LCD operation structure (defined in lcd.h):
//LCD operation structure
typedef struct
{
vu16 LCD_REG;
vu16 LCD_RAM;
} LCD_TypeDef;
//Use NOR/SRAM Bank1.sector4, address bit HADDR[27,26]=11 A6 as the data command distinguishing line
//Note that when the data bus is 16 bits, the internal address of STM32 will be shifted right by one bit to align!
#define LCD_BASE ((u32)(0x6C000000 | 0x0000007E))
#define LCD ((LCD_TypeDef *) LCD_BASE)
LCD_BASE must be determined according to the connection of our external circuit. We use Bank1.sector4, which starts from address 0X6C000000, and 0X0000007E is the offset of A6. Many friends here do not understand the concept of this offset. Here is a brief explanation: Taking A6 as an example, 7E converted into binary is: 1111110, and for 16-bit data, the address is shifted right by one bit to align, so when it actually corresponds to the address pin, it is: A6:A0=0111111, at this time A6 is 0, but if the 16-bit address is added by 1 (note: the corresponding 8-bit address is added by 2, that is, 7E+0X02), then: A6:A0=1000000, at this time A6 is 1, which realizes the control of 0 and 1 of RS.
We force this address to be converted into the LCD_TypeDef structure address, and we can get the address of LCD->LCD_REG is 0X6C00,007E, and the corresponding state of A6 is 0 (ie RS=0), and the address of LCD->LCD_RAM is 0X6C00,0080 (the structure address is incremented), and the corresponding state of A6 is 1 (ie RS=1).
So, with this definition, when we want to write commands/data to the LCD, we can write it like this:
LCD->LCD_REG=CMD; //write command
LCD->LCD_RAM=DATA; //write data
When reading, just do the opposite, as shown below:
CMD= LCD->LCD_REG; //Read LCD register
DATA = LCD->LCD_RAM; //Read LCD data
Among them, CS, WR, RD and IO port direction are all controlled by FSMC, and we don't need to set them manually. Next, let's introduce another important structure in lcd.h:
//LCD important parameter set
typedef struct
{
u16 width; //LCD width
u16 height; //LCD height
u16 id; //LCD ID
u8 dir; //Horizontal or vertical screen control: 0, vertical screen; 1, horizontal screen.
u16 wramcmd; //Start writing gram command
u16 setxcmd; //Set x coordinate command
u16 setycmd; //Set y coordinate command
}_lcd_dev;
//LCD parameters
extern _lcd_dev lcddev; //Manage important LCD parameters
This structure is used to save some important LCD parameter information, such as the length and width of the LCD, LCD ID (driver IC model), LCD horizontal and vertical screen status, etc. Although this structure occupies more than a dozen bytes of memory, it allows our driver function to support LCDs of different sizes and realize important functions such as LCD horizontal and vertical screen switching, so the advantages outweigh the disadvantages. With the above understanding, let's start to introduce some important functions in lcd.c.
Let's first look at 7 simple but important functions:
//Write register function
//regval: register value
void LCD_WR_REG(vu16 regval)
{ regval=regval; //When using -O2 optimization, the delay must be inserted
LCD->LCD_REG=regval; //Write the register number to be written
}
//Write LCD data
//data: the value to be written
void LCD_WR_DATA(vu16 data)
{ data=data; //When using -O2 optimization, the delay must be inserted
LCD->LCD_RAM=data;
}
//Read LCD data
//Return value: the value read
u16 LCD_RD_DATA(void)
{ vu16 ram; //Prevent optimization
ram=LCD->LCD_RAM;
return ram;
}
//Write register
//LCD_Reg: register address
//LCD_RegValue: data to be written
void LCD_WriteReg(vu16 LCD_Reg, vu16 LCD_RegValue)
{ LCD->LCD_REG = LCD_Reg; //Write the register number to be written
LCD->LCD_RAM = LCD_RegValue; //Write data
}
//Read register
//LCD_Reg: register address
//Return value: the data read
u16 LCD_ReadReg(vu16 LCD_Reg)
{ LCD_WR_REG(LCD_Reg); //Write the register number to be read
delay_us(5);
return LCD_RD_DATA(); //Return the read value
}
//Start writing GRAM
void LCD_WriteRAM_Prepare(void)
{ LCD->LCD_REG=lcddev.wramcmd;
}
//LCD write GRAM
//RGB_Code: color value
void LCD_WriteRAM(u16 RGB_Code)
{ LCD->LCD_RAM = RGB_Code; //Write 16-bit GRAM
}
Because FSMC automatically controls the WR/RD/CS signals, these 7 functions are very simple to implement, so we won't say much. Note that we have added some support for MDK -O2 optimization in the above functions. If we remove them, there will be problems during -O2 optimization. The functions of these functions are shown in the notes in front of the functions. Through the combination of these simple functions, we can perform various operations on the LCD.
Previous article:STM32f4---TFTLCD display experimental code (02)
Next article:STM32f4---OLCD display experimental code (04)
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- From probes to power supplies, Tektronix is leading the way in comprehensive innovation in power electronics testing
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
- Why signal isolation is important in 48V HEV/EV systems
- [Dialogue with forum members] Fake goods: I didn’t expect that inductors could also be fake + the FPGA I just bought has a problem with random inspection
- IIC Timing Diagram
- Please recommend a 5V to positive and negative 15V op amp power supply circuit or chip to share
- Lock-in Amplifier Design
- EEWORLD University ----RISC-V 5th workshop
- What is transparent transmission and point-to-multipoint transmission? What are their classic applications and advantages?
- How to build an undervoltage protection circuit using discrete components
- [Mill MYB-YT507 development board trial experience] + some problems in the compilation experience
- How to configure the pins used by LCD as GPIO?