嵌入式工程师只使用C语言来编写代码,不用考虑面向对象语言那么多的设计模式。但是在实际编程中还是有一些固定的模式要掌握。掌握这些固定的软件架构,不仅可以看懂资深工程师写的代码,还可以用在自己的项目中。
下面就来演示下这些非常重要模式。
// 操作系统层
#include
void operating_system_layer(void) {
printf("Operating System Layer\n");
// 操作系统层的处理
}
// 硬件抽象层
void hardware_abstraction_layer(void) {
printf("Hardware Abstraction Layer\n");
// 硬件抽象层的处理
operating_system_layer(); // 硬件抽象层调用操作系统接口
}
// 应用层
void application_layer(void) {
printf("Application Layer\n");
// 应用层的处理
hardware_abstraction_layer(); // 应用层调用硬件抽象层
}
// 主函数
int main(void) {
// 应用层的调用
application_layer();
return 0;
}
这样的设计体现了分层架构的核心思想,使得不同层次的功能清晰划分,提高了代码的可维护性和可扩展性。在实际应用中,每个层次的功能会更加复杂,可能涉及更多的模块和接口设计。通常在阅读操作系统源代码时候,要知道这种分层思想就可以很容易读懂系统代码。
#include
// 事件定义
typedef enum {
BUTTON_PRESSED,
TIMER_TIMEOUT,
SENSOR_DATA_UPDATE,
NUM_EVENT_TYPES // 用于计数事件类型的总数
} EventType;
// 事件结构体
typedef struct {
EventType type;
// 其他事件相关的数据
} Event;
// 事件处理函数
void handle_button_pressed(Event event) {
printf("Button Pressed Event Handled\n");
// 处理按钮按下事件的逻辑
}
void handle_timer_timeout(Event event) {
printf("Timer Timeout Event Handled\n");
// 处理定时器超时事件的逻辑
}
void handle_sensor_data_update(Event event) {
printf("Sensor Data Update Event Handled\n");
// 处理传感器数据更新事件的逻辑
}
// 主循环 - 不断处理事件
int main(void) {
while (1) {
// 模拟检查是否有新事件发生
Event currentEvent = { .type = SENSOR_DATA_UPDATE }; // 模拟传感器数据更新事件
// 处理事件的选择分支
switch (currentEvent.type) {
case BUTTON_PRESSED:
handle_button_pressed(currentEvent);
break;
case TIMER_TIMEOUT:
handle_timer_timeout(currentEvent);
break;
case SENSOR_DATA_UPDATE:
handle_sensor_data_update(currentEvent);
break;
default:
// 处理未知事件类型或其他逻辑
break;
}
}
return 0;
}
在这个例子中,主循环会不断迭代,模拟检查是否有新事件发生。根据当前事件的类型,使用 switch
语句选择相应的事件处理函数。实际上,这个过程可能会涉及到中断、事件队列、定时器等硬件或系统的机制,具体实现会因应用的需求而有所不同。
#include
#include
#include
// 消息结构体
typedef struct {
int messageType;
// 其他消息相关的数据
} Message;
// 定义消息队列
#define MAX_QUEUE_SIZE 10
typedef struct {
Message queue[MAX_QUEUE_SIZE];
int front;
int rear;
} MessageQueue;
// 初始化消息队列
void initMessageQueue(MessageQueue* q) {
q->front = -1;
q->rear = -1;
}
// 发送消息到队列
void sendMessage(MessageQueue* q, Message message) {
if ((q->rear + 1) % MAX_QUEUE_SIZE == q->front) {
printf("Error: Message queue is full.\n");
return;
}
if (q->front == -1) {
q->front = 0;
q->rear = 0;
} else {
q->rear = (q->rear + 1) % MAX_QUEUE_SIZE;
}
q->queue[q->rear] = message;
}
// 从队列接收消息
Message receiveMessage(MessageQueue* q) {
Message emptyMessage = { -1 }; // 空消息,表示队列为空
if (q->front == -1) {
printf("Error: Message queue is empty.\n");
return emptyMessage;
}
Message message = q->queue[q->front];
if (q->front == q->rear) {
q->front = -1;
q->rear = -1;
} else {
q->front = (q->front + 1) % MAX_QUEUE_SIZE;
}
return message;
}
// 任务1:发送消息
void* task1(void* arg) {
MessageQueue* messageQueue = (MessageQueue*)arg;
for (int i = 0; i < 5; ++i) {
Message message = { i };
sendMessage(messageQueue, message);
printf("Task 1 sent message: %d\n", i);
sleep(1);
}
pthread_exit(NULL);
}
// 任务2:接收并处理消息
void* task2(void* arg) {
MessageQueue* messageQueue = (MessageQueue*)arg;
for (int i = 0; i < 5; ++i) {
Message receivedMessage = receiveMessage(messageQueue);
if (receivedMessage.messageType != -1) {
printf("Task 2 received and processed message: %d\n", receivedMessage.messageType);
}
sleep(1);
}
pthread_exit(NULL);
}
int main() {
MessageQueue messageQueue;
initMessageQueue(&messageQueue);
pthread_t thread1, thread2;
// 创建两个线程,分别执行任务1和任务2
if (pthread_create(&thread1, NULL, task1, (void*)&messageQueue) != 0 ||
pthread_create(&thread2, NULL, task2, (void*)&messageQueue) != 0) {
fprintf(stderr, "Error creating threads.\n");
return 1;
}
// 等待两个线程结束
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
return 0;
}
消息传递通常涉及到多任务或多线程的场景,其中任务或线程之间通过消息进行通信。上面是一个简单的C语言示例,演示了一个简单的消息队列,一个任务发送消息,另一个任务接收并处理消息。
#include
// 定义状态
typedef enum {
STATE_A,
STATE_B,
STATE_C,
NUM_STATES
} State;
// 定义事件
typedef enum {
EVENT_X,
EVENT_Y,
EVENT_Z,
NUM_EVENTS
} Event;
// 定义状态机结构体
typedef struct {
State currentState;
} StateMachine;
// 初始化状态机
void initStateMachine(StateMachine* fsm) {
fsm->currentState = STATE_A; // 初始状态为 STATE_A
}
// 处理事件并执行状态转移
void processEvent(StateMachine* fsm, Event event) {
switch (fsm->currentState) {
case STATE_A:
if (event == EVENT_X) {
printf("Transition from STATE_A to STATE_B\n");
fsm->currentState = STATE_B;
} else {
printf("Invalid event in STATE_A\n");
}
break;
case STATE_B:
if (event == EVENT_Y) {
printf("Transition from STATE_B to STATE_C\n");
fsm->currentState = STATE_C;
} else {
printf("Invalid event in STATE_B\n");
}
break;
case STATE_C:
if (event == EVENT_Z) {
printf("Transition from STATE_C to STATE_A\n");
fsm->currentState = STATE_A;
} else {
printf("Invalid event in STATE_C\n");
}
break;
default:
printf("Unknown state\n");
break;
}
}
int main() {
StateMachine fsm;
initStateMachine(&fsm);
// 模拟事件序列
Event events[] = { EVENT_X, EVENT_Y, EVENT_Z, EVENT_X };
int numEvents = sizeof(events) / sizeof(events[0]);
// 处理事件序列
for (int i = 0; i < numEvents; ++i) {
processEvent(&fsm, events[i]);
}
return 0;
}
有限状态机(Finite State Machine,FSM)是一种形式化的计算模型,对于描述系统的状态和状态之间的转移非常有用。上面是一个简单的C语言示例,演示了一个有限状态机的基本结构和转移过程。
#include
// 定义回调函数类型
typedef void (*CallbackFunction)(void);
// 回调函数1
void callbackFunction1(void) {
printf("Callback Function 1: Button Pressed\n");
}
// 回调函数2
void callbackFunction2(void) {
printf("Callback Function 2: Button Released\n");
}
// 模拟外部触发的事件
void simulateExternalEvent(CallbackFunction callback) {
// 模拟事件触发
printf("Simulating External Event...\n");
// 调用回调函数
callback();
}
int main() {
// 模拟外部事件触发回调函数1
simulateExternalEvent(&callbackFunction1);
// 模拟外部事件触发回调函数2
simulateExternalEvent(&callbackFunction2);
return 0;
}
在这个简单的例子中:
callbackFunction1
和 callbackFunction2
,分别模拟了按钮按下和按钮释放的事件处理。simulateExternalEvent
函数来模拟外部触发的事件,这个函数接受一个回调函数作为参数,并在模拟的事件发生时调用该回调函数。main
函数中,我们模拟了两次外部事件触发,分别触发了不同的回调函数。以上就是非常重要的几种嵌入式架构和模式,实际代码可能会复杂点,但是基本原理都是相同的。这些架构会在工作经常用到,希望对大家有帮助。