本文主要是介绍初试 STC8A8K64D4 库函数 + Small RTOS51 1.12,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
零、目录
零、目录
一、注意事项
二、本次期望达到的目标
三、添加 STC8A8K64D4 库函数
四、Small RTOS51 1.12 的移植
五、编写多线程测试代码
六、总结
一、注意事项
- 本次使用 STC8A8K64D4 作为 MCU,其库函数可以在 STC 官网下载:http://www.stcmcudata.com/
- 本次使用 Small RTOS51 1.12 版本,1.20 版本等以后有空了再瞅瞅,目前先用 1.12 版本的学习学习。网络上有关 1.12 版本的下载路径很多,这里暂时不单独贴出。
- Small RTOS51 在类型定义、文件命名部分与 STC8A8K64D4 相冲突,编译时将会导致报错。这里采用的解决方法是对 Small RTOS51 的文件进行小的修改,因为 Small RTOS51 也可以移植到其他的 STC 51 单片机上,如果要用到 STC 的库函数的话,这些小的修改将有利于今后的移植。
- 如果不适应 STC 库函数的话,本教程也可以适用于单纯 Small RTOS51 的移植,只需要跳过有关 Small RTOS51 的代码修改、库函数的移植和使用即可。
二、本次期望达到的目标
- 利用 STC8A8K64D4 在 33.1776MHz 的时钟下通过 UART1 打印三个任务的信息,以初步体验使用 Small RTOS51 来进行多任务操作。
- 略微小改 Small RTOS51 的部分类型、文件命名,使其可以兼容 STC8A8K64D4 的库函数,同时修改 OSWait() 的参数类型,使其数据类型便于修改,并可以实现延时时间的加长,这个步骤可以依据实际情况进行,可以不修改。如果想用寄存器而不使用库函数,则可以跳过 Small RTOS51 的修改,因为修改只是为了兼容库函数,不会影响 RTOS 的实际功能。
三、添加 STC8A8K64D4 库函数
- 在 STC 官网下载 STC8A8K64D4 库函数,解压压缩包,官方的库函数均存放于 Driver 文件夹下。
-
官方的库文件还依赖其他文件,有:Config.h、isr.arm、STC8A8K64D4.H 和 Type_def.h
-
新建 KEIL 项目,将 Driver 文件夹放到工程文件夹下,将前面提到的 4 个文件也添加到 Driver/ 路径下。
-
内存模式设置为 small 模式。
-
在 KEIL 项目中添加需要的文件,本次只需要使用以下功能:STC8A_Delay.c (延时)、STC8A_UART.c (串口输出)。同时添加库函数的中断函数 STC8A_UART_Isr.c。
-
添加 Driver/ 路径和 Driver/Inc/ 路径到项目中。
-
到 Config.h 下修改 MCU 时钟频率,本次时钟为 33177600L。
-
编写程序进行测试,查看库函数是否移植成功:
#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 的移植
- Small RTOS51 代码文件夹下有三个文件夹:CONFIG_H/、OS/、TARGET_CPU/。将这三个文件夹添加到 KEIL 项目文件夹下。由于这三个文件夹都在 Small_RTOS51/ 文件夹下,因此直接赋值该文件夹即可。
- 修改 CONFIG_H 文件夹下的 CONFIG.H 的文件名,由于库函数的 Config.h 被库函数的很多文件引用,因此这里将修改 Small RTOS51 的 CONFIG.H 头文件,避免因为重名而导致文件无法添加到 KEIL 项目中。本次将 CONFIG.H 改名为 SmallRTOS51.H(因为用户只需要包含该头文件即可调用到 Small RTOS51 的系统函数,因此仿照 rtthread.h 进行命名)。
- 到 KEIL 项目中添加 Small RTOS51 的所有文件。
- 由于 OS_CPU_A.ASM 引用了 OS_CPU.H 和 OS_CFG.H,因此需要为 .asm 添加头文件路径:Option for Target → A51 → Include Paths 中添加 .h 头文件路径。
- 因为前面修改了 CONFIG.H 的文件名,因此需要到以下文件中手动修改 #include 引用的文件名 —— 修改为新命名的文件名即可。如果不使用库函数则可以跳过这一步。
OS_CORE.C OS_Q.C OS_SEM.C OS_CPU_C.C -
由于 Small RTOS51 的类型定义与库函数重叠,考虑到今后的移植,这边将对 Small RTOS51 的数据类型进行修改,如果嫌这步麻烦的阅读者可以跳过这一步。
-
利用 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位整数关键字 */
-
将 #define const code 移除,将用到 const 关键字的变量修改为 code 修饰的变量。(可做可不做)
-
在 OS_CPU.H 中,新添类型:
typedef os_uint16 os_tick_t;
添加该类型的目的是为便于修改 OSWait() 的延时时长,原版的 OSWait() 只能延时 255 个系统滴答时钟,修改为 16位 数据类型后可以延长到 65535 个系统滴答时钟,而且使用 typedef 的方法也便于类型的修改。
需要修改的函数和数组有:
函数 OSWait() 的 tick 参数 函数 OSSemPend() 的 tick 参数
函数 OSQPend() 的 tick 参数
数组 OSWaitTick[]
修改完后,OSWait() 的延时时长便可方便的进行修改了。
-
-
到 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 需要被开启,因为涉及到串口的数据发送,这里会引起新的中断,因此要加入中断嵌套管理。
-
到 OS_CPU.H 中,修改一下宏定义:
#define OS_TIME_ISR 1 /* 系统定时器使用的中断 */
由于 STC8A8K64D4 的 Timer0 的已经具备了专用于 RTOS 的 16位不可屏蔽的自动重装载模式,因此这里选用 Timer0 作为系统定时器。
-
编译项目,若无报错即移植完毕。
五、编写多线程测试代码
- 编写 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.1776MHzAUXR &= 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); }
- 修改任务列表
/********************************/ /* "以下为系统配置" */ /********************************/ #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
- 修改在库函数的 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
- 编译,若无错误则可以烧录到板子查看效果,测试效果如下:
可以看到程序正常的运行了,task1 发送数据的时间间隔基本上在 1s 左右,task2、task3 的任务信息也正常的发送了,说明多任务运行没有问题。
六、总结
- 本次成功实现了库函数与 Small RTOS51 的兼容,虽然修改了 Small RTOS51 的部分代码,但并未影响到 RTOS 的运行。
- 这次测试只测试了每个任务是否可以正常运行,之后有机会尝试信号量和消息队列,学习线程间同步和线程间通讯。
- 这次测试是在 small 模式下运行,由于 1.12 版本不支持 reentrant 任务,因此下次将测试一下线程调用 reentrant 函数会不会正常运行。
这篇关于初试 STC8A8K64D4 库函数 + Small RTOS51 1.12的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!