Re-learning STM32---(vii) FSMC+LCD

Source: Internet
Author: User

About FSMC+LCD the first time after the study, he is still on this not clear, sometimes clear, sometimes confused. This time to learn again, can not in this, carefully STM32 reference manual, atomic LCD experiment looked over, and on the internet to find a lot of information about FSMC+LCD, finally thoroughly understand,,, of course, Call me completely a person independent of this LCD display experiment program written out or not, C language still need to improve, actual combat or too little, see someone else write code, some details at all not unexpectedly, let alone to write ....

  

Information collected:

The LCD has the following control lines:

Cs:chip Select Blade selectable, low active

Rs:register Select Register Selection

Wr:write write signal, low active

Rd:read read signal, low active

Reset: Restart signal, low active

DB0-DB15: Data Cable

If these lines, all with ordinary IO port control. According to the LCD control chip manual (most of the control chip timing is similar):

If the situation is as follows:

The Db0-db15 io is all 1 (for data 0xff), or any other value, where 0xFF is the example.

CS is 0 (indicates the chip is selected, when CS pulls low, the chip will be valid for incoming data)

RS is 1 (indicating that the value passed on the db0-15 is to be written to the register), and if 0, indicates that the data is passed.

WR is 0,rd 1 (denoted by write action), which in turn is read action.

Reset is always high and if reset is low, it causes the chip to restart.

In this case, a value of 0xFF will be passed into the chip, the LCD control chip as the write register value to parse. After the LCD control chip receives the value on the db0-15, according to other control lines, it concludes that the 0xFF is used to set the register. In general, the LCD control chip will be the incoming register value of the high 8 bits as the register address (because there is certainly more than one register inside the chip), low 8 bits as the real to be assigned to the corresponding register value. This completes the timing of writing an internal register of the LCD control chip.

If the above condition is not changed, only the RS is lowered, then the situation is as follows: The LCD control chip will treat the data on the db0-15 as a simple data value. Then if the LCD in the drawing state, this incoming value of 0xFF, will be displayed to the corresponding point, 0xFFFF represents white, then the corresponding point is white. Before this data value is passed, the program will definitely pass the register value to tell the LCD where the point where the chip is to be written.

If both of the above conditions are unchanged, the signals of WR and RD are reversed (wr=1,rd=0), then the write signal is turned into a read signal. Read the signal, the master chip needs to read the value of db0-15, and the LCD control chip will set the value of db0-15, so as to complete the reading data timing.

The timing of the read register is a bit cumbersome. In the first step, both WR and Rd are lowered, and the master chip passes through the DB0-15 to the register address. The second step is the same as the previous reading data, the WR is high, RD low, read out the value of db0-15. In this whole process, RS has been low.

Well, the above is the IO Direct control LCD method. If put in the STM32 inside, with the direct control of IO appears inefficient. STM32 have FSMC (in fact, other chips basically have similar bus function), FSMC the advantage is that once you set up, WR, RD, db0-db15 These control lines and data lines, are FSMC automatic control. For example, when you write in a program:

* (volatile unsigned short int *) (0x60000000) =val;

Then FSMC will automatically perform a write operation, the corresponding master chip of the We, RD these feet, will present a write time out (ie, we=0,rd=1), the value of the data Val will be automatically presented through the db0-15 (that is, fsmc-d0:fsmc-d15=val). Address 0x60000000 will be presented on the data line (that is, a0-a25=0, address line correspondence is the most troublesome, according to the specific situation, take a good look at FSMC manual).

So on the hardware, what we need to do is just the connection between the MCU and the LCD control chip:

WE-WR, all low-level active

RD-RD, all low-level active

FSMC-D0-15 Connector LCD db0-15

Once connected, the read-write sequence is automatically completed by FSMC. But there is also a very important problem, that is, RS did not answer, CS did not answer. Because in the FSMC, there is no corresponding to the RS and CS feet. What do we do? At this time, there is a good way to use a certain address line to pick up the Rs. For example, we chose the A16 address line to pick up, so when we want to write registers, we need RS, that is, A16 high. How do you do it in software? That is to change the address FSMC to write to 0x60020000, as follows:

* (volatile unsigned short int *) (0x60020000) =val;

At this time, A16 will be pulled higher while performing other FSMC, because A0-a18 will show the address 0x60020000. 0x60020000 inside the bit17=1, will cause A16 to 1.

When you want to read the data, the address changed from 0x60020000 to 0x60000000, this time A16 is 0.

Then there are friends will have doubts, first, why the address is 0x6xxxxxxx and not 0x0xxxxxxx; second, CS How to answer, third, why Bit17 corresponds to A16?

