找回密码
 立即注册
楼主: CosyOS

全局不关总中断的 RTOS,CosyOS-III-V1.2.0, 送 擎天柱-AI8051U转89C52核心板

 火... [复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-05-01 10:58:55

44

主题

230

回帖

2841

积分

金牌会员

积分
2841
发表于 2024-11-21 09:52:35 | 显示全部楼层
向CosyOS成功迈出的第一步: 通过串口库助手观察任务管理器输出:
截图202411210942424516.jpg




首先从作者的gitee仓库拉取最新的没有测试case的纯净版本,防止其他因素影响;


然后按照作者文档中心 -> 开发流程 创建keil 工程(为了使用CosyOS 给mac电脑装了个win系统 {:5_318:});
接下来添加需要的代码:
1、在初始化钩子中添加初始化代码:
  1. /**************************************************************************//**
  2. * @item     CosyOS-II Hook
  3. * @file     init_hook.c
  4. * @brief    初始化钩子
  5. * @detail   在主函数中首先被调用,适用于初始化时钟、GPIO、寄存器等工作。
  6. * @author   迟凯峰
  7. * @version  V3.0.0
  8. * @date     2024.06.25
  9. ******************************************************************************/
  10. #include "..\System\os_link.h"
  11. void init_hook(void)
  12. {
  13.         #define BAUD  115200 // 串口波特率
  14.         #define TM2   (65536 - SYSCFG_SYSCLK / 4 / BAUD)
  15.         P0M0 = 0; P0M1 = 0;
  16.         P1M0 = 0; P1M1 = 0;
  17.         P2M0 = 0; P2M1 = 0;
  18.         P3M0 = 0; P3M1 = 0;
  19.         P4M0 = 0; P4M1 = 0;
  20.         P5M0 = 0; P5M1 = 0;
  21.         P6M0 = 0; P6M1 = 0;
  22.         P7M0 = 0; P7M1 = 0;
  23.        
  24.         AUXR  =        0x00;  // 允许访问内部xdata
  25.         P_SW2 =        EAXFR | 0x01; // xxxx xxxx = 1000 0000 允许访问扩展RAM区特殊功能寄存器, 我是用的是STCH试验箱,因此这里需要切换串口二的引脚;
  26.        
  27.         TMOD = 0x00;   // 定时器0、1、2、3、4为16位自动重装载模式
  28.         AUXR = 0x45;   // 定时器1、2为1T模式,  串口1用定时器2做波特率发生器
  29.         SCON = 0x40;   // 串口1工作模式为模式1
  30.         S2CON = 0x40;  // 串口2工作模式为模式0,串口2用定时器2做波特率发生器
  31.         P_SW1 = 0xC0;  // 串口1切换至P4.3/P4.4
  32.         TI = 1;        // 用于printf
  33.         /* 定时器2 */
  34.         T2L = (unsigned char)TM2;
  35.         T2H = (unsigned char)(TM2 >> 8);
  36.         AUXR|= T2R;
  37.         /* UART2中断优先级为1级 */
  38.         IP2H &=~PS2H;
  39.         IP2 |= PS2;
  40.         /* INT0中断优先级为0级 */
  41.         IPH &=~PX0H;
  42.         PX0 = 0;
  43.         /* 任务管理器 */
  44.         #if SYSCFG_DEBUGGING == 1
  45.         S2CON |= S2REN;
  46.         IE2 |= ES2;
  47.         #endif
  48. }
复制代码


2、在用户分组下新建.C 文件编写串口处理程序(直接copy 作者的)
  1. /**************************************************************************//**
  2. * @item     CosyOS-II User
  3. * @file     Taskmgr.c
  4. * @brief    CosyOS-II 任务管理器
  5. * @detail   当前配置为使用UART2,用户可自行调整。
  6.              正常情况下,下方代码中,您仅需调整:UART2_Isr、中断向量号、S2CON、S2TI、S2RI、S2BUF。
  7.              您需自行初始化串口、串口中断优先级、波特率等相关配置。
  8. * @author   迟凯峰
  9. * @version  V1.0.2
  10. * @date     2024.05.11
  11. ******************************************************************************/
  12. #include "..\System\os_link.h"
  13. #if SYSCFG_DEBUGGING == __ENABLED__
  14. void UART2_Isr(void) interrupt 8// using 3
  15. {
  16.         if(S2CON & S2TI){
  17.                 S2CON &= ~S2TI;
  18.                 if(*s_debug_sendptr){
  19.                         S2BUF = *s_debug_sendptr++;
  20.                 }
  21.                 else{
  22.                         iDebugSend;
  23.                 }
  24.         }
  25.         if(S2CON & S2RI){
  26.                 S2CON &= ~S2RI;
  27.                 if(s_debug_recvptr - s_debug_recvbuff < OS_DEBUGRECVBUFFSIZE - 1){
  28.                         *s_debug_recvptr++ = S2BUF;
  29.                 }
  30.                 iDebugRecv;
  31.         }
  32. }
  33. #endif
复制代码
由于使用了串口二,需要使用LINK1D的另一组串口,接线如下:

截图202411210951375783.jpg

效果如下:





点评

任务管理器相关命令: 开启任务管理器:taskmgr 退出任务管理器:exit 设置任务管理器更新速度:taskmgr /s=xxx xxx: 50~5000, 单位毫秒。 命令结尾要加 回车换行 \r\n 要靠串口助手自动加,而不是写到命令中。  详情 回复 发表于 2024-11-21 12:49
不争是争
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-11-21 12:49:13 | 显示全部楼层
大*** 发表于 2024-11-21 09:52
向CosyOS成功迈出的第一步: 通过串口库助手观察任务管理器输出:

{:5_332:}

任务管理器相关命令:
开启任务管理器:taskmgr
退出任务管理器:exit
设置任务管理器更新速度:taskmgr /s=xxx
xxx: 50~5000, 单位毫秒。

命令结尾要加 回车换行 \r\n
要靠串口助手自动加,而不是写到命令中。
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-05-01 10:58:55

44

主题

230

回帖

2841

积分

金牌会员

积分
2841
发表于 2024-11-22 14:34:46 | 显示全部楼层
使用CosyOS点亮试验箱的流水灯:


1、在用户组中添加led.h 头文件,和 led.c源文件:
这里有个小疑问, led.c 文件中的两个变量是全局变量把, 任务是不是不可重入的;

  1. #ifndef __LED_H
  2. #define __LED_H
  3. dExternTask(led_flow);  // 在头文件中声明任务
  4. #endif
复制代码
  1. #include "..\User\led.h"
  2. #include "..\System\os_link.h"
  3. s_u8_t xdata ledIndex;
  4. s_u8_t code ledNum[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
  5. uCreateTask(led_flow, 1, 32,0,0) {
  6.     P6 = ~ledNum[ledIndex];        //输出低驱动
  7.         ledIndex++;
  8.         if(ledIndex > 7)
  9.         {
  10.             ledIndex = 0;
  11.         }
  12.     uDelay_ms(300);
  13.         
  14.         uEndTasking;
  15. }
复制代码
2、在初始化钩子中设置端口,并且打开led电源开关:
截图202411221428262757.jpg
  1. P6M1 = 0x00;   P6M0 = 0xff;   //设置为推挽输出
  2. P40 = 0;                //LED Power On
复制代码


3、在启动钩子中启动任务:
  1. /**************************************************************************//**
  2. * @item     CosyOS-II Hook
  3. * @file     start_hook.c
  4. * @brief    启动钩子
  5. * @detail   在启动任务中被调用,可在此启动用户任务。
  6. * @service  uStartTask(task, status); 启动任务
  7.              uStartTask_Ready(task);   启动任务并就绪
  8.              uStartTask_Suspend(task); 启动任务并挂起
  9. * @author   迟凯峰
  10. * @version  V3.0.0
  11. * @date     2024.06.25
  12. ******************************************************************************/
  13. #include "..\System\os_link.h"
  14. #include "stdio.h"
  15. #include "..\User\led.h"
  16. void start_hook(void)
  17. {
  18.         uStartTask(led_flow, 0);
  19. }
复制代码


看流水灯和任务管理器效果:


点评

任务创建 要 注意 动态 或 静态 的问题, uCreateTask:静态创建 uExternTask:静态声明 dCreateTask:动态创建 dExternTask:动态声明 静态创建的要静态声明,动态创建的要动态声明,否则编译器应该会有警告!  详情 回复 发表于 2024-11-22 17:10
不争是争
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-11-22 17:10:24 | 显示全部楼层
大*** 发表于 2024-11-22 14:34
使用CosyOS点亮试验箱的流水灯:

任务创建 要 注意 动态 或 静态 的问题,

uCreateTask:静态创建
uExternTask:静态声明

dCreateTask:动态创建
dExternTask:动态声明

静态创建的要静态声明,动态创建的要动态声明,否则编译器应该会有警告!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-05-01 10:58:55

44

主题

230

回帖

2841

积分

金牌会员

积分
2841
发表于 2024-11-22 19:14:42 | 显示全部楼层
Cos*** 发表于 2024-11-22 17:10
任务创建 要 注意 动态 或 静态 的问题,

uCreateTask:静态创建

哦哦,原来如此,确实有告警,没来得及看原因。
不争是争
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-05-01 10:58:55

44

主题

230

回帖

2841

积分

金牌会员

积分
2841
发表于 2024-11-26 09:45:12 | 显示全部楼层
STC8试验箱例程16 用CosyOS实现

例程16的功能是:
1、模拟RTC显示时分;
2、行列扫描方式实现检测矩阵键盘更新时间;
3、数码管显示时间和按键值;

思路:
三个功能分别对应三个任务:
1、rtc_task:用来延时500ms,循环执行,执行过程中调用display_task 提供的修改显示缓存的函数;
2、display_task:延时1ms 通过P6,P7发送显示数据到595, 并且提供刷新显示缓存函数;
3、key_task:用来检测按键,调用led 提供的修改显示缓存函数修改按键显示值和时间显示;

步骤:
1、 按照迟老师教程搭建工程,也可以复制之前的工程,修改内容;
2、添加 lec.c , led.h、key.c、key.h、 rtc.h、rtc.c:
截图202411260922356646.jpg
内容如下:
led.c:
  1. #include "..\System\os_link.h"
  2. #include "..\User\led.h"
  3. #define DIS_DOT     0x20
  4. #define DIS_BLACK   0x10
  5. #define DIS_        0x11
  6. s_u8_t code t_display[]={                       //标准字库
  7. //   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  8.     0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
  9. //black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
  10.     0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
  11.     0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
  12. s_u8_t code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
  13. s_u8_t  LED8[8];        //显示缓冲
  14. s_u8_t  display_index;  //显示位索引
  15. uCreateTask(display_task, 6, 32, 0 ,0 ) {  // 创建任务,名称为display_task,优先级为6,给定任务栈大小为32字节;
  16.        
  17.         s_u8_t i;
  18.         for(i=0; i<8; i++) {
  19.                 LED8[i] = 0x10; //上电消隐
  20.         }
  21.         display_index = 0;
  22.         refreshDisplay(12, 30, 0);
  23.        
  24.         while (1) {
  25.                
  26.                 P7 = ~T_COM[7-display_index];
  27.                 P6 = ~t_display[LED8[display_index]];
  28.                 if(++display_index >= 8) {
  29.                         display_index = 0;  //8位结束回0
  30.                 }
  31.        
  32.                 uDelay_ms(1);        // 1毫秒延时, 延时时间到后发送数据到595
  33.         }
  34.        
  35.        
  36.         uEndTasking;
  37.        
  38. }
  39. void refreshDisplay(s_u8_t hour, s_u8_t minute, s_u16_t msecond) {
  40.         if(hour >= 10) {
  41.                  LED8[0] = hour / 10;
  42.         }
  43.     else {
  44.                 LED8[0] = DIS_BLACK;
  45.         }
  46.     LED8[1] = hour % 10;
  47.     LED8[2] = minute / 10;
  48.     LED8[3] = minute % 10;
  49.     if(msecond >= 500) {
  50.                 LED8[1] |= DIS_DOT; //小时后的小数点做秒闪
  51.         }
  52. }
  53. void showKeyCode(s_u8_t keyCode) {
  54.         LED8[6] = keyCode / 10; //显示键码
  55.     LED8[7] = keyCode % 10; //显示键码
  56. }
复制代码
led.h
  1. #ifndef __LED_H
  2. #define __LED_H
  3. uExternTask(display_task);
  4. void showKeyCode(s_u8_t keyCode);
  5. void refreshDisplay(s_u8_t hour, s_u8_t minute, s_u16_t msecond);
  6. #endif
复制代码
rtc.c
  1. #include "..\System\os_link.h"
  2. #include "..\User\rtc.h"
  3. #include "..\User\led.h"
  4. s_u8_t  hour,minute,second; //RTC变量
  5. s_u16_t msecond;
  6. void RTC(void)
  7. {
  8.     if(++second >= 60)
  9.     {
  10.         second = 0;
  11.         if(++minute >= 60)
  12.         {
  13.             minute = 0;
  14.             if(++hour >= 24) {
  15.                                 hour = 0;
  16.                         }
  17.         }
  18.     }
  19. }
  20. uCreateTask(rtc_task, 5, 32, 0, 0) {
  21.         hour = 12;
  22.         minute = 0;
  23.         second = 0;
  24.         msecond = 0;
  25.         while(1) {
  26.                 msecond += 500;
  27.                 if(msecond >= 1000) {
  28.                         msecond = 0;
  29.                         RTC();
  30.                 }
  31.         refreshDisplay(hour, minute, msecond);
  32.                
  33.                 uDelay_ms(500);
  34.         }
  35.        
  36.         uEndTasking;
  37. }
  38. void addHour(void) {
  39.         if(++hour >= 24) {
  40.                 hour = 0;
  41.         }
  42.        
  43.         refreshDisplay(hour, minute, msecond);
  44. }
  45. void decHour(void) {
  46.         if(--hour >= 24) {
  47.                 hour = 23;
  48.         }   
  49.         refreshDisplay(hour, minute, msecond);
  50. }
  51. void addMin(void) {
  52.         second = 0;
  53.     if(++minute >= 60) {
  54.                 minute = 0;
  55.         }
  56. }
  57. void decMin(void) {
  58.         second = 0;
  59.     if(--minute >= 60) {        // 这里就很巧妙,利用溢出
  60.                  minute = 59;
  61.         }
  62. }
复制代码
rtc.h
  1. #ifndef __RTC_H
  2. #define __RTC_H
  3. void addHour(void);
  4. void decHour(void);
  5. void addMin(void);
  6. void decMin(void);
  7. void RTC(void);
  8. uExternTask(rtc_task);
  9. #endif
复制代码
key.c
  1. #include "..\System\os_link.h"
  2. #include "..\User\rtc.h"
  3. #include "..\User\key.h"
  4. #include "..\User\led.h"
  5. s_u8_t  KeyCode;    //给用户使用的键码, 1~16有效
  6. s_u8_t IO_KeyState, IO_KeyState1, IO_KeyHoldCnt;    //行列键盘变量
  7. s_u8_t code T_KeyTable[16] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};
  8. void IO_KeyDelay(void)
  9. {
  10.     s_u8_t i;
  11.     i = 60;
  12.     while(--i);
  13. }
  14. void IO_KeyScan(void)    //50ms call
  15. {
  16.     s_u8_t  j;
  17.     j = IO_KeyState1;   //保存上一次状态
  18.     P0 = 0xf0;  //X低,读Y
  19.     IO_KeyDelay();
  20.     IO_KeyState1 = P0 & 0xf0;
  21.     P0 = 0x0f;  //Y低,读X
  22.     IO_KeyDelay();
  23.     IO_KeyState1 |= (P0 & 0x0f);
  24.     IO_KeyState1 ^= 0xff;   //取反
  25.    
  26.     if(j == IO_KeyState1)   //连续两次读相等
  27.     {
  28.         j = IO_KeyState;
  29.         IO_KeyState = IO_KeyState1;
  30.         if(IO_KeyState != 0)    //有键按下
  31.         {
  32.             F0 = 0;
  33.             if(j == 0)  F0 = 1; //第一次按下
  34.             else if(j == IO_KeyState)
  35.             {
  36.                 if(++IO_KeyHoldCnt >= 20)   //1秒后重键
  37.                 {
  38.                     IO_KeyHoldCnt = 18;
  39.                     F0 = 1;
  40.                 }
  41.             }
  42.             if(F0)
  43.             {
  44.                 j = T_KeyTable[IO_KeyState >> 4];
  45.                 if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0))
  46.                     KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16;    //计算键码,17~32
  47.             }
  48.         }
  49.         else    IO_KeyHoldCnt = 0;
  50.     }
  51.     P0 = 0xff;
  52. }
  53. uCreateTask(key_task, 4, 32,0 ,0) {
  54.         while(1) {
  55.                 IO_KeyScan();
  56.                
  57.                 if(KeyCode > 0)     //有键按下
  58.         {
  59.                         showKeyCode(KeyCode);
  60.             if(KeyCode == 25)   //hour +1
  61.             {
  62.                 addHour();
  63.             }
  64.             if(KeyCode == 26)   //hour -1
  65.             {
  66.                 decHour();
  67.             }
  68.             if(KeyCode == 27)   //minute +1
  69.             {
  70.                 addMin();
  71.             }
  72.             if(KeyCode == 28)   //minute -1
  73.             {
  74.                 decMin();
  75.             }
  76.             KeyCode = 0;
  77.         }
  78.                
  79.                
  80.                 uDelay_ms(50);
  81.         }
  82.        
  83.         uEndTasking;
  84. }
