嵌入式 C 语言设计模式,在STC89C52上的应用

嵌入式系统中的C语言设计模式主要包括以下几种:

  1. 状态机模式:状态机模式是一种常用的嵌入式系统设计模式,可以用于处理多状态的控制逻辑。状态机模式将系统的状态和状态转换定义为一组状态和转换规则,通过状态转换来实现控制逻辑。

  2. 观察者模式:观察者模式是一种常用的事件处理模式,可以用于处理系统中的事件通知。观察者模式将事件处理和事件通知分离开来,通过注册和通知机制来实现事件处理。

  3. 适配器模式:适配器模式是一种常用的接口转换模式,可以用于处理系统中的接口兼容问题。适配器模式将不兼容的接口转换为兼容的接口,从而实现系统的兼容性。

  4. 单例模式:单例模式是一种常用的对象创建模式,可以用于控制系统中的对象数量。单例模式通过限制对象创建数量来实现系统的控制和优化。

  5. 工厂模式:工厂模式是一种常用的对象创建模式,可以用于处理系统中的对象创建和管理。工厂模式将对象的创建和管理分离开来,通过工厂来实现对象的创建和管理。

  6. 策略模式:策略模式是一种常用的算法处理模式,可以用于处理系统中的算法选择和执行。策略模式将不同的算法实现定义为一组策略,通过策略选择来实现算法的处理。

以上是常用的嵌入式系统中的C语言设计模式,不同的设计模式适用于不同的应用场景,需要根据具体的需求进行选择和应用。

采用嵌入式 C 语言设计模式,写STC89C52,P2口8个按键的C51应用实例

状态机模式

好的,以下是一个简单的状态机模式的例子,用于控制STC89C52芯片的P2口8个按键。请注意,这只是一个基本的示例,实际上,您可能需要根据您的具体需求进行修改和优化。

#include <reg52.h>

#define KEY_PORT P2 // 按键端口
sbit LED = P1^0; // LED端口

typedef enum{
    IDLE_STATE = 0,
    KEY1_PRESSED,
    KEY2_PRESSED,
    KEY3_PRESSED,
    KEY4_PRESSED,
    KEY5_PRESSED,
    KEY6_PRESSED,
    KEY7_PRESSED,
    KEY8_PRESSED
} KeyState;

void key_scan(void)
{
    static KeyState state = IDLE_STATE;
    switch(state){
        case IDLE_STATE:
            if(KEY_PORT != 0xFF){ // 检测到按键按下
                switch(KEY_PORT){
                    case 0xFE:
                        state = KEY1_PRESSED;
                        break;
                    case 0xFD:
                        state = KEY2_PRESSED;
                        break;
                    case 0xFB:
                        state = KEY3_PRESSED;
                        break;
                    case 0xF7:
                        state = KEY4_PRESSED;
                        break;
                    case 0xEF:
                        state = KEY5_PRESSED;
                        break;
                    case 0xDF:
                        state = KEY6_PRESSED;
                        break;
                    case 0xBF:
                        state = KEY7_PRESSED;
                        break;
                    case 0x7F:
                        state = KEY8_PRESSED;
                        break;
                    default:
                        break;
                }
            }
            break;
        case KEY1_PRESSED:
            LED = ~LED; // LED取反
            state = IDLE_STATE;
            break;
        case KEY2_PRESSED:
            // do something
            state = IDLE_STATE;
            break;
        case KEY3_PRESSED:
            // do something
            state = IDLE_STATE;
            break;
        case KEY4_PRESSED:
            // do something
            state = IDLE_STATE;
            break;
        case KEY5_PRESSED:
            // do something
            state = IDLE_STATE;
            break;
        case KEY6_PRESSED:
            // do something
            state = IDLE_STATE;
            break;
        case KEY7_PRESSED:
            // do something
            state = IDLE_STATE;
            break;
        case KEY8_PRESSED:
            // do something
            state = IDLE_STATE;
            break;
        default:
            state = IDLE_STATE;
            break;
    }
}

