初试 STC8A8K64D4 库函数 + Small RTOS51 1.12

本文详细介绍了如何在STC8A8K64D4微控制器上移植SmallRTOS511.12版本,包括注意事项、目标设定、库函数的添加、SmallRTOS51的移植步骤以及多线程测试代码的编写。通过修改SmallRTOS51的数据类型以避免与库函数冲突,并调整了OSWait()的参数以增加延时灵活性。最终,成功实现了多任务的运行并通过串口验证了程序的正确性。
摘要由CSDN通过智能技术生成

零、目录

零、目录

一、注意事项

二、本次期望达到的目标

三、添加 STC8A8K64D4 库函数

四、Small RTOS51 1.12 的移植

五、编写多线程测试代码

六、总结


一、注意事项

  1. 本次使用 STC8A8K64D4 作为 MCU,其库函数可以在 STC 官网下载:http://www.stcmcudata.com/
  2. 本次使用 Small RTOS51 1.12 版本,1.20 版本等以后有空了再瞅瞅,目前先用 1.12 版本的学习学习。网络上有关 1.12 版本的下载路径很多,这里暂时不单独贴出。
  3. Small RTOS51 在类型定义、文件命名部分与 STC8A8K64D4 相冲突,编译时将会导致报错。这里采用的解决方法是对 Small RTOS51 的文件进行小的修改,因为 Small RTOS51 也可以移植到其他的 STC 51 单片机上,如果要用到 STC 的库函数的话,这些小的修改将有利于今后的移植。
  4. 如果不适应 STC 库函数的话,本教程也可以适用于单纯 Small RTOS51 的移植,只需要跳过有关 Small RTOS51 的代码修改、库函数的移植和使用即可。

       


二、本次期望达到的目标

  1. 利用 STC8A8K64D4 在 33.1776MHz 的时钟下通过 UART1 打印三个任务的信息,以初步体验使用 Small RTOS51 来进行多任务操作。
  2. 略微小改 Small RTOS51 的部分类型、文件命名,使其可以兼容 STC8A8K64D4 的库函数,同时修改 OSWait() 的参数类型,使其数据类型便于修改,并可以实现延时时间的加长,这个步骤可以依据实际情况进行,可以不修改如果想用寄存器而不使用库函数,则可以跳过 Small RTOS51 的修改,因为修改只是为了兼容库函数,不会影响 RTOS 的实际功能。

        


三、添加 STC8A8K64D4 库函数

  1. 在 STC 官网下载 STC8A8K64D4 库函数,解压压缩包,官方的库函数均存放于 Driver 文件夹下。
  2. 官方的库文件还依赖其他文件,有:Config.h、isr.arm、STC8A8K64D4.H 和 Type_def.h

  3. 新建 KEIL 项目,将 Driver 文件夹放到工程文件夹下,将前面提到的 4 个文件也添加到 Driver/ 路径下。

  4. 内存模式设置为 small 模式。

  5. 在 KEIL 项目中添加需要的文件,本次只需要使用以下功能:STC8A_Delay.c (延时)、STC8A_UART.c (串口输出)。同时添加库函数的中断函数 STC8A_UART_Isr.c。

  6. 添加 Driver/ 路径和 Driver/Inc/ 路径到项目中。

  7. 到 Config.h 下修改 MCU 时钟频率,本次时钟为 33177600L。

  8. 编写程序进行测试,查看库函数是否移植成功:

    #include "Config.h"
    #include "STC8A_Delay.h"
    #include "STC8A_UART.h"
    
    void main(void)
    {
    	COMx_InitDefine xdata com;
    	P_SW2 |= 0x80;
    
    	com.BaudRateDouble = DISABLE;
    	com.Morecommunicate = DISABLE;
    	com.UART_BaudRate = 115200;
    	com.UART_BRT_Use = BRT_Timer1;
    	com.UART_Mode = UART_8bit_BRTx;
    	com.UART_RxEnable = ENABLE;
    
    	UART_Configuration(UART1, &com);
    	ES = 1;
    	EA = 1;
    
    	while(1)
    	{
    		delay_ms(1000);
    		PrintString1("Hello STC8A8K Driver!\r\n");
    	}
    }

     烧录程序后到串口查看效果。

          可以看到串口正常输出,表明库函数移植完成。