复制代码
key.h
  1. #ifndef __KEY_H
  2. #define __KEY_H
  3. uExternTask(key_task);
  4. #endif
复制代码
3、修改初始化钩子和启动钩子
  1. /**************************************************************************//**
  2. * @item     CosyOS-II Hook
  3. * @file     init_hook.c
  4. * @brief    初始化钩子
  5. * @detail   在主函数中首先被调用,适用于初始化时钟、GPIO、寄存器等工作。
  6. * @author   迟凯峰
  7. * @version  V3.0.0
  8. * @date     2024.06.25
  9. ******************************************************************************/
  10. #include "..\System\os_link.h"
  11. void initGPIO(void) {
  12.         P0M1 = 0x30;   P0M0 = 0x30;   //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
  13.     P1M0 = 0; P1M1 = 0;
  14.     P2M0 = 0; P2M1 = 0;
  15.     P3M0 = 0; P3M1 = 0;
  16.     P4M0 = 0; P4M1 = 0;
  17.     P5M0 = 0; P5M1 = 0;
  18.         P6M1 = 0xff;   P6M0 = 0xff;   //设置为漏极开路(实验箱加了上拉电阻到3.3V)
  19.     P7M1 = 0x00;   P7M0 = 0x00;   //设置为准双向口
  20. }
  21. void init_hook(void)
  22. {
  23.         #define BAUD  115200 // 串口波特率
  24.     #define TM2   (65536 - SYSCFG_SYSCLK / 4 / BAUD)
  25.    
  26.         initGPIO();                // 初始化GPIO
  27.        
  28.        
  29.     AUXR  =        0x00;  // 允许访问内部xdata
  30.     P_SW2 =        EAXFR | 0x01; // xxxx xxxx = 1000 0000 允许访问扩展RAM区特殊功能寄存器, 我是用的是STCH试验箱,因此这里需要切换串口二的引脚;
  31.    
  32.     TMOD = 0x00;   // 定时器0、1、2、3、4为16位自动重装载模式
  33.     AUXR = 0x45;   // 定时器1、2为1T模式,  串口1用定时器2做波特率发生器
  34.     SCON = 0x40;   // 串口1工作模式为模式1
  35.     S2CON = 0x40;  // 串口2工作模式为模式0,串口2用定时器2做波特率发生器
  36.     P_SW1 = 0xC0;  // 串口1切换至P4.3/P4.4
  37.     TI = 1;        // 用于printf
  38.     /* 定时器2 */
  39.     T2L = (unsigned char)TM2;
  40.     T2H = (unsigned char)(TM2 >> 8);
  41.     AUXR|= T2R;
  42.     /* UART2中断优先级为1级 */
  43.     IP2H &=~PS2H;
  44.     IP2 |= PS2;
  45.     /* INT0中断优先级为0级 */
  46.     IPH &=~PX0H;
  47.     PX0 = 0;
  48.     /* 任务管理器 */
  49.     #if SYSCFG_DEBUGGING == 1
  50.     S2CON |= S2REN;
  51.     IE2 |= ES2;
  52.     #endif
  53. }
