找回密码
 立即注册
查看: 401|回复: 5

AI8051U 伪多任务 极简框架

[复制链接]
  • 打卡等级:偶尔看看III
  • 打卡总天数:50
  • 最近打卡:2025-05-01 11:24:23

13

主题

95

回帖

294

积分

中级会员

积分
294
发表于 2024-8-19 21:28:39 | 显示全部楼层 |阅读模式
AI8051U单片机的 伪多任务 极简框架





实现功能
  • 每个任务都有一个预定的周期
  • 每个任务都有一个与之关联的计数器
  • 递增的计数器作为系统时间
  • 比较式任务调度
  • 伪非阻塞式任务运行







先看框架
  1. // 定义任务函数
  2. void task1();
  3. void task2();
  4. void task3();
  5. // 定义任务周期(单位:毫秒)
  6. #define TASK1_PERIOD 100
  7. #define TASK2_PERIOD 50
  8. #define TASK3_PERIOD 200
  9. // 定义任务计数器
  10. volatile unsigned int task1_counter = 0;
  11. volatile unsigned int task2_counter = 0;
  12. volatile unsigned int task3_counter = 0;
  13. // 主循环
  14. void main() {
  15.     // 初始化计数器
  16.     task1_counter = TASK1_PERIOD;
  17.     task2_counter = TASK2_PERIOD;
  18.     task3_counter = TASK3_PERIOD;
  19.     // 主循环
  20.     while (1) {
  21.         // 模拟一个循环中的任务调度
  22.         taskScheduler();
  23.     }
  24. }
  25. // 任务调度函数
  26. void taskScheduler() {
  27.     static unsigned int system_tick = 0;  // 系统计数器
  28.     // 更新系统计数器
  29.     system_tick++;
  30.     // 检查任务1是否准备好执行
  31.     if (system_tick >= task1_counter) {
  32.         task1_counter += TASK1_PERIOD;
  33.         task1();
  34.     }
  35.     // 检查任务2是否准备好执行
  36.     if (system_tick >= task2_counter) {
  37.         task2_counter += TASK2_PERIOD;
  38.         task2();
  39.     }
  40.     // 检查任务3是否准备好执行
  41.     if (system_tick >= task3_counter) {
  42.         task3_counter += TASK3_PERIOD;
  43.         task3();
  44.     }
  45. }
  46. // 任务1
  47. void task1() {
  48.     // 执行任务1的代码
  49.     // 例如控制LED闪烁
  50.     // ...
  51. }
  52. // 任务2
  53. void task2() {
  54.     // 执行任务2的代码
  55.     // 例如读取传感器数据
  56.     // ...
  57. }
  58. // 任务3
  59. void task3() {
  60.     // 执行任务3的代码
  61.     // 例如更新显示屏显示
  62.     // ...
  63. }
复制代码

再看实测演示




