📜 ⬆️ ⬇️

MultiClet: mastering SPI on the example of working with LCD

In early May, I became the proud owner of the LDM-MCp debug kit. For a couple of months he was gathering dust on the table, there was a lot of work, a vacation was brewing. When he returned, with new forces, a bright head and a zeal to feel something, to do something, but definitely not a job, the hands themselves reached for a new toy. Put the SDK under Linux, everything is connected.

First quest


Immediately after connecting, the system happily discovered a paired FTDI device, creating two ttyUSBx devices at once. And here is the dilemma - either to use the Serial-console, or to be able to upload the firmware, - the bundled bootloader works directly with the FTDI device. I had to draw scripts on my knee for the “correct” loading of the ftdi_sio module. Nakedness has proven itself in the use of Python bindings to the ftd2xx library. The general essence comes down to unloading the module, blocking the FTDI used for the firmware, and simultaneously loading the module back with it. Then the nuclear module can block the remaining FTDI for the UART.

Hello, world! - too trite


A simple “Hello, world!” With flashing LEDs started working immediately, it was only found that after flashing with the Linux mc-ploader, you also need to reset the board or wait until the WDT works.
Once in the winter I ordered a pair of SPY - screens HY28A for myself , but with our mail they arrived only in May. Here and the decision itself came - to start from the screen. Armed with a SYSCLK DX USB logic analyzer, it is useful to study specs on the GPIO and SPIx registers in the MCp processor and to pick around using the SPI examples.
')

Sound setting


On the LDM board, two of the three SPIs were already involved. One under the ADC, the second under the microSD slot. All MCp peripherals consist of GPIO registers that also have alternative functions, be it a network interface (MAC / MDIO), UART, USB, or I2C.
First of all, it is necessary to configure an alternative function for the remaining unused SPI0 via bit fields. To work, we need to include a pair of header files:
#include <HDL51001_ccf.h> #include <spi.h> … GPIOB->BPS = 0x07F; 
Here we have defined alternative functions for pin 0-9 GPIOB, corresponding to SCK, MOSI, MISO, SS0, SS1 and SS2. Another pair of SEL_IN / SCK_IN is used only in slave mode.
Now we need to set the parameters of the SPI bus itself:
 SPI0->SS = 0x07; //   CS    SPI0->CR = 0x37710000; 
So, what is the SPIxCR register? I will note the most interesting fields for us:
BitValueDescription
29onePolarization. SCK standby status. We use the HIGH signal.
28onePhase clock. We read data in a downturn.
270The prohibition of the divider at 16. We want maximum speed. With a processor frequency of 80 MHz, the SPI bus frequency will be 20 MHz
26oneThe bit sequence in transmission is LSB or MSB. We use MSB.
25oneThe operation mode of our SPI: “0” is slave, “1” is master.
24oneThis bit includes an SPI block.
23-200111The length of the data word. We want 8 bits (0x3 - 0xf - 4-16 bits respectively). For 32 bits, the field value must be zero.
19-160001Sets the prescaler mode. At zero, there were problems with the clock signal. T.ch. I chose "1".

To select the slave, SS0-SS2 lines are used. The active state is LOW. Sampling is done through the SPIxSS register: “1” sets the value HIGH, and “0” sets the value LOW.
SPI configuration is more or less sorted out. We turn to the display.
image

Pinout is pretty simple. We need to connect pins 3v3_IN, GND, SCK, CS, SDO (aka MISO), SDI (aka MOSI) and nRESET with BL_CTRL. Using the BL_CTRL line and PWM, you can control the brightness of the LED backlight. Illumination and so weak, t.ch. just feed it from 3v3. The nRESET signal line is used during the screen reset / initialization procedure. To do this, we need to configure another GPIO output:
 GPIOB->DIR |= 0x100; //  8-  GPIOB  OUTPUT GPIOB->OUT &= ~0x100; //     LOW 
Now we are ready to do some SPI work.

SPI: First Steps



To transmit something, we must announce our intentions. For this, before each sending of commands, we need to select a slave device. We have one - LCD. The command to write to the SPI port for our 8-bit packages will look like this:
 #define SPI_CS_LOW SPI0->SS = 0x06 /*       */ #define SPI_CS_HI SPI0->SS = 0x07 /* …    */ int SPI_WRITE(int data) { /*  ,          TX, ..   MSB */ SPI0->TX = ((uint32_t)data) << 24; /*     */ while(SPI_ST_TIP(SPI0) == 1); /*    */ /* ,       (SPI_ST_NF) */ while(SPI_ST_NE(SPI0) == 0); /* *    RX. *  ,       , *      . */ return SPI0->RX; } 
I will not go into the details of the screen initialization - this is also the setting / removal of the active nRESET signal, this is also the multiple write / read commands from the SPI. All this can be viewed in the source code lcd-ili9320.c in the function LCD_init .

Working with LCD is reduced to issuing commands for setting the position (X, Y) or limiting the scanning area, and then the sequentially recorded data will fill the specified area. For example, drawing rectangles is done by sequentially writing WxH color value words, thereby optimizing the number of commands issued. SPI - the bus is not fast, slave devices can operate at frequencies up to 25 MHz. Therefore, to show the video does not work, for this purpose it is necessary to use a parallel bus. There is no double buffer either. Everything that is issued by SPI is recorded in the internal memory of the display driver and is displayed on the screen during subsequent scanning. Welcome to the days of Turbo Pascal with the graph module! T.ch. The screen in SPI mode is good for displaying statics or rarely changing pictures.

In my test program, I generated fonts and a picture in the RLE sequence using the lcd-image-converter program. True, we had to modify the algorithm for generating RLE-sequences, the most optimal when working with 32-bit words. The original code gave out something “inedible”.

Having overlaid everything with functions for drawing sectors, circles, rectangles with straight lines, you can get the following result:

image

Source: https://habr.com/ru/post/191184/


All Articles