复制代码


效果演示:





点评

如果你 启用了 CosyOS 的软件RTC,就可以用更高明的方法来实现这些功能。 1、display_task 中,更新 P7、P6 的工作 在 滴答钩子中执行,每滴答周期执行一次。 2、refreshDisplay 这个函数的功能,可全部在 滴答钩子  详情 回复 发表于 2024-11-26 16:10
现在貌似任务已经正常运行,但仍存在一些不可靠因素,需一步优化、调整。 1、refreshDisplay 应被定义为 不可重入函数,因为它被设计用来固定写访问全局数组 LED8[]。 三个任务都调用了该函数, display_task 无所谓  详情 回复 发表于 2024-11-26 14:41
1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
不争是争
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-11-26 14:41:49 | 显示全部楼层
本帖最后由 CosyOS 于 2024-11-26 15:27 编辑
大*** 发表于 2024-11-26 09:45
STC8试验箱例程16 用CosyOS实现

例程16的功能是:

现在貌似任务已经正常运行,但仍存在一些不可靠因素,需一步优化、调整。


1、refreshDisplay 应被定义为 不可重入函数,因为它被设计用来固定写访问全局数组 LED8[]。
三个任务都调用了该函数,
display_task 无所谓,因为仅初始化时调用一次;
rtc_task、key_task,可能会频繁调用该函数,而它们的任务优先级又不相同,长时间运行后,有 高优先级任务 打断 低优先级任务 的可能,导致在概率上必然存在 refreshDisplay 重入。


