The Magic of Microcontroller Programming: Separation of Powers

In microcontroller programming, many people can complicate issues that seem simple, creating a mess akin to a spider web in a forest.

In fact, according to the philosophy of programming magic, strictly dividing the process of program handling into departments, each performing its own duties, and ensuring that departments do not interfere with each other’s internal affairs is the key to successful programming.

Perhaps my statement seems abstract to many. Everyone knows the concept of modular design, but how many can apply this concept with ease?

To illustrate this issue, let’s take an example:

Now, we need to write a display program for a microcontroller.

According to the object-oriented philosophy of the microcontroller programming magician, we clearly need to handle our display processing independently. The result of this processing is that we will obtain a display object, which is an independent module. When we use this display object, we do not need to concern ourselves with what hardware corresponds to this display object, whether it is an LCD or an 8-segment display, etc.

We all know that we have supreme authority in programming. However, if you truly exercise such authority, both you and your program will ultimately suffer, especially as your program scales up.

For programming tasks like that of a display, we must first clarify the relationships conceptually, ensuring clear segmentation and reasonable structure.

To achieve this, we will employ the separation of powers in our program. As shown in the figure:

The Magic of Microcontroller Programming: Separation of PowersThis image, along with the concept of separation of powers, should be clear to everyone, right? There’s no need for further explanation. Many might think: this concept is easy to grasp.

This example does not consider image and animation processing, nor does it address the issue of single-screen display limitations.

First, we consider the jurisdiction of the data area in the separation of powers.

The data area stores all data for display purposes. Taking a character-type display as an example, the data area holds everything that needs to be displayed.

In other words, no other areas should contain the data required for display.

We refer to this data area as video memory. I believe that upon seeing this term, some forum friends might recall something.

Next, let’s define video memory simply:

#define ROWS        2
#define COLS          16
unsigned char vm[ROWS][COLS];

The definition of video memory is complete.

Video memory is one of the three powers in the separation of powers.

Originally, we could directly modify video memory to change the display content, but considering general applicability and inheritance, we cannot do so.

Therefore, we do not allow direct read/write access to video memory. Instead, we need to provide a universal read/write tool, as follows:

// Function: Write to video memory
// Parameters: r - row to write to
//            c - column to write to
//            s - string to write
void WriteVM(unsigned char r, unsigned char c, unsigned char *s)
{
    // Call the display positioning function (not discussed in this post)
    // Process the display string here
}

With this, we have a powerful control over video memory operations. Next, we need to consider how to handle the display of video memory content.

Such power, why not take a moment to practice it, fellow magicians?

Next, displaying the content of video memory becomes the key to display processing. Displaying the content of video memory essentially involves two situations: one is the need for continuous updates, and the other is the need for immediate updates.

If continuous updates or partial content needs to be updated constantly, this issue is easy to handle. We just need to provide a function that continuously refreshes the display, as shown in the example below:

void showVM(void)
{
    // Immediately send all content of video memory to the display, i.e., full screen refresh
    // Data that does not need constant refreshing is updated using the continuous update approach
    // This method is not suitable for microcontrollers with poor processing capabilities
}

Of course, if some magicians do not wish to use the full-screen refresh method, they can modify the previous WriteVM() function to refresh the display while writing to video memory. However, this method lacks flexibility, and I do not recommend it. Modern microcontrollers generally have sufficient capability to handle display tasks.

Of course, writing a good showVM() is not easy, as some displays may have many dots.

At this point, we need to adopt a line-by-line scanning method to reduce the CPU load of showVM(). The line-by-line scanning method refreshes only a specific line or part of the display each time it is called. This is a specific application of the threading handling method in the “Microcontroller Programming Magician”.

Once showVM() is completed, the originally complex display object is greatly simplified. These two simple functions represent the second power in the separation of powers.

Now, let’s summarize the first and second powers.

First, we treat the display as an object and handle it accordingly, which is the grand idea that the “Microcontroller Programming Magician” strives to elucidate.

Second, the first and second powers represent the grand idea of digital separation in the “Microcontroller Programming Magician”.

Third, using threads to enhance display effects is the threading handling philosophy in the “Microcontroller Programming Magician”.

Fourth, other techniques introduced in the “Microcontroller Programming Magician” will provide awakening skills to enhance program performance in this small application.

Since we are discussing the separation of powers, let’s now talk about the third power.

With the foundational ideas of the first and second powers, the third power is simply an application of these concepts. We can write content to video memory without worry about how it will be displayed or refreshed.

This is clearly great news. Now we just need to write this good news on paper. For example:

void main( )
{
    while(1)                {
        ……
        WriteVM(x,y," ");        // Can display content at any position without considering any display issues, just need to think about how to fill in the parameters
        ……
        showVM( );        // Here, just a simple call is needed, without considering any other issues
    }
}

Here is the spatial block diagram illustrating this concept:

The Magic of Microcontroller Programming: Separation of Powers

Finally, let’s summarize the application of this concept once more.

Before I proposed the object-oriented philosophy of bare programming, many people had used the object-oriented programming provided by programming languages. I too had used it for many years.

Since everyone has experience with object-oriented programming, we all start from the same point, which is not worth mentioning, so I hardly talk about that time.

Since I proposed the bare object-oriented approach, it must differ from the past; otherwise, I would just be sensationalizing and regurgitating others’ ideas, which is meaningless. A simple visit to a bookstore reveals a plethora of related books.

I reiterate: all ideas in bare programming are derived from past thoughts but differ from them. The implementation methods are not the same as traditional thoughts. Bare programming ignores syntactical constraints and tool support, greatly simplifying traditional ideas without introducing any additional knowledge, allowing methods that previously required sufficient hardware and software support to be effectively utilized without any extra software support and only minimal hardware.

This philosophy is related yet distinct from traditional thoughts.

Many readers may find these concepts familiar, but familiarity does not equate to truth. Whether one has attained truth depends on whether they can cast magic.

Just like the C language, it uses fewer symbols to describe the world, which is vastly different from human languages like English or Chinese. The fewer the symbols, the harder it is to describe the world. With fewer symbols, the available morphemes are also limited. Fewer morphemes make grammar easier to learn, but using a limited number of morphemes to describe an infinite world complicates the description methods.

Mastering Microcontrollers

Submissions, collaborations, sponsorships can be sent to: [email protected]

The Magic of Microcontroller Programming: Separation of Powers

Leave a Comment