IIC interface-How to write OLED driver?

Infineon / Mitsubishi / Fuji / Semikron / Eupec / IXYS

IIC interface-How to write OLED driver?

Posted Date: 2024-01-20

This chapter takes the OLED screen, a common IIC interface module on the market, as an example to teach how to write the driver for the IIC interface.

The first step is of course to figure out what driver is used for the OLED screen you are using. It is said to be a screen, but it is actually a dense LED dot matrix, so there must be a driver for controlling a large number of LED lights. The OLED driver used in this tutorial is SSD1306. The driver has a variety of communication interfaces, and the IIC interface is used here (the specific interface used will be detailed in the data sheet)

According to the description of the SSD1306 data sheet, the slave address of the device depends on the level of SA0. However, I searched through the information given to me by the merchant and could not find the hardware schematic diagram of the entire module (it may be missing), so I had no choice but to open it. The routine checks that the slave address is 0x78.

The data sheet describes the IIC interface rules of 1306 in detail. The 7-bit address bit + 1-bit read and write bit. The data line and clock line describe the standard IIC protocol, so there is no need to get too entangled.

The following content is the key point. It should be noted that writing a driver for any peripheral device basically cannot escape instructions and data. The driving methods may be diverse, but at most they are just a combination of instructions and data, which is a little more complicated. Register operations will be added (that is, microcontroller No. 1 is used to control microcontroller No. 2 through some communication interface). After grasping the essence, ideas can be opened up.

Let’s first take a look at what the data sheet describes:

For those of you who have difficulty reading, let me highlight the key points:

Article 2 describes the setting of the slave address, which was mentioned earlier;

Article 3 talks about the definition of IIC read and write bits;

Article 4 talks about the rules of response signals in the IIC protocol. It is explained here that 1306 will respond to all IIC data (including address | read and write bytes);

Article 5 says that once the host establishes communication with 1306 (after sending the address | reading and writing bytes), the subsequent data sent to the IIC bus will be recognized as "control bytes" or "data bytes". What is the specific It is the control byte and data byte, which will be explained in detail later;

Article 6 says that every control byte and data byte will be responded to;

Article 7 talks about the stop bit rules of the IIC protocol;

Now let's explain what control bytes and data bytes are. For the screen, the purpose of our operation is to display content on the screen. "Display" is an action or behavior, which can also be called a command, and "content" is a piece of data. Therefore, when controlling the device, it will contain at least one command and one data. However, the command and data are only an 8-bit number in various communication protocols. How to distinguish them has become a very critical point.

1306 uses such a way to distinguish them: once communication is established through the IIC interface, the 0th byte (byte0) received subsequently must be used to indicate the type of the next byte (byte1), which uses 2 bytes to express a complete data transmission. The frame structure diagram of 1306 using IIC communication is posted in the data sheet:

The way the control byte distinguishes the data byte type is through its two highest bits: Co and D/C#. Let’s talk about the DC bit first. D is data and C is command. If this bit is 0, it means that the next byte is a command. If the bit is 1, then the next byte is data. In fact, as long as there is such a bit, the control of 1306 can be completed. Now think about a problem, if I need to write a large number of commands (such as 100) continuously, in order to complete the transmission of these 100 commands, I need 200 bytes are transmitted because each command needs to be bound to a control byte. In order to improve transmission efficiency, the Co bit came into being. If the Co bit is 0 and the DC bit is also 0, then the 1306 will recognize all data incoming after the control byte as commands. In this way, if you want to write 100 commands actually only need to send 101 bytes to achieve the purpose, and the efficiency is almost doubled. The same is true for transmitting data. You only need to set the Co bit to 0 and the DC bit to 1, and the subsequent incoming bytes will be all data. If there is no need to continuously write a large amount of data of the same type (command/data, the data in brackets is for the screen display, the data before the brackets is for the IIC bus), you can also set the Co bit to 1 The function is implemented in the form of "control byte + data byte (DC byte)".

The following is the writing of the code. We use the union to directly list the frame structure that needs to be sent. When sending, you only need to assign the corresponding bit and then send the value array. This way, there is no need to perform bit operations when sending. Greatly improve code readability:

Post another function that sends instructions. This function uses a single write method, which is not efficient but is convenient to use. It should be noted that this function does not have the ability to establish IIC communication. It is only responsible for the situation where communication has been established. Issue a complete command below.