void main()
{
    while(1)
    {
        key_scan(); // 扫描按键
    }
}

在上面的代码中,我们使用了一个枚举类型(KeyState)来表示状态机的状态。在 key_scan() 函数中,我们使用一个静态变量 state 来表示当前状态,并根据按键的状态来切换状态。当检测到按键按下时,我们根据按键的值来切换到不同的状态,然后执行相应的操作。当状态执行完毕后,我们将状态切换回 IDLE_STATE,等待下一次按键事件的发生。

请注意,上面的代码只是一个简单的示例,您需要根据您的具体需求进行修改和优化。同时,如果您使用的是不同的开发板,您需要根据您的开发板来修改代码中的引脚定义和端口号。

观察者模式

好的,下面是基于观察者模式的STC89C52 P2口8个按键的C51代码:

#include <reg52.h>
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

// 定义观察者模式的接口
typedef struct {
  void (*press)(uchar key);  // 按键按下事件
  void (*release)(uchar key);  // 按键释放事件
} KeyObserver;

// 定义按键
typedef struct {
  uchar state;  // 按键状态,0表示未按下,1表示按下
  uchar code;  // 按键编码,从0开始
  KeyObserver* observer;  // 观察者,可以为空
} Key;

// 定义按键数组
Key keys[8];

// 定义状态机
typedef enum {
  IDLE, PRESSED, RELEASED
} KeyState;

// 定义状态机转移表
KeyState stateTable[3][2] = {
  {PRESSED, IDLE},  // IDLE状态下按下按键,转移到PRESSED状态
  {PRESSED, RELEASED},  // PRESSED状态下释放按键,转移到RELEASED状态
  {IDLE, IDLE}  // RELEASED状态下不做任何事情,转移到IDLE状态
};

// 定义按键扫描函数
void scanKeys() {
  uchar i;
  for (i = 0; i < 8; i++) {
    // 设置P2口为输入
    P2 = P2 & ~(1 << i);
    _nop_();
    _nop_();
    _nop_();
    keys[i].state = (P2 >> i) & 1;  // 读取P2口状态
    // 设置P2口为输出
    P2 = P2 | (1 << i);
  }
}

// 定义按键状态机处理函数
void handleKeys() {
  uchar i;
  for (i = 0; i < 8; i++) {
    Key* key = &keys[i];
    KeyState prevState = key->state;
    KeyState nextState = stateTable[prevState][key->state];
    key->state = nextState;
    if (prevState == IDLE && nextState == PRESSED) {
      // 触发按键按下事件
      if (key->observer != NULL && key->observer->press != NULL) {
        key->observer->press(key->code);
      }
    } else if (prevState == PRESSED && nextState == RELEASED) {
      // 触发按键释放事件
      if (key->observer != NULL && key->observer->release != NULL) {
        key->observer->release(key->code);
      }
    }
  }
}

// 定义状态机模式的例子,用于控制P2口8个按键
void main() {
  uchar i;
  // 初始化按键数组
  for (i = 0; i < 8; i++) {
    keys[i].state = 0;
    keys[i].code = i;
    keys[i].observer = NULL;
  }
  // 设置P2口为输出
  P2 = 0xff;
  // 循环扫描按键并处理状态机
  while (1) {
    scanKeys();
    handleKeys();
  }
}

在这个例子中,我们定义了一个观察者模式的接口KeyObserver,用于定义按键按下和释放事件的回调函数。然后定义了一个按键结构体Key,包含了按键的状态、编码和观察者。接着定义了一个按键数组keys,用于存储8个按键的状态。然后定义了一个状态机KeyState,包含了三个状态:IDLE、PRESSED和RELEASED。接着定义了一个状态机转移表stateTable,用于根据当前状态和输入状态计算下一个状态。然后定义了按键扫描函数scanKeys(),用于读取P2口的状态并更新按键的状态。接着定义了按键状态机处理函数handleKeys(),用于根据当前状态和下一个状态触发按键事件。最后在main()函数中初始化按键数组,并循环调用scanKeys()handleKeys()函数来处理按键事件。