2、rtc_task、key_task,都会访问全局的RTC变量,对它们进行 读、写、自运算。
由于自运算的存在,每个变量(hour, minute, second, msecond)都要保证不会重入(自运算过程不可打断);
同时,hour, minute, second, msecond 也应做为一个整体来看,保证整体的不会重入;
由于 这两个任务的优先级不同,所以在概率上必然存在 RTC变量 重入。

综上所述,把三个任务都调整为相同的优先级(display_task 可以用不同优先级),且保证每个任务的运行时间(while(1)中,从头到 uDelay_ms 之前)都小于时间片,可能是一种比较好的实现互斥访问的方法,整体运行也将会非常可靠。(当然也可以考虑 任务临界区 等其它的互斥访问方法,但我认为 相同优先级的方法最好。)
如此的话,display_task 中,uDelay_ms(1) 可能需要适当延长,相同优先级的话。
另外,也许还存在其它一些我看不到的问题,就要靠你自己多思考了。

其它提示:
1、display_task 中,更新 P7、P6 的工作 可考虑在 滴答钩子中执行,每滴答周期执行一次。(就不需要 display_task 了)
     这将会是一个非常好的方法,推荐采用!
2、可考虑结合 CosyOS 的 软件RTC,一并应用。





回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:432
  • 最近打卡:2025-05-01 16:19:56