Now that we have the functions to establish IIC communication and send instructions, we can actually use these functions to see the effect. One instruction in 1306 is A5H. Its function is to forcefully light up all the pixels on the screen and correctly initialize the OLED. After that, just send A5H.

Regarding the initialization of OLED, the module information provides a complete set of initialization instructions. Simply put, after powering on, these instructions need to be sent to the OLED driver first, and then the screen will work normally. The details of each instruction are detailed. function, please also check the instruction table chapter of the 1306 data manual, or directly search for relevant information on the 1306 instruction.

Bringing the topic back to the screen display, our goal is definitely not just as simple as polishing the entire screen. The screen is either used for drawing or writing. It must at least be able to write. What we now know is that the screen is an LED array. We only need to control a batch of pixels to light up according to fixed rules to display the content we want. The process of achieving this is also called font acquisition, which is packaged by the merchants who sell the screen. There will be software for extracting fonts from the information. If not, you can directly download one online. The font data is preset and stored in the microcontroller and can be displayed directly when needed. This method is simple and effective.

Great, now our writing goal has changed to "light up the right pixels at the right position", so how to determine the position? The screen has so many pixels, and now there is data but no location. At this time, we need to briefly explain the display logic of OLED. The entire screen is divided into multiple pages. Each page has 128 columns of pixels. The screen resolution is 128*64, with 128 pixels horizontally and 64 pixels vertically. The data we write each time is 8 bits. This 8 bit data indicates the pixel status of a certain column in a certain pixel page. To put it figuratively: 8 dots are arranged in a row, and 128 columns are arranged horizontally to form a page. The entire screen has a total of 8 pages. These 8 pages are arranged vertically, ultimately forming a 128*64 screen.

If you want to display content in the correct position, you have to select the correct page (hereinafter referred to as page). There are 8 page0-page7 in total. Each page has its own physical address, from B0H to B7H, so we can use this Write a function that determines the cursor position. This function can anchor a correct display position when we need to write.

The font mentioned above is actually a batch of 8-bit data. Combined with the screen display principle just explained, we have to think about a question again: How fine must the pixels be to look like a word? It is in line with the characteristics of OLED, which has 8 rows of pixels on one page (because it will operate better). The answer is to use a square with a width of 8n pixels to display characters. Currently, characters of 16*16 size just meet the requirements. This is also the size chosen by most small-screen displays. In this way, if you want to display a character, you need to write several columns of data in 2 pages, so there is a writing function. The specific code is as follows:

This function first establishes IIC communication, sets the coordinates of the displayed characters after establishing communication with the slave, and then directly sends out the pixel data of the upper and lower parts in sequence. This function can independently complete the display of characters, and the subsequent demonstration code The function for displaying strings in is implemented based on this function. Although for the display of strings, the best solution is to establish one communication and complete the transmission of all data, but such code will mix various functions together, and the hierarchy is not clear enough. Here This planning is also for better understanding of the content. The code files about IIC and OLED will be attached at the end of the article.

All data used for pixel display will be stored in Graphic Display Data RAM (GGDRAM). Since it is RAM, theoretically the data stored in it should be 0 when power is turned on, but in order to avoid unnecessary interference For possible impacts, we also need a screen clearing function, which actually sets all data on all pages to 0.

With all the prerequisites, we can display the content in the main function. Add IIC initialization and OLED initialization to the device initialization, plus string display, and you're done.

Finally, post a picture to see the finished product.

Some digressions at the end of the article. There is a lot of information on software simulation of IIC and OLED drivers on the Internet. Except for the application layer code of the writing part, it is recommended to write the code of the data link layer yourself. The IIC bus efficiency of these open source codes is actually It is very low and easy to cause misunderstanding. When the editor was studying the routines provided by the merchant, he never understood why the routine could initialize successfully when sending 0x00 as the control byte, but I could not. Later, I thought about it carefully. It was because they IIC, only 2 bytes of content will be sent each time communication is established. That is to say, if you want to send 20 commands, you need to establish 20 IIC communications, and the slave address must be resent each time. Send these 20 A command actually sends 60 bytes (including the IIC address bytes). The function can certainly be implemented, but the efficiency is very low, and the code comments are not detailed (even if the code is appropriated without changing the comments), if it is used as Learning to use without explanation can easily lead to misunderstanding (at least I was misunderstood). If readers really have learning needs rather than simple appropriation needs, it is best to follow the content described in the manual.

Review Editor: Huang Fei

#IIC #interfaceHow #write #OLED #driver