请注意,这只是一个简单的例子,仅用于演示如何使用观察者模式设计嵌入式系统中的按键处理程序。实际应用中,可能需要根据具体情况进行修改和优化。

适配器模式

好的,以下是一个使用嵌入式C语言设计模式中的适配器模式来设计STC89C52芯片P2口8个按键的C51完整代码:

#include <reg52.h> 
#include <intrins.h>

#define uint unsigned int
#define uchar unsigned char

sbit K1 = P2^0;
sbit K2 = P2^1;
sbit K3 = P2^2;
sbit K4 = P2^3;
sbit K5 = P2^4;
sbit K6 = P2^5;
sbit K7 = P2^6;
sbit K8 = P2^7;

/* 适配器模式 */
typedef struct {
    void (*init)(void);
    uint (*read)(void);
} KeyAdapter;

/* 适配器实现 */
void P2AdapterInit(void) {
    P2 = 0xff;
}

uint P2AdapterRead(void) {
    return P2;
}

/* 状态机模式 */
typedef enum {
    IDLE = 0,
    PRESS,
    RELEASE
} KeyState;

/* 状态机结构体 */
typedef struct {
    KeyState state;
    uint cnt;
} KeyFSM;

/* 状态机初始化 */
void KeyFSMInit(KeyFSM* fsm) {
    fsm->state = IDLE;
    fsm->cnt = 0;
}

/* 状态机更新 */
void KeyFSMUpdate(KeyFSM* fsm, uint input) {
    switch(fsm->state) {
        case IDLE:
            if(input != 0xff) {
                fsm->state = PRESS;
                fsm->cnt = 0;
            }
            break;
        case PRESS:
            if(input == 0xff) {
                fsm->state = RELEASE;
                fsm->cnt = 0;
            }
            else {
                fsm->cnt++;
                if(fsm->cnt == 100) {
                    fsm->cnt = 0;
                    /* 按键按下 */
                    if(input & 0x01) {
                        /* K1被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                    else if(input & 0x02) {
                        /* K2被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                    else if(input & 0x04) {
                        /* K3被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                    else if(input & 0x08) {
                        /* K4被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                    else if(input & 0x10) {
                        /* K5被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                    else if(input & 0x20) {
                        /* K6被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                    else if(input & 0x40) {
                        /* K7被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                    else if(input & 0x80) {
                        /* K8被按下 */
                        // TODO: 在这里添加相应的处理代码
                    }
                }
            }
            break;
        case RELEASE:
            if(input != 0xff) {
                fsm->state = PRESS;
                fsm->cnt = 0;
            }
            break;
        default:
            break;
    }
}

/* 主函数 */
void main() {
    KeyAdapter adapter = {
        .init = P2AdapterInit,
        .read = P2AdapterRead
    };
    KeyFSM fsm;
    KeyFSMInit(&fsm);
    adapter.init();
    while(1) {
        uint input = adapter.read();
        KeyFSMUpdate(&fsm, input);
    }
}

在这段代码中,我们使用了适配器模式来适配STC89C52芯片的P2口输入,使得我们可以将其当做一个普通的按键输入来处理。然后,我们使用状态机模式来处理按键的按下和弹起事件,并在按键按下时调用相应的处理代码。在这里,我们只是留下了一些TODO标记,你需要根据具体的需求来编写相应的处理代码。

单例模式

好的,以下是一个基于状态机模式的单例模式设计的STC89C52芯片P2口8个按键的C51完整代码,供您参考:

#include <reg52.h>

// 定义按键的状态
#define KEY_UP 0
#define KEY_DOWN 1

// 定义状态机的状态
typedef enum {
  STATE_IDLE,
  STATE_PRESS,
  STATE_RELEASE
} State;

// 定义单例模式实例
static State state = STATE_IDLE;

// 定义按键的状态数组
static unsigned char key_states[8] = {0};