测试代码
  1. #include <STC8051U.H>
  2. #include "intrins.h"
  3. #include "stc32_stc8_usb.h"
  4. #include "ST7735.h"
  5. #include <stdio.h>
  6. #include "AHT25.h"
  7. #include "key.h"
  8. #include "delay.h"
  9. #define FOSC 24000000UL //ISP 下载时需将工作频率设置为 24MHz
  10. char *USER_DEVICEDESC = NULL;
  11. char *USER_PRODUCTDESC = NULL;
  12. char *USER_STCISPCMD = "@STCISP#"; //不停电自动 ISP 下载命令
  13. #define POWER_IO P10
  14. int num_A = 0;
  15. int num_M = 0;
  16. int num_B = 0;
  17. char buf[30] = {0};
  18. volatile float tem;
  19. volatile float hum;
  20. #define POWER_ON POWER_IO = 1;
  21. #define POWER_OFF POWER_IO = 0;
  22. // 任务调度函数
  23. void taskScheduler();
  24. // 定义任务函数
  25. void task1();  //按键检测
  26. void task2();  //读温湿度
  27. void task3();  //更新显示
  28. // 定义任务周期(单位:毫秒)
  29. #define TASK1_PERIOD 50
  30. #define TASK2_PERIOD 500
  31. #define TASK3_PERIOD 200
  32. // 定义任务计数器
  33. volatile unsigned int task1_counter = 0;
  34. volatile unsigned int task2_counter = 0;
  35. volatile unsigned int task3_counter = 0;
  36. void main()
  37. {
  38.     EAXFR = 1;
  39.     WTST = 0X00;
  40.     CKCON = 0X00;
  41.     //POWER_IO  0: 关机  1:开机 推挽输出
  42.     P1M0 |= 0x01;
  43.     P1M1 &= ~0x01;
  44.     POWER_ON
  45.     //POWER_KEY 0:按键没按下,即充电开机  1:按开机 下拉输入
  46.     P4M0 &= ~0x04;
  47.     P4M1 &= ~0x04;
  48.     P4PD |= 0x04;
  49.     //tft 推挽输出
  50.     P3M0 |= 0xc0;
  51.     P3M1 &= ~0xc0;
  52.     P1M0 |= 0xa0;
  53.     P1M1 &= ~0xa0;
  54.     //KEY_A KEY_M KEY_B 下拉输入
  55.     P1M0 &= ~0x1c;
  56.     P1M1 |= 0x1c;
  57.     P1PD |= 0x1c;
  58.     //SCL 推挽输出
  59.     P2M0 |= 0x10;
  60.     P2M1 &= ~0x10;
  61.     //SDA 准双向IO口
  62.     P2M0 &= ~0x08;
  63.     P2M1 &= ~0x08;
  64.     //USB_CDC
  65.     P3M0 &= ~0x03; //P3.0/P3.1 和 USB 的 D-/D+共用 PIN 脚,
  66.     P3M1 |= 0x03; //需要将 P3.0/P3.1 设置为高阻输入模式
  67.     IRC48MCR = 0x80; //使能内部 48M 的 USB 专用 IRC
  68.     while (!(IRC48MCR & 0x01));
  69.     USBCLK = 0x00; //设置 USB 时钟源为内部 48M 的 USB 专用 IRC
  70.     USBCON = 0x90; //使能 USB 功能
  71.     usb_init(); //调用 USB CDC 初始化库函数
  72.     IE2 |= 0x80; //使能 USB 中断
  73.     EA = 1;
  74.     ST7735_Init();
  75.     // 初始化计数器
  76.     task1_counter = TASK1_PERIOD;
  77.     task2_counter = TASK2_PERIOD;
  78.     task3_counter = TASK3_PERIOD;
  79.     while(1)
  80.     {
  81.         taskScheduler();
  82.         m_delay_ms(1);
  83.     }
  84. }
  85. // 任务调度函数
  86. void taskScheduler() {
  87.    
  88.     static unsigned long int system_tick = 0;  // 系统计数器 32位 49.7天溢出
  89.     // 更新系统计数器
  90.     system_tick++;
  91.     // 检查任务1是否准备好执行
  92.     if (system_tick >= task1_counter) {
  93.         task1_counter += TASK1_PERIOD;
  94.         task1();
  95.     }
  96.     // 检查任务2是否准备好执行
  97.     if (system_tick >= task2_counter) {
  98.         task2_counter += TASK2_PERIOD;
  99.         task2();
  100.     }
  101.     // 检查任务3是否准备好执行
  102.     if (system_tick >= task3_counter) {
  103.         task3_counter += TASK3_PERIOD;
  104.         task3();
  105.     }
  106.    
  107. }
  108. // 任务1
  109. void task1() {
  110.     // 执行任务1的代码
  111.     static unsigned char key_value;
  112.     key_value = KEY_Scan(0);
  113.     switch(key_value) {
  114.     case A_PRES:
  115.         num_A++;
  116.         break;
  117.     case M_PRES:
  118.         num_M++;
  119.         break;
  120.     case B_PRES:
  121.         num_B++;
  122.         break;
  123.     case POWER_PRES:
  124.         POWER_OFF break;
  125.     default:
  126.         break;
  127.     }
  128. }
  129. // 任务2
  130. void task2() {
  131.     // 执行任务2的代码
  132.     AHT10_Read(tem,hum);
  133. }
  134. // 任务3
  135. void task3() {
  136.     // 执行任务3的代码
  137.     sprintf(buf,"T:%.2f %d",tem,num_A);
  138.     ST7735_WriteString(10,10,buf, Font_11x18,ST7735_GREEN,ST7735_BLACK);
  139.     sprintf(buf,"H:%.2f %d",hum,num_B);
  140.     ST7735_WriteString(10,40,buf, Font_11x18,ST7735_RED,ST7735_BLACK);
  141. }