First two questions, we find STM32 FSMC manual, in FSMC Manual, we are easy to find, FSMC will 0x60000000-0x6fffffff address as Nor/pram (a total of 256M address range). And this storage block, is divided into four parts, each part of the 64M address range. When one of the blocks is read and written, the corresponding NEX is lowered. Here, it solves our two problems, first, the LCD operation timing, and Nor/pram is the same (why do you look for the Nor/pram time series to see), so we choose to 0x6xxxxxxx this address range (Select this address range, the operation of this address, The FSMC will show the Nor/pram timing). Second, we can connect the NEX to the LCD CS, as long as the address we operate is within the first memory block (that is, the 0-0X3FFFFFF address range).

The third question to take a look at the FSMC manual about the memory word width, we found that when the external memory is 16 bits, the hardware pin A0-a24 represents the value of the address line a1-a25, so we have to shift a bit, Bit17 value, will actually be reflected to A16 this IO. Regarding the data width and the displacement question, the beginner's friend may be more puzzled, when you touch the device such as multi-nor/pram, you will find that many chips of the bus, are designed in order to save the address line

The second angle of understanding:

On the FSMC bus, the LCD has only 2 addresses.

Bank1_lcd_c is write register, at this time Rs=1, tell LCD i output data on the bus is the address of the Register

Bank1_lcd_d is write data, at this time rs=0, tell LCD i output data on the bus is register data or gram data.

Write the register data by 2 steps:

First step to Bank1_lcd_c (corresponding to Rs=1), the address of the Sending register: * (__io uint16_t *) (Bank1_lcd_c) = index; Then at Bank1_lcd_d this address (corresponding to rs=0), write the data of the register just pointing to: * (__io uint16_t *) (bank1_lcd_d) = Val;

Why * (__io uint16_t *) (Bank1_lcd_c) = index; is to write registers to the LCD?

This is a 16-bit IO assignment operation, the address is Bank1_lcd_c, this address is the NE1 corresponding address space to the Bank1 of FSMC. and LCD chip selection is connected to the NE1, the specific address to see the RS to which the address line. When the CPU executes to this one, it will use the FSMC Bus controller on the data bus address is a Bank1_lcd_c write operation, this operation automatically completes the CS signal,

RD signal, WR signal, and output of the address bus data (RS signal) as well as data from the bus.

The other operations are the combination of these two operations. That's what I said above,

"All register address and register data, as well as gram data, are transmitted through IO0-IO15, not FSMC addresses. This is a very easy place to mix. The LCD has only one FSMC address, which is Rs."

The TFT is regarded as SRAM-like memory and can only be connected to the BANK1. The corresponding base address is 0x60000000.

And BANK1 is divided into four slices, respectively, corresponding to the base address:

NE1 0x600000000

NE2 0x640000000

NE3 0x680000000

NE4 0x6c0000000

So each NEX can address a space size of 64M, which corresponds to the FSMC A0 to A25 a total of 26 address lines.

If the use of NE4 received for the LCD chip selected CS, then corresponding to the base site 0x6c000000,

If RS is connected to the A0 of the address line, then when RS is 0 o'clock the corresponding address is Lcd_reg = 0x6c000000, (in fact you use 0X6CFFFFF0 is the same, because only one address line).

RS 1 o'clock corresponds to the address is Lcd_ram =0x6c000001, (0x6cfffff1 as corresponding to Lcd_ram, because it corresponds to Rs=1).

If RS is connected to another address line, the situation is similar.

For example, if you receive an on,

Lcd_reg= 0x6c000000,

lcd_ram= 0x6c000000 | (1<<n)

Note that this address is not unique, as long as the address can be addressed to BANK1 NE4 and make rs=0, then Lcd_reg, so Rs=1, is lcd_ram.

corresponding to the address of the Bank1_lcd_c, the FSMC Bus Controller at Rs the address line of the output is 1, and corresponding to the bank1_lcd_d, the output of 0.

RS is not a gpio, it is a FSMC address bus. The FSMC reads and writes the output level at the address bus according to the address to read and write.

There is no fixed requirement for the address line at RS, but once you're sure which one to pick up, Bank_lcd_c and Bank_lcd_d will have to be sure, which is not "automatic."

Although there is no manual operation of the Gpio to operate RS, you can manually specify the Bank1_lcd_c or Bank1_lcd_d when you tap the code to determine the level of the Rs.

The so-called "automatic" refers to: not by operating the Gpio to operate RS, but directly according to the address bus address of the different to complete the operation of RS, the two methods of speed difference is very large.

In the case of Gpio, you first have to output RS,CS, etc. by operating the GPIO, and then output the data through the Gpio operation, and then use the Gpio to operate the Rd,wr,cs level.

Each GPIO operation takes several cycles and adds up very slowly.

And FSMC is doing all this in a FSMC write cycle.

Question: How RS chooses:

#define BANK1_LCD_R ((uint32_t) 0x60000000)//disp Reg ADDR

#define BANK1_LCD_D ((uint32_t) 0x60020000)//disp Data ADDR

Here the LCD selected 16 bits, the RS is connected to A16, then haddr[25:1] corresponds to fsmc_a[24:0]; The key is why???