// 定义按键的状态更新函数
void update_key_states() {
  // 读取P2口的值
  unsigned char p2_value = P2;
  
  // 遍历8个按键
  for (int i = 0; i < 8; i++) {
    // 判断按键状态是否改变
    if ((p2_value & (1 << i)) && key_states[i] == KEY_UP) {
      key_states[i] = KEY_DOWN;
    } else if (!(p2_value & (1 << i)) && key_states[i] == KEY_DOWN) {
      key_states[i] = KEY_UP;
    }
  }
}

// 定义状态机的状态转换函数
void transition_state() {
  switch (state) {
    case STATE_IDLE:
      for (int i = 0; i < 8; i++) {
        if (key_states[i] == KEY_DOWN) {
          state = STATE_PRESS;
          break;
        }
      }
      break;
      
    case STATE_PRESS:
      for (int i = 0; i < 8; i++) {
        if (key_states[i] == KEY_UP) {
          state = STATE_RELEASE;
          break;
        }
      }
      break;
      
    case STATE_RELEASE:
      for (int i = 0; i < 8; i++) {
        if (key_states[i] == KEY_DOWN) {
          state = STATE_PRESS;
          break;
        }
      }
      if (state == STATE_RELEASE) {
        state = STATE_IDLE;
      }
      break;
  }
}

// 定义主函数
void main() {
  while (1) {
    update_key_states();
    transition_state();
    
    // 按键按下时的处理
    if (state == STATE_PRESS) {
      // TODO: 在此处编写按键按下时的处理代码
    }
    
    // 按键释放时的处理
    if (state == STATE_RELEASE) {
      // TODO: 在此处编写按键释放时的处理代码
    }
  }
}

需要注意的是,以上代码只是一个示例,您需要根据具体需求进行修改和完善。另外,您还需要根据硬件连接情况修改按键状态更新函数中的P2口读取代码。

工厂模式

好的,以下是一个基于工厂模式的STC89C52芯片P2口8个按键的C51完整代码,供您参考:

#include <reg52.h>

// 定义按键的状态
#define KEY_UP 0
#define KEY_DOWN 1

// 定义状态机的状态
typedef enum {
  STATE_IDLE,
  STATE_PRESS,
  STATE_RELEASE
} State;

// 定义按键的状态数组
static unsigned char key_states[8] = {0};

// 定义按键处理器接口
typedef void (*KeyHandler)(void);

// 定义按键处理器工厂
typedef struct {
  KeyHandler press_handler;
  KeyHandler release_handler;
} KeyHandlerFactory;

// 定义按键处理器
static void handle_key_1_press(void) {
  // TODO: 在此处编写按键1按下时的处理代码
}

static void handle_key_1_release(void) {
  // TODO: 在此处编写按键1释放时的处理代码
}

static void handle_key_2_press(void) {
  // TODO: 在此处编写按键2按下时的处理代码
}

static void handle_key_2_release(void) {
  // TODO: 在此处编写按键2释放时的处理代码
}

// 定义按键处理器工厂实例
static KeyHandlerFactory key_handler_factory[8] = {
  { handle_key_1_press, handle_key_1_release },
  { handle_key_2_press, handle_key_2_release },
  // TODO: 在此处添加剩余按键的处理器
};

// 定义按键的状态更新函数
void update_key_states() {
  // 读取P2口的值
  unsigned char p2_value = P2;
  
  // 遍历8个按键
  for (int i = 0; i < 8; i++) {
    // 判断按键状态是否改变
    if ((p2_value & (1 << i)) && key_states[i] == KEY_UP) {
      key_states[i] = KEY_DOWN;
    } else if (!(p2_value & (1 << i)) && key_states[i] == KEY_DOWN) {
      key_states[i] = KEY_UP;
    }
  }
}