四、Small RTOS51 1.12 的移植

  1.  Small RTOS51 代码文件夹下有三个文件夹:CONFIG_H/、OS/、TARGET_CPU/。将这三个文件夹添加到 KEIL 项目文件夹下。由于这三个文件夹都在 Small_RTOS51/ 文件夹下,因此直接赋值该文件夹即可。
  2. 修改 CONFIG_H 文件夹下的 CONFIG.H 的文件名,由于库函数的 Config.h 被库函数的很多文件引用,因此这里将修改 Small RTOS51 的 CONFIG.H 头文件,避免因为重名而导致文件无法添加到 KEIL  项目中本次将 CONFIG.H 改名为 SmallRTOS51.H(因为用户只需要包含该头文件即可调用到 Small RTOS51 的系统函数,因此仿照 rtthread.h 进行命名)。
  3. 到 KEIL 项目中添加 Small RTOS51 的所有文件。
  4. 由于 OS_CPU_A.ASM 引用了 OS_CPU.H 和 OS_CFG.H,因此需要为 .asm 添加头文件路径:Option for Target → A51 → Include Paths 中添加 .h 头文件路径。
  5. 因为前面修改了 CONFIG.H 的文件名,因此需要到以下文件中手动修改 #include 引用的文件名 —— 修改为新命名的文件名即可。如果不使用库函数则可以跳过这一步。
    OS_CORE.C
    OS_Q.C
    OS_SEM.C
    OS_CPU_C.C
  6. 由于 Small RTOS51 的类型定义与库函数重叠,考虑到今后的移植,这边将对 Small RTOS51 的数据类型进行修改如果嫌这步麻烦的阅读者可以跳过这一步

    1. 利用 VSCODE,将以 “uint” 开头的类型全部替换为 “os_uint”、以 “int” 开头的类型全部替换为 “os_int”(Small RTOS51 中基本上使用的都是 uint8 类型)。

      typedef unsigned char  os_uint8;                                   /* 定义可移植的无符号8位整数关键字            */
      typedef signed   char  os_int8;                                    /* 定义可移植的有符号8位整数关键字            */
      typedef unsigned int   os_uint16;                                  /* 定义可移植的无符号16位整数关键字           */
      typedef signed   int   os_int16;                                   /* 定义可移植的有符号16位整数关键字           */
      typedef unsigned long  os_uint32;                                  /* 定义可移植的无符号32位整数关键字           */
      typedef signed   long  os_int32;                                   /* 定义可移植的有符号32位整数关键字           */
    2. 将 #define const code 移除,将用到 const 关键字的变量修改为 code 修饰的变量。(可做可不做)

    3. 在 OS_CPU.H 中,新添类型:

      typedef os_uint16	   os_tick_t;

      添加该类型的目的是为便于修改 OSWait() 的延时时长,原版的 OSWait() 只能延时 255 个系统滴答时钟,修改为 16位 数据类型后可以延长到 65535 个系统滴答时钟,而且使用 typedef 的方法也便于类型的修改。

      需要修改的函数和数组有:

      函数OSWait() 的 tick 参数
      函数

      OSSemPend() 的 tick 参数

      函数

      OSQPend() 的 tick 参数

      数组

      OSWaitTick[]

      修改完后,OSWait() 的延时时长便可方便的进行修改了。

  7. 到 OS_CFG.H 中,修改一下宏定义:

    #define OS_MAX_TASKS            3          /* 最大任务数1~16                                           */
    #define OS_TICKS_PER_SEC        0          /* 声明1秒系统系统节拍数,这个得自己计算出来   os_uint8 OSWaitTick[OS_MAX_TASKS];   */
    #define EN_USER_TICK_TIMER      0          /* 禁止(0)或允许(1)系统定时中断调用用户函数UserTickTimer() ,在系统中断中挂钩的用户计时器 */
    #define EN_OS_INT_ENTER         1           /* 禁止(0)或允许(1)中断嵌套管理                             */
    #define EN_TIMER_SHARING        1           /* 禁止(0)或允许(1) 系统 定时器中断调用OSTimeTick() ,禁止时要在高优先级任务中调用 OSTimeTick()*/
    #define TICK_TIMER_SHARING      1           /* 定义进入多少次硬件中断为一次系统定时器软中断             */

    OS_TICKS_PER_SEC 在当前版本的 Small RTOS51 中并未使用。TICK_TIMER_SHARING 意思是,累计触发若干次硬件定时器中断作为一次系统滴答计数。这里修改为 1 意味着一次硬件定时器中断就是一次系统滴答计数。EN_OS_INT_ENTER 需要被开启,因为涉及到串口的数据发送,这里会引起新的中断,因此要加入中断嵌套管理。

  8. 到 OS_CPU.H 中,修改一下宏定义:

    #define  OS_TIME_ISR     1                                     /* 系统定时器使用的中断                           */

    由于 STC8A8K64D4 的 Timer0 的已经具备了专用于 RTOS 的 16位不可屏蔽的自动重装载模式,因此这里选用 Timer0 作为系统定时器。

  9. 编译项目,若无报错即移植完毕。

       


