C language program structure of small capacity 87LPC764 single chip microcomputer system

Publisher:平凡幸福Latest update time:2011-12-30 Keywords:87LPC764 Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere
The author set out to write a working program for an IC card prepaid electricity meter. The meter uses Philips' 8-bit 51 extended single-chip microcomputer 87LPC764. It is required to realize many functions, including display off, load calculation and control, indicator flashing, and query of various parameters of the meter. In short, many time units are required. The author used ASM51 to complete the writing of this program at that time, and the program size after completion was a little more than 2KB. Later, due to various reasons, this program was not really used. It was only used for timing and load calculation on an aging device after some changes. About a year later, the author rewrote the code again.

1 System Improvement

It can be said that this code implemented with ASM51 is not organized at all. Whatever function is needed is added, making the structure of the program very loose. In fact, this is also the reason why the author finally decided to rewrite the code. As

you know, 87LPC764 has 4KB Flash ROM, and the author's program size is only a little more than 2KB. Therefore, the first idea is to use C language as the main development language, which should not lead to insufficient code space. Secondly, considering that there are many modules (or tasks, hereinafter referred to as tasks) that require timing functions, it is necessary to manage these tasks in an orderly manner. The author considers using the time slice polling method, that is, giving each task that requires time management a time interval, and once the time interval is reached, running its code, so as to achieve the purpose of reasonable use of system timer resources. As far as the 51 system is concerned, generally at least one timer can be used for time slice polling. Based on the above ideas, the following data types are constructed.

typedef unsigned char uInt8
typedef struct {
void (*proc)(void); //Processing program
uInt8 ms_count; //Time slice size
} _op_;
After the data structure is defined, the next step is to implement the code, which includes three parts, namely, initialization data, time slice refresh and time to execute.
Initialization data.
#define proc_cnt 0x08 //Define the number of processes or tasks
//Task stack initialization
code _op_ Op[proc_cnt]={{ic_check, 10}, {disp_loop, 100},
{calc_power, 150}, {set_led, 2}, …
};
//Set the initial value of the time slice
data uInt8 time_val[proc_cnt]={10, 100, 150, 2, …};
Time slice refresh.
void time_int1(void) interrupt 3
{ uInt8 cnt;
Time_Counter:=Time_Unit;
for(cnt=0;cnt { time_val[cnt]--;
}
}
Task execution.
void main(void){
uInt8 cnt;
init(); //Program initialization
interrupt_on(); //Open interrupt
do{
for(cnt=0;cnt { if(!time_val[cnt])
{ time_val[cnt]=Op[cnt].ms_count;
Op[cnt].proc();
}
}
}while(1);
}

In the above structure definition, proc cannot take parameters. The communication between tasks can define a parameter memory block and exchange data information through a mechanism, such as defining a global variable. For a small-capacity single-chip microcomputer system, there are not many tasks that need to be done in this way, and the total number of tasks will not be too large, so this coordination is not too difficult to handle.

Perhaps everyone has such an understanding that in a real-time system, almost all specific tasks have time attributes. Even if the process or task does not require timing, it is not necessary to query and refresh it all the time. For example, IC card media detection, it is sufficient to ensure once per second. Therefore, these tasks can also be included in this structure.

In the above program code, considering the RAM limitation of the single-chip system, the task stack cannot be established in the RAM like some real-time OS. The author established the task stack in the code space, so it is impossible to dynamically add tasks when the program is running, so it is required that the task stack has been determined when the program is compiled. At the same time, a set of count value flags time_val are defined to record the amount of time when the program is running and refresh it in a timer interrupt. Changing the Time_Unit in the time slice refresh interrupt process statement Time_Counter:=Time_Unit; can change the refresh granularity of the system time slice. Generally, this value is determined by the minimum time measurement value of the system.

At the same time, it can be seen from the execution process of the task that this system structure does not change the nature of its foreground/background system, but only effectively manages the background logic operation sequence. At the same time, if the task execution process is changed and the task with a small time slice is guaranteed to be placed in front, as shown in the following program.
do{
for(cnt=0;cnt if(!time_val[cnt]){
time_val[cnt]=Op[cnt].ms_count;
Op[cnt].proc();
break; //After execution is completed, re-prioritize scheduling
}
}
}while(1);

Then the system becomes a task scheduling system with execution frequency as priority. Of course, you must be very careful when setting this method, and pay attention to the allocation of time slices. If the time slice is too small, it may cause tasks with lower execution frequency to be difficult to execute; and if there are two identical time slices, it is even more dangerous, which may cause the second task with the same time slice not to be executed. Therefore, the allocation of time slices must be reasonable and ensure its uniqueness.

2 Performance Analysis and Task Splitting

The above two task management methods, the former is scheduled in sequence according to the order of the task stack and the size of the time slice, which is temporarily called flow operation scheduling; and the latter is called frequency priority scheduling. Both methods have their own advantages and disadvantages. The tasks of flow operation scheduling have equal priority, and they will be called in sequence as soon as the time slice arrives. The order and uniqueness of the time slice size are not required; the disadvantage is that it may cause the task with a small time slice, that is, the task that is required to be executed faster, to wait too long. The tasks of frequency priority scheduling are prioritized according to the size of their time slice, that is, the execution frequency. Tasks with a small time slice have a high execution frequency and always have a higher priority, but the allocation of time slices must be coordinated, otherwise it may cause tasks with low execution frequency to wait for a long time.

It should be noted that both methods may cause some tasks to wait for a long time, and the time set by the time slice cannot be used as the basis for accurate time. According to the requirements or needs of the system, some protection work may even be performed during the execution of the task, such as interrupt shielding, so pay attention when planning tasks. If a task is cumbersome or may take a long time to wait, you should consider splitting the task, breaking down a larger task into smaller tasks, and dividing a time-consuming task into multiple less time-consuming tasks to complete its function together. For example, if the waiting time is long, you can add a timed task. When the timed task arrives, a message flag is sent. If the main process does not detect the message flag, it will return immediately, otherwise it will continue to execute. The following is a sample code. Assuming that the task will wait for a long time, it is now split into two tasks, proc1 and proc2, to complete the original work together. Proc1 is executed once every 100 time units, and proc2 is executed once every 200 time units.

// Define two tasks and add them to the task stack.
code _op_ Op[proc_cnt]={…,{proc1,100},{proc2,200}};
data int time1_Seg; //Define a global flag
//Task implementation
void proc1(void){
if (time1_Seg)
exit;
else
time1_Seg=const_Time1; //If the time is up, restore the initial value and
//then execute the following code.
… //Task actual execution code
}

void proc2(void){
if(time1_Seg)
time1_Seg--;
}

From the above example, we can see that after the task is split, it hardly takes up too much CPU time, which greatly reduces the waiting time of the task and gives the CPU enough time to manage and schedule the task. At the same time, the structure and readability of the program are greatly enhanced.

Conclusion

After the IC card meter working program is completely rewritten based on the above ideas and structure, the structural performance of the system has been greatly improved. After all the writing is completed, the program code volume is about 3KB. It can be seen that the program construction of this structure does not cause a lot of system overhead (most of the overhead is due to the use of C), but simplifies the development. This only requires subdividing the system into a series of tasks, and then adding them to the task stack for compilation. It is very suitable for the development of small-capacity single-chip microcomputer systems, and the author has successfully applied this structure in multiple systems.

Keywords:87LPC764 Reference address:C language program structure of small capacity 87LPC764 single chip microcomputer system

Previous article:Using USB UART bridge to realize MCU online programming
Next article:Design of time-delay leakage relay based on single chip microcomputer

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号