5

主题

1127

回帖

4263

积分

荣誉版主

积分
4263
发表于 2024-11-26 16:10:42 | 显示全部楼层
本帖最后由 CosyOS 于 2024-11-26 16:13 编辑
大*** 发表于 2024-11-26 09:45
STC8试验箱例程16 用CosyOS实现

例程16的功能是:

如果你 启用了 CosyOS 的软件RTC,就可以用更高明的方法来实现这些功能。
1、display_task 中,更新 P7、P6 的工作 在 滴答钩子中执行,每滴答周期执行一次。
2、refreshDisplay 这个函数的功能,可全部在 滴答钩子中实现,不再需要此函数。
3、rtc_task 也不再需要,因为 RTC 将由 OS 更新。
4、仅需要一个 key_task 就可以了,在 key_task 中,先获取RTC到本地,
     而后按键导致的时间变化也更新本地的,最后再设置RTC。

如此,仅需一个 key_task 就可实现全部这些功能。
有兴趣的话,你自己尝试一下吧!
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-05-01 10:58:55

44

主题

230

回帖

2841

积分

金牌会员

积分
2841
发表于 2024-11-26 20:59:27 | 显示全部楼层
hsr*** 发表于 2023-5-6 14:00
膜拜大神,坐等向sdcc编译器的迁移