As can be seen from the above, the LCD in addition to the data cable, the additional address line is not required ~~~~~ but in STM32 in the FSMC bus operation, all the address lines will still appear timing, but the LCD does not need additional address line, that is fsmc_a[16:25] Can be liberated, but note that once the FSMC is configured, the pins will still appear in sequential order;

Now we send data to 0x60000000 this block address, of course, this data is certainly 16 bits, because it is 16-bit LCD, because RS (A16) is 0, so the operation of this read-write register, when writing data to 0x60020000, because the bus timing is to have address write, At this time bit17 is high, that is, RS is 1, then the operation is to read and write RAM!!!!

Where the choice of Rs can be arbitrary, but generally still choose, not the address line for good ~~~~~

Program: (Only FSMC initialization)

void Lcd_init ()
{
Rcc->ahbenr |= 1 << 8; Turn on the FSMC clock
Rcc->apb2enr |=1 << 3 | 1 << 5 | 1 << 6 | 1 << 8; Turn on the b,d,e,g clock
Rcc->apb2enr |= 1 << 0; Open Afio

GPIOB-&GT;CRL &= 0xfffffff0;
GPIOB-&GT;CRL |= 0x00000003; GPIOB0 Push-Pull output

GPIOD-&GT;CRL &= 0xff00ff00;
GPIOD-&GT;CRL |= 0X00BB00BB; Setting 0,1,4,5 for multiplexed push-pull output
GPIOD-&GT;CRH &= 0x00fff000;
GPIOD-&GT;CRH |= 0xbb000bbb; Set 8,9,10,14,15 to push-pull output

GPIOE-&GT;CRL &= 0x0fffffff;
GPIOE-&GT;CRL |= 0xb0000000; It's all multiplexed push-pull output.
GPIOE-&GT;CRH &= 0x00000000;
GPIOE-&GT;CRH |= 0xbbbbbbbb; //

GPIOG-&GT;CRL &= 0xfffffff0;
GPIOG-&GT;CRL |= 0x0000000b;
GPIOG-&GT;CRH &= 0xfff0ffff;
GPIOG-&GT;CRH |= 0x000b0000;

FSMC_BANK1-&GT;BTCR[6] &= 0x00000000;
FSMC_BANK1-&GT;BTCR[6] |= 1 << 14| 1 << 12 | 0x01 << 4 | 0x00 << 2 | 1 << 0; BCR4 Extended mode, write enable, 16-bit, SRAM, memory block enable

FSMC_BANK1-&GT;BTCR[7] &= 0x00000000;
FSMC_BANK1-&GT;BTCR[7] |= 0x00 << 28 | 0x0000 << 20 | 0x0f << 8 | 0x01 Mode A, no crossover,16HCLK Read data settling time, 1HCLK address settling time

FSMC_BANK1E-&GT;BWTR[6] &= 0x00000000; (about this clock setting I didn't find)
FSMC_BANK1E-&GT;BWTR[6] |= 0x00 << 28 | 0x0000 << 20 | 0x03 << 8 | 0x00;//mode A, no crossover,3HCLK Write Data settling time, 0HCLK address settling time

Then read out their ID number, according to their own LCD driver ID number to select the LCD initialization sequence, do not need to write their own

}

The rest is based on the LCD manual to read and write, the commonly used commands are several

Write Register function
Regval: Register Value
void Lcd_wr_reg (U16 regval)
{
lcd->lcd_reg=regval;//Write the register number to write
}
Write LCD data
Data: The value to write
void Lcd_wr_data (U16 DATA)
{
lcd->lcd_ram=data;
}
Read LCD data
Return value: The value read
U16 Lcd_rd_data (void)
{
VU16 ram;//Prevention is optimized
ram=lcd->lcd_ram;
return RAM;
}
Write register
Lcd_reg: Register Address
Lcd_regvalue: Data to write
void Lcd_writereg (U16 lcd_reg,u16 Lcd_regvalue)
{
Lcd->lcd_reg = lcd_reg;//Writes the register number to write
Lcd->lcd_ram = lcd_regvalue;//Write Data
}
Read Register
Lcd_reg: Register Address
Return value: The data read
U16 Lcd_readreg (U16 Lcd_reg)
{
Lcd_wr_reg (Lcd_reg);//write the register number to read
Delay_us (5);
return Lcd_rd_data ();//Returns the value read
}

typedef struct
{
Vu16 Lcd_reg; Write commands
Vu16 Lcd_ram; Write Data

}lcd_type;

#define LCD_BASE (unsigned int) (0x60000000 + 0x0c000000 + 0x000007fe) //This bracket must be hit, otherwise there will be a hardware error (it took me a few hours, I did not expect the error here)
#define LCD ((lcd_type*) lcd_base)

This is the most critical, as long as the dragon understand, it feels that LCD display is not very difficult, mainly drawing a shape with C language difficult to write, display strings, and so on, these are to see how C language learning,,,

Re-learning STM32---(vii) FSMC+LCD

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.