五、编写多线程测试代码

  1. 编写 main.c
    #include "Config.h"
    #include "STC8A_Delay.h"
    #include "STC8A_UART.h"
    #include "SMALLRTOS51.H"
    
    void task1(void)
    {
    	while(1)
    	{
    		PrintString1("task1\r\n");
    		OSWait(K_TMO, 1000);
    	}
    }
    
    void task2(void)
    {
    	while(1)
    	{
    		PrintString1("\ttask2\r\n");
    		OSWait(K_TMO, 3000);
    	}
    }
    
    void task3(void)
    {
    	while(1)
    	{
    		PrintString1("\ttask3\r\n");
    		OSWait(K_TMO, 5000);
    	}
    }
    
    void main(void)
    {
    	P_SW2 |= 0x80;
    
    	do
    	{
    		// 配置系统时钟: 33.1776MHz
    		AUXR &= 0x7F;		// 定时器时钟12T模式
    		TMOD &= 0xF0;		// 设置定时器模式
    		TL0 = 0x33;			// 设置定时初始值
    		TH0 = 0xF5;			// 设置定时初始值
    		TF0 = 0;			// 清除TF0标志
    		TR0 = 1;			// 定时器0开始计时
    		ET0 = 1;			// 开启定时器中断
    	} while (0);
    	
    	do
    	{
    		COMx_InitDefine xdata com;
    		P_SW2 |= 0x80;
    
    		com.BaudRateDouble = DISABLE;
    		com.Morecommunicate = DISABLE;
    		com.UART_BaudRate = 115200;
    		com.UART_BRT_Use = BRT_Timer1;
    		com.UART_Mode = UART_8bit_BRTx;
    		com.UART_RxEnable = ENABLE;
    
    		UART_Configuration(UART1, &com);
    		ES = 1;
    	} while(0);
    
    	OSStart();
    	while(1);
    }
  2. 修改任务列表
    
    
    /********************************/
    /*     "以下为系统配置"           */
    /********************************/
    #pragma  REGPARMS
    #include "STC8A8K64D4.H"
    #include <intrins.h>
    #include <absacc.h>
    
    
    
    
    
    /********************************/
    /*     "操作系统定义"            */
    /********************************/
    #include "OS_CFG.H"
    #include "OS_CPU.H"
    #include "OS_CORE.H"
    #include "OS_SEM.H"
    #include "OS_Q.H"
    
    
    
    
    /********************************/
    /*     "以下为程序配置"           */
    /********************************/
    //任务定义
    #ifdef IN_OS_CPU_C_C               // 保证以下声明只在 OS_CPU_C中出现
    
    extern void task1(void);
    extern void task2(void);
    extern void task3(void);
    
    void  (* code TaskFuction[OS_MAX_TASKS])(void)={
    													task1,
    													task2,
    													task3
    												};
    
             //函数数组TaskFuction[]保存了各个任务初始PC指针,其按任务ID(既优先级次序)顺序保存
    #endif
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
  3. 修改在库函数的 Config.h 头文件中 #include "SmallRTOS51.h",为串口中断函数添加中断管理语句
    #ifdef UART1
    void UART1_ISR_Handler (void) interrupt UART1_VECTOR
    {
    	OS_INT_ENTER();
    	if(RI)
    	{
    		RI = 0;
    		if(COM1.B_RX_OK == 0)
    		{
    			if(COM1.RX_Cnt >= COM_RX1_Lenth)	COM1.RX_Cnt = 0;
    			RX1_Buffer[COM1.RX_Cnt++] = SBUF;
    			COM1.RX_TimeOut = TimeOutSet1;
    		}
    	}
    
    	if(TI)
    	{
    		TI = 0;
    		COM1.B_TX_busy = 0;
    	}
    
    	OSIntExit();
    }
    #endif
  4. 编译,若无错误则可以烧录到板子查看效果,测试效果如下:

         可以看到程序正常的运行了,task1 发送数据的时间间隔基本上在 1s 左右,task2、task3 的任务信息也正常的发送了,说明多任务运行没有问题。


六、总结

  • 本次成功实现了库函数与 Small RTOS51 的兼容,虽然修改了 Small RTOS51 的部分代码,但并未影响到 RTOS 的运行。
  • 这次测试只测试了每个任务是否可以正常运行,之后有机会尝试信号量和消息队列,学习线程间同步和线程间通讯。
  • 这次测试是在 small 模式下运行,由于 1.12 版本不支持 reentrant 任务,因此下次将测试一下线程调用 reentrant 函数会不会正常运行。

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值