爬楼中,遇到了大佬

点评

别别别……我只是个爱热闹的外行……  发表于 2024-11-26 21:29
不争是争
回复 支持 反对

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:468
  • 最近打卡:2025-05-01 10:58:55

44

主题

230

回帖

2841

积分

金牌会员

积分
2841
发表于 2024-12-2 00:16:48 | 显示全部楼层
试验箱例程16 通过CosyOS实现改版

上一个版本存在一些问题,在迟老师的耐心细致的指导下,结合最新版的CosyOS 重新实现,最终只保留一个key_task;

思路:
key_task 做按键检查,使用矩阵键盘,行列扫描的方式实现;
原来的模拟RTC任务rtc_task 使用CosyOS的软件RTC实现;
原来的显示数据发送任务led_task 使用滴答钩子实现;

具体代码:
key_task.c:
  1. #include "..\System\os_link.h"
  2. #include "..\User\key.h"
  3. #include "..\User\led.h"
  4. s_u8_t  KeyCode;    //给用户使用的键码, 1~16有效
  5. s_u8_t IO_KeyState, IO_KeyState1, IO_KeyHoldCnt;    //行列键盘变量
  6. s_u8_t code T_KeyTable[16] = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};
  7. void IO_KeyDelay(void)
  8. {
  9.     s_u8_t i;
  10.     i = 60;
  11.     while(--i);
  12. }
  13. void IO_KeyScan(void)    //50ms call
  14. {
  15.     s_u8_t  j;
  16.     j = IO_KeyState1;   //保存上一次状态
  17.     P0 = 0xf0;  //X低,读Y
  18.     IO_KeyDelay();
  19.     IO_KeyState1 = P0 & 0xf0;
  20.     P0 = 0x0f;  //Y低,读X
  21.     IO_KeyDelay();
  22.     IO_KeyState1 |= (P0 & 0x0f);
  23.     IO_KeyState1 ^= 0xff;   //取反
  24.    
  25.     if(j == IO_KeyState1)   //连续两次读相等
  26.     {
  27.         j = IO_KeyState;
  28.         IO_KeyState = IO_KeyState1;
  29.         if(IO_KeyState != 0)    //有键按下
  30.         {
  31.             F0 = 0;
  32.             if(j == 0)  F0 = 1; //第一次按下
  33.             else if(j == IO_KeyState)
  34.             {
  35.                 if(++IO_KeyHoldCnt >= 20)   //1秒后重键
  36.                 {
  37.                     IO_KeyHoldCnt = 18;
  38.                     F0 = 1;
  39.                 }
  40.             }
  41.             if(F0)
  42.             {
  43.                 j = T_KeyTable[IO_KeyState >> 4];
  44.                 if((j != 0) && (T_KeyTable[IO_KeyState& 0x0f] != 0))
  45.                     KeyCode = (j - 1) * 4 + T_KeyTable[IO_KeyState & 0x0f] + 16;    //计算键码,17~32
  46.             }
  47.         }
  48.         else    IO_KeyHoldCnt = 0;
  49.     }
  50.     P0 = 0xff;
  51. }
  52. uCreateTask(key_task, 4, 32,0 ,0) {
  53.         while(1) {
  54.                 IO_KeyScan();
  55.                
  56.                 if(KeyCode > 0)     //有键按下
  57.         {
  58.                         s_rtc_ts u_rtc;
  59.                         showKeyCode(KeyCode);
  60.                        
  61.                         uGetTime(&u_rtc);        // 获取RTC到本地
  62.             if(KeyCode == 25)   //hour +1
  63.             {
  64.                 if(++u_rtc.hour >= 24) {
  65.                                         u_rtc.hour = 0;
  66.                                 }
  67.             }
  68.             if(KeyCode == 26)   //hour -1
  69.             {
  70.                if(--u_rtc.hour >= 24) {
  71.                                         u_rtc.hour = 23;
  72.                            }
  73.             }
  74.             if(KeyCode == 27)   //minute +1
  75.             {
  76.                 u_rtc.second = 0;
  77.                                 if(++u_rtc.minute >= 60) {
  78.                                         u_rtc.minute = 0;
  79.                                 }
  80.             }
  81.             if(KeyCode == 28)   //minute -1
  82.             {
  83.                 u_rtc.second = 0;
  84.                                 if(--u_rtc.minute >= 60) {
  85.                                         u_rtc.minute = 59;
  86.                                 }
  87.             }
  88.                        
  89.                         uSetTime(&u_rtc);
  90.             KeyCode = 0;
  91.         }
  92.                
  93.                
  94.                 uDelay_ms(50);
  95.         }
  96.        
  97.         uEndTasking;
  98. }
复制代码


tick_hook.c
  1. /**************************************************************************//**
  2. * @item     CosyOS-II Hook
  3. * @file     tick_hook.c
  4. * @brief    滴答钩子
  5. * @detail   每个系统滴答周期,在系统滴答中断中都会被调用一次,
  6.              适用于每滴答周期/秒/分/时/日/月/年/...做一次的工作。
  7. * @note  1. 如果您在滴答钩子中调用服务,应调用滴答API。
  8.           2. 如果您在滴答钩子中调用自定义函数并且您的MCU内核为8051,自定义函数
  9.              可能需要添加using属性、或声明为相对寄存器访问。
  10.              demo1:
  11.              void your_function(void) MCUCFG_C51USING {... ...}
  12.             
  13.              demo2:
  14.              #pragma NOAREGS
  15.              void your_function(void) {... ...}
  16.              #pragma AREGS
  17. * @author   迟凯峰
  18. * @version  V3.1.0
  19. * @date     2024.11.26
  20. ******************************************************************************/
  21. #include "..\System\os_link.h"
  22. #include "..\User\led.h"
  23. #if SYSCFG_TICKHOOK == __ENABLED__
  24. void tick_hook(void) MCUCFG_C51USING
  25. {
  26.         if(true){ /* 每滴答周期执行一次 */
  27.                 refreshDisplay();
  28.                 sendData();
  29.         }
  30.         #if SYSCFG_SOFTRTC == __ENABLED__
  31.         if(s_sign_every.halfsec){
  32.                 s_sign_every.halfsec = false;
  33.                 if(true){ /* 每半秒执行一次(每半秒,first tick)*/
  34.                         setDot();
  35.                 }
  36.                 if(s_sign_every.second){
  37.                         s_sign_every.second = false;
  38.                         if(true){ /* 每秒钟执行一次(每秒,first tick)*/
  39.                                 clearDot();
  40.                         }
  41.                         if(s_sign_every.minute){
  42.                                 s_sign_every.minute = false;
  43.                                 if(true){ /* 每分钟执行一次(每分0秒,first tick)*/
  44.                                        
  45.                                 }
  46.                                 if(s_sign_every.hour){
  47.                                         s_sign_every.hour = false;
  48.                                         if(true){ /* 每小时执行一次(每时0分0秒,first tick)*/
  49.                                                
  50.                                         }
  51.                                         if(s_sign_every.day){
  52.                                                 s_sign_every.day = false;
  53.                                                 if(true){ /* 每天执行一次(每天0时0分0秒,first tick)*/
  54.                                                        
  55.                                                 }
  56.                                                 if(s_sign_every.month){
  57.                                                         s_sign_every.month = false;
  58.                                                         if(true){ /* 每月执行一次(每月1日0时0分0秒,first tick)*/
  59.                                                                
  60.                                                         }
  61.                                                         if(s_sign_every.year){
  62.                                                                 s_sign_every.year = false;
  63.                                                                 if(true){ /* 每年执行一次(每年1月1日0时0分0秒,first tick)*/
  64.                                                                        
  65.                                                                 }
  66.                                                         }
  67.                                                 }
  68.                                         }
  69.                                 }
  70.                         }
  71.                 }
  72.         }
  73.         #endif
  74. }
  75. #endif