// 定义状态机的状态转换函数
void transition_state() {
  static State state = STATE_IDLE;
  
  switch (state) {
    case STATE_IDLE:
      for (int i = 0; i < 8; i++) {
        if (key_states[i] == KEY_DOWN) {
          state = STATE_PRESS;
          break;
        }
      }
      break;
      
    case STATE_PRESS:
      for (int i = 0; i < 8; i++) {
        if (key_states[i] == KEY_UP) {
          state = STATE_RELEASE;
          break;
        }
      }
      break;
      
    case STATE_RELEASE:
      for (int i = 0; i < 8; i++) {
        if (key_states[i] == KEY_DOWN) {
          state = STATE_PRESS;
          break;
        }
      }
      if (state == STATE_RELEASE) {
        state = STATE_IDLE;
      }
      break;
  }
  
  // 调用对应的按键处理器
  if (state == STATE_PRESS) {
    for (int i = 0; i < 8; i++) {
      if (key_states[i] == KEY_DOWN) {
        key_handler_factory[i].press_handler();
      }
    }
  } else if (state == STATE_RELEASE) {
    for (int i = 0; i < 8; i++) {
      if (key_states[i] == KEY_UP) {
        key_handler_factory[i].release_handler();
      }
    }
  }
}

// 定义主函数
void main() {
  while (1) {
    update_key_states();
    transition_state();
  }
}

需要注意的是,以上代码只是一个示例,您需要根据具体需求进行修改和完善。另外,您还需要根据硬件连接情况修改按键状态更新函数中的P2口读取代码,并根据实际需求添加按键处理器工厂中的处理器函数。

策略模式

好的,以下是一个基于策略模式的STC89C52芯片P2口8个按键的C51完整代码,供您参考:

#include <reg52.h>

// 定义按键的状态
#define KEY_UP 0
#define KEY_DOWN 1

// 定义按键处理器接口
typedef void (*KeyHandler)(void);

// 定义按键处理器策略
typedef struct {
  KeyHandler press_handler;
  KeyHandler release_handler;
} KeyHandlerStrategy;

// 定义按键处理器
static void handle_key_1_press(void) {
  // TODO: 在此处编写按键1按下时的处理代码
}

static void handle_key_1_release(void) {
  // TODO: 在此处编写按键1释放时的处理代码
}

static void handle_key_2_press(void) {
  // TODO: 在此处编写按键2按下时的处理代码
}

static void handle_key_2_release(void) {
  // TODO: 在此处编写按键2释放时的处理代码
}

// 定义按键处理器策略数组
static KeyHandlerStrategy key_handler_strategies[8] = {
  { handle_key_1_press, handle_key_1_release },
  { handle_key_2_press, handle_key_2_release },
  // TODO: 在此处添加剩余按键的处理器策略
};

// 定义按键状态数组
static unsigned char key_states[8] = {0};

// 定义按键状态更新函数
void update_key_states() {
  // 读取P2口的值
  unsigned char p2_value = P2;
  
  // 遍历8个按键
  for (int i = 0; i < 8; i++) {
    // 判断按键状态是否改变
    if ((p2_value & (1 << i)) && key_states[i] == KEY_UP) {
      key_states[i] = KEY_DOWN;
    } else if (!(p2_value & (1 << i)) && key_states[i] == KEY_DOWN) {
      key_states[i] = KEY_UP;
    }
  }
}

// 定义按键状态处理函数
void handle_key_states() {
  // 遍历8个按键
  for (int i = 0; i < 8; i++) {
    // 判断按键状态
    if (key_states[i] == KEY_DOWN) {
      // 调用按键按下处理器
      key_handler_strategies[i].press_handler();
    } else if (key_states[i] == KEY_UP) {
      // 调用按键释放处理器
      key_handler_strategies[i].release_handler();
    }
  }
}

// 定义主函数
void main() {
  while (1) {
    update_key_states();
    handle_key_states();
  }
}

需要注意的是,以上代码只是一个示例,您需要根据具体需求进行修改和完善。另外,您还需要根据硬件连接情况修改按键状态更新函数中的P2口读取代码,并根据实际需求添加按键处理器策略。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zp1990412

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值