复制代码




实验结果
  • 能运行
  • 满足项目需求



待优化

  • 使用定时器中断来更新系统计数器




回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:425
  • 最近打卡:2025-05-04 00:16:27
已绑定手机

19

主题

3191

回帖

4930

积分

论坛元老

积分
4930
发表于 2024-8-19 22:04:00 | 显示全部楼层
没有使用定时器中断,还是有点不足
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:偶尔看看III
  • 打卡总天数:50
  • 最近打卡:2025-05-01 11:24:23

13

主题

95

回帖

294

积分

中级会员

积分
294
发表于 2024-8-19 22:31:22 | 显示全部楼层
so*** 发表于 2024-8-19 22:04
没有使用定时器中断,还是有点不足

定时器还没学
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:449
  • 最近打卡:2025-04-30 10:57:37

17

主题

533

回帖

1326

积分

金牌会员

积分
1326
发表于 2024-8-19 23:02:25 | 显示全部楼层
想法挺不错的
自信就会温和,温和就会坚定!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家I
  • 打卡总天数:337
  • 最近打卡:2025-04-28 12:55:00

23

主题

296

回帖

1160

积分

金牌会员

积分
1160
发表于 2024-8-20 07:58:10 | 显示全部楼层
中断计时设定1ms,可以参考下


  1. typedef struct
  2. {
  3.         uint8_t taskstate;              //任务状态  
  4.         uint16_t tasktime;             //任务时间
  5.         uint16_t tasktimer;             //任务时间重装值
  6.     void (*pTaskFunCb)(void);            //任务函数
  7.   }Task_t;
  8. static Task_t g_task[] =
  9. {
  10.   //状态  计数  周期  函数
  11.   0
  12. //        {0,   5,   5,button_app_tset},
  13. //        {0,   2000,   2000,        LedCtrltwo},
  14.           /* Add new task here */
  15. };
  16. #define TASK_MAX (sizeof(g_task) / sizeof(g_task[0]))
  17. /*--------------------------------------------------------------------------
  18. @brief:  时间片轮转调用结构体函数
  19. @param: 无
  20. @retval: 无
  21. --------------------------------------------------------------------------*/
  22. static void TaskHandle(void)
  23. {
  24.         uint8_t i;
  25.         for(i = 0; i < TASK_MAX; i++)
  26.         {
  27.                 if (g_task[i].taskstate)
  28.                 {
  29.                         g_task[i].taskstate = 0;
  30.                         g_task[i].pTaskFunCb();
  31.                 }
  32.         }
  33. }
  34. /*-------------------------------------------------------------------------
  35. @brief: 结构体函数状态刷新函数
  36. @param: 无
  37. @retval: 无
  38. -------------------------------------------------------------------------*/
  39. static void TaskCbState(void)
  40. {
  41.         uint8_t i;
  42.         for( i = 0; i < TASK_MAX; i++)
  43.         {
  44.                 if (g_task[i].tasktime)
  45.                 {
  46.                         g_task[i].tasktime--;
  47.                         if(0 == g_task[i].tasktime)
  48.                         {
  49.                                 g_task[i].taskstate = 1;
  50.                                 g_task[i].tasktime= g_task[i].tasktimer;
  51.                         }
  52.                 }
  53.         }
  54. }
  55. static void DrvInit(void)
  56. {
  57.     Timer0_Init();
  58.     GpioInit();
  59.     Uart2Init();   
  60. }
  61. static void AppInit(void)
  62. {
  63. }
  64. void main(void)
  65. {
  66.     DrvInit();
  67.     AppInit();
  68.   
  69.     EA = 1;
  70.    
  71.     printf("uart2  printf test\n");
  72.     while(1)
  73.     {
  74.         TaskHandle();
  75.     }
  76. }
  77. void Time0_ISR() interrupt     TMR0_VECTOR   //定时器0中断函数
  78. {
  79.     TaskCbState();   
  80. }
复制代码
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:524
  • 最近打卡:2025-05-03 05:13:35
已绑定手机

34

主题

459

回帖

2223

积分

金牌会员

积分
2223
发表于 2024-8-23 13:37:22 | 显示全部楼层
学习
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-5-4 04:15 , Processed in 0.557413 second(s), 83 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表