复制代码
led.c
  1. #include "..\System\os_link.h"
  2. #include "..\User\led.h"
  3. #define DIS_DOT     0x20        // 0010 0000,
  4. #define DIS_BLACK   0x10       
  5. #define DIS_        0x11
  6. s_u8_t code t_display[]={                       //标准字库
  7. //   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
  8.     0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
  9. //black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
  10.     0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
  11.     0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
  12. s_u8_t code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
  13. s_u8_t LED8[8] = {1,2,3,0,0,0,0,0};
  14. void sendData(void) MCUCFG_C51USING {
  15.         static s_u8_t display_index = 0;
  16.         P7 = ~T_COM[7-display_index];
  17.         P6 = ~t_display[LED8[display_index]];
  18.         if(++display_index >= 8) {
  19.                 display_index = 0;  //8位结束回0
  20.         }
  21. }
  22. void refreshDisplay(void) MCUCFG_C51USING {
  23.        
  24.         if(s_rtc.hour >= 10) {
  25.                 LED8[0] = s_rtc.hour / 10;
  26.         } else {
  27.                 LED8[0] = DIS_BLACK;
  28.         }
  29.         LED8[1] = (LED8[1] &  DIS_DOT) | s_rtc.hour % 10;    // 这里注意,否则会导致秒点不闪
  30.         LED8[2] = s_rtc.minute / 10;
  31.         LED8[3] = s_rtc.minute % 10;
  32. }
  33. void showKeyCode(s_u8_t keyCode) {
  34.         LED8[6] = keyCode / 10; //显示键码
  35.     LED8[7] = keyCode % 10; //显示键码
  36. }
  37. void setDot(void) {
  38.         LED8[1] |= DIS_DOT;
  39. }
  40. void clearDot(void) {
  41.         LED8[1] &= ~DIS_DOT;
  42. }
复制代码


效果展示:


最后:
率先使用了CosyOS的最新版本,任务管理器的内容更加美观易读。 滴答钩子中添加了半秒处理选项;


1 喜欢他/她就送朵鲜花吧,赠人玫瑰,手有余香!
不争是争
回复 支持 反对

使用道具 举报 送花

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

本版积分规则

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

GMT+8, 2025-5-2 00:06 , Processed in 0.203595 second(s), 111 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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