Connecting a color LCD with a touch screen to the microcontroller

    Good afternoon, habr. Today I would like to share some experience regarding the connection of color LCD-indicators to the microcontroller. This topic has already been raised on the hub ( http://habrahabr.ru/post/139384/ ), so this post can be considered as an addition to the one already written by my esteemed colleagues.


    In the post referenced at the beginning, LCD indicators connected via the SPI interface are discussed. This connection method is simple, but not the only one. Many indicators have “on board” only a simplified controller that does not have memory for storing the image, and therefore requires continuous updating of the image. Such indicators are used everywhere in electronic gadgets, and for their functioning a special LCD controller is needed, which is built into the microcontroller. An example of such an indicator is MI0350CT-3 manufactured by Multi-Inno Technology. This is a fairly typical representative of color LCDs, having a resolution of 320 * 240 and a resistive sensor.
    So, we have some problem. Let each pixel be represented in memory by a 32-bit value (only 24 of them are used, but the data is aligned on 4-byte boundaries). In total, under one video page we need 320 * 240 * 4 = 307200 bytes = 300 KB of RAM. Not every microcontroller has such an amount of memory. Therefore, as a rule, an external memory is required for the LCD to work, and therefore an external memory controller on a microcontroller chip.
    In fairness, it should be noted that the requirements for memory size can be reduced if you use not 24-bit per pixel, but a smaller color depth, but, on the other hand, we may want to place several video pages in the system memory in order to be able to quickly switch between them . We will return to this topic later.
    As an example, consider connecting an LCD to an LPC2478 microcontroller. This is a slightly outdated representative of the NXP microcontrollers (on the ARM7 core, and not on the modern Cortex M3), but for our purposes this is not essential. This microcontroller contains everything you need: an external memory controller (with the ability to connect both SRAM and SDRAM), and an LCD controller with the possibility of very flexible settings.
    For experiments, I used the SK-MLPC2478 board, which, in addition to the LPC2478 microcontroller, has a K6R4008V1D-TI10 static memory chip (CMOS SRAM) with a capacity of 512Kx8 bit. The aforementioned MI0350CT-3 indicator is connected to the board.
    There is another pitfall: this indicator requires a source with an output current of 20 mA at a voltage of about 20 V. ma If the load is not connected, then the converter operates in the mode of stabilization of the output voltage (U o = 20 V). The converter circuit is shown in Fig. 1. The principle of operation and calculation of the boost converter will not be considered here, those interested in this topic can refer to the documentation for the MC34063A chip.



    Fig. 1. The voltage converter.

    Let us briefly consider the connection and operation of this type of LCD. The LCD uses 24 signals for color information, a CLK signal for pixel synchronization, HSINK and VSINC signals for horizontal and vertical pulses. In addition, the indicator has an SPI interface for setting auxiliary registers, a #RESET signal and a DEN (data enable) signal. The SPI interface in this case is not intended to transmit an image to the display controller, but to configure auxiliary registers. These registers allow you to select the mode of operation of the indicator, adjust the brightness, contrast and other parameters. However, the indicator control registers are set to the desired state by default, and if we are not going to change them, the SPI signals can simply be ignored. The #RESET signal can simply be set to inactive (single) state.
    So, the main signals necessary for this type of indicator to work are: data signals that carry information about the current pixel color in RGB format, CLK clock signal, vertical and horizontal synchronization signals, and also a data resolution signal. Consider the timing charts.



    Fig. 2. Timing diagram of data transmission in LCD.

    In fig. 2 shows the most “large-scale” data transfer timing diagram depicting data transmission of one image line. Transmission occurs on the edge of the CLK signal, and is accompanied by a high DEN data resolution signal. The transmission takes place in RGB format, while the Data0 - Data7 bits correspond to blue, Data8 - Data15 bits to green, Data16-Data23 to red.
    Before transmitting the string data and after transmitting the data, “empty”, non-information-carrying pulses CLK are inserted. The line feed is preceded by a horizontal synchronization pulse HSYNC (LCD_LP).
    The clock frequency of the indicator is 6.4 MHz (it can be reduced, but then the flicker of the frames becomes noticeable).



    Fig. 3. Timing diagram of frame transmission in LCD The

    timing diagram of transmission of a full frame in LCD is shown in Fig. 3. The transmission of the frame begins with 13 “empty” lines, then 240 lines with the image, followed by “empty” lines again. Frame transmission begins with a vertical sync pulse.
    We also connect a resistive sensor to the microcontroller. A description of this connection will be given below.
    I will not give a complete diagram of connecting the indicator to the microcontroller, due to its obviousness, I will only give a table of correspondence between the indicator pins and the controller pins.

    Table 1. Correspondence of LCD signals and controller outputs

    SignalSK-MLPC2478 (connector X6)LCD pinMicrocontroller portNote
    GND153, 54land
    + 5V2-not used
    DATA6318data
    +3.3 V441, 42nutrition
    LCD CLK IN5-not used
    DATA 7619data
    DATA 19731data
    DATA 188thirtydata
    DATA 22934data
    DATA 231035data
    DATA 20eleven32data
    DATA 211233data
    DATA 14thirteen26data
    DATA 151427data
    DATA 12fifteen24data
    DATA 131625data
    DATA 111723data
    DATA 101822data
    DATA 119thirteendata
    DATA 02012data
    DATA 92121data
    DATA 82220data
    DATA 172329thdata
    DATA 162428data
    LCD LE25-not used
    LCD PWR26-not used
    LCD FP2737Vertical sync
    LCD CLK2838Indicator Clocking
    LCD LP29th36Horizontal sync
    LCD ENABthirty52Data resolution
    DATA 53117data
    DATA 43216data
    DATA 333fifteendata
    DATA 23414data
    SPENA3543P0.20SPI interface, serial port data enable
    -36-Not used
    #RESET376P0.19discharge
    -38-Not used
    SPCK3949P0.17SPI interface, serial port clock
    SPDA40fiftyP0.18SPI interface, serial data
    YuConnector X7.158AD0 / P0.23Resistive Sensor
    XrConnector X7.139AD1 / P0.24Resistive Sensor
    YdConnector X7.1010P0.26Resistive Sensor
    XLConnector X7.12elevenP0.25Resistive Sensor

    We assemble the device layout (Fig. 4-6):



    Fig. 4. Board layout device



    Fig. 5. The device layout (partially assembled)



    Fig. 6. The layout of the device assembly

    Now that everything is connected, you can start writing code. The first thing to do is configure and test external SRAM memory:

    // Init SDRAM controller
      // Enable EMC clock
      PCONP_bit.PCEMC    = 1;
      EMCSTATICWAITRD0   = 0x00000001;
      EMCSTATICWAITPG0   = 0x00000000;
      EMCSTATICWAITWR0   = 0x00000000;
      EMCSTATICWAITTURN0 = 0x00000000;
      EMCCONTROL      = 1;         // enable EMC
    

    SRAM test:
    char SRAM_Test(void)
    {
    // 32 bits access
      for (Int32U i = 0; i < 0x80000; i+=sizeof(Int32U))
      {
        *(Int32U*)(((Int32U)SRAM_BASE_ADDR)+i) = i;
      }
      for (Int32U i = 0; i < 0x80000; i+=sizeof(Int32U))
      {
        if (*(Int32U*)(((Int32U)SRAM_BASE_ADDR)+i) != i)
        {
          printf("Verification error on address : 0x%x\n",(Int32U)SRAM_BASE_ADDR+i);
          return(FALSE);
        }
      }
      return TRUE;
    }
    

    It should be understood that the performance of external memory is an important factor. In fact, the data stream in our case is Fclk * N, where Fclk is the clock frequency of the indicator, N is the number of bytes in memory allocated for 1 pixel. Total we get 6.4 * 10 ^ 6 * 4 = 25.6 MB / s. For memory with an 8-bit interface, this means a maximum allowable access time of 39 ns. Memory performance requirements can be reduced by using memory with a 16 or 32-bit interface and / or reducing the color depth used.
    We configure the LCD in, setting the signal duration in accordance with the indicator documentation:
    // Init GLCD cotroller
      PCONP_bit.PCLCD = 1;      // enable LCD controller clock
      CRSR_CTRL_bit.CrsrOn = 0; // Disable cursor
      LCD_CTRL_bit.LcdEn = 0;   // disable GLCD controller
      LCD_CTRL_bit.LcdBpp= 5;  //2bpp // 24 bpp
      LCD_CTRL_bit.LcdTFT= 1;   // TFT panel
      LCD_CTRL_bit.LcdDual=0;   // single panel
      LCD_CTRL_bit.BGR   = 0;   // normal output
      LCD_CTRL_bit.BEBO  = 0;   // little endian byte order
      LCD_CTRL_bit.BEPO  = 0;   // little endian pix order
      LCD_CTRL_bit.LcdPwr= 0;   // disable power
      // init pixel clock
      LCD_CFG_bit.CLKDIV = SYS_GetFsclk() / (Int32U)C_GLCD_PIX_CLK;
      LCD_POL_bit.BCD    = 1;   // bypass inrenal clk divider
      LCD_POL_bit.CLKSEL = 0;   // clock source for the LCD block is HCLK
      LCD_POL_bit.IVS    = 1;   // LCDFP pin is active LOW and inactive HIGH
      LCD_POL_bit.IHS    = 1;   // LCDLP pin is active LOW and inactive HIGH
     // LCD_POL_bit.IPC    = 1;   // data is driven out into the LCD on the falling edge
      LCD_POL_bit.IPC    = 0;   // data is driven out into the LCD on the rising edge
      LCD_POL_bit.PCD_HI = 0;  //  //
      LCD_POL_bit.PCD_LO = 0;  //
      LCD_POL_bit.IOE    = 0;   // active high
      LCD_POL_bit.CPL    = C_GLCD_H_SIZE-1;
      // init Horizontal Timing
      LCD_TIMH_bit.HBP   =  C_GLCD_H_BACK_PORCH - 1;
      LCD_TIMH_bit.HFP   =  C_GLCD_H_FRONT_PORCH - 1;
      LCD_TIMH_bit.HSW   =  C_GLCD_H_PULSE - 1;
      LCD_TIMH_bit.PPL   = (C_GLCD_H_SIZE/16) - 1;
      // init Vertical Timing
      LCD_TIMV_bit.VBP   =  C_GLCD_V_BACK_PORCH;
      LCD_TIMV_bit.VFP   =  C_GLCD_V_FRONT_PORCH;
      LCD_TIMV_bit.VSW   =  C_GLCD_V_PULSE;
      LCD_TIMV_bit.LPP   =  C_GLCD_V_SIZE - 1;
      // Frame Base Address doubleword aligned
      LCD_UPBASE         =  (Int32U)GetVramAddr()  & ~7UL;
    

    Now we write a test picture in ROM and copy it to RAM:



    Fig. 7. Test picture. The picture is

    written as an unsigned int [240] [320] array and copied to the base address of the external memory (0x80000000).
    The operation of the LCD support mechanism built into the microcontroller consists in the fact that the data is read from the RAM by the DMA controller and fed to the LCD controller, where the cursor image is superimposed and the data is fed to the LCD input. Also, the LCD controller can provide palette support for modes from 1 to 8 bits per pixel. The palette is implemented in the microcontroller as 256 16-bit registers and, thus, provides the mapping of 8-bit color to 16-bit (5 bits / color + 1 bit of total intensity).
    The cursor has a separate palette of two 32-bit registers; it provides a monochrome image of the cursor in a 24-bit color space. The cursor can be 64x64 pixels or 32x32 pixels in size, and contains both the cursor image itself and the image inversion mask.
    Now you can run the test program and look at the result.



    Fig. 8. The result of the work.

    Resistive Sensor Connection


    The principle of operation of a resistive sensor is widely known (those who are not familiar with it can see it, for example, here http://ru.wikipedia.org/wiki/Touch screen ). Therefore, we proceed immediately to the description of connecting the sensor to the microcontroller. This device uses a four-wire sensor. The connection diagram is shown in fig. 9.


    Fig. 9. The connection diagram of the resistive sensor to the microcontroller.

    The idea underlying this connection is as follows. Each pin of the microcontroller can be in one of the following states: output with a logical 0, output with a log. 1, an input (i.e., in fact, an unconnected output), and an input pulled up to the supply voltage through a resistor. The YU and XL pins can also serve as ADC inputs.
    The whole procedure for determining the coordinates of pressing can be conditionally divided into three phases. In the first phase, the conclusions to which the sensor is connected are in the following state: (Fig. 10).



    Fig. 10. Determination of the coordinates of pressing. Phase 1.

    When the sensor films are closed, a log signal is received at the input of the microcontroller. 0, and the program proceeds to phase 2, determining the x-coordinate of pressing (Fig. 11). This is followed by phase 3, determination of the y-coordinate. (fig. 12).



    Fig. 11. Determination of the x-coordinate of pressing.



    Fig. 12. Determination of the y-coordinate of pressing.

    Of course, the algorithm for calculating the coordinates of pressing must include the suppression of the bounce of “contacts” (sensor films).
    With a single measurement, the accuracy of determining the coordinates will be too low, the noise of the measurements will lead to the fact that the cursor will fluctuate strongly in the vicinity of the point of contact. Therefore, it is highly desirable to use some kind of filtering algorithm, for example a median filter ( http://en.wikipedia.org/wiki/Median_filter ).
    After receiving the result in the ADC codes, it is recalculated into the coordinates of the screen using the usual linear transformations (ax + b), where the coefficients a and b must be found by calibrating the sensor and stored in the non-volatile memory of the controller. In fig. 13. An example calibration screen is provided.



    Fig. 13. Calibration screen.



    Fig. 14. Calibration screen on the LCD.

    It is also possible to connect the touch screen using an external controller, for example, XPT2046.
    The full source code for the sample program can be downloaded from here: https://bitbucket.org/arktur04/lcd-demo (IAR development environment).

    Links to the documentation mentioned in the post:
    1. Display Multi-Inno MI0350CT-3 http://www.displayfuture.com/engineering/specs/TFT/MI0350CT-3.pdf
    2. Pulse voltage converter MC34063A http: //www.fairchildsemi .com / ds / MC / MC33063A.pdf
    3.LPC2478 microcontroller http://www.ru.nxp.com/products/microcontrollers/arm7/lpc2400/LPC2478.html
    4. XPT2046 resistive sensor controller http: //www.dzsc .com / uploadfile / company / 785710 / 20111014212155973.pdf

    Also popular now: