大锤子
发表于 2024-11-21 09:52:35
向CosyOS成功迈出的第一步: 通过串口库助手观察任务管理器输出:
首先从作者的gitee仓库拉取最新的没有测试case的纯净版本,防止其他因素影响;
然后按照作者文档中心 -> 开发流程 创建keil 工程(为了使用CosyOS 给mac电脑装了个win系统 {:5_318:});
接下来添加需要的代码:
1、在初始化钩子中添加初始化代码:
/**************************************************************************//**
* @item CosyOS-II Hook
* @file init_hook.c
* @brief 初始化钩子
* @detail 在主函数中首先被调用,适用于初始化时钟、GPIO、寄存器等工作。
* @author 迟凯峰
* @versionV3.0.0
* @date 2024.06.25
******************************************************************************/
#include "..\System\os_link.h"
void init_hook(void)
{
#define BAUD115200 // 串口波特率
#define TM2 (65536 - SYSCFG_SYSCLK / 4 / BAUD)
P0M0 = 0; P0M1 = 0;
P1M0 = 0; P1M1 = 0;
P2M0 = 0; P2M1 = 0;
P3M0 = 0; P3M1 = 0;
P4M0 = 0; P4M1 = 0;
P5M0 = 0; P5M1 = 0;
P6M0 = 0; P6M1 = 0;
P7M0 = 0; P7M1 = 0;
AUXR= 0x00;// 允许访问内部xdata
P_SW2 = EAXFR | 0x01; // xxxx xxxx = 1000 0000 允许访问扩展RAM区特殊功能寄存器, 我是用的是STCH试验箱,因此这里需要切换串口二的引脚;
TMOD = 0x00; // 定时器0、1、2、3、4为16位自动重装载模式
AUXR = 0x45; // 定时器1、2为1T模式,串口1用定时器2做波特率发生器
SCON = 0x40; // 串口1工作模式为模式1
S2CON = 0x40;// 串口2工作模式为模式0,串口2用定时器2做波特率发生器
P_SW1 = 0xC0;// 串口1切换至P4.3/P4.4
TI = 1; // 用于printf
/* 定时器2 */
T2L = (unsigned char)TM2;
T2H = (unsigned char)(TM2 >> 8);
AUXR|= T2R;
/* UART2中断优先级为1级 */
IP2H &=~PS2H;
IP2 |= PS2;
/* INT0中断优先级为0级 */
IPH &=~PX0H;
PX0 = 0;
/* 任务管理器 */
#if SYSCFG_DEBUGGING == 1
S2CON |= S2REN;
IE2 |= ES2;
#endif
}
2、在用户分组下新建.C 文件编写串口处理程序(直接copy 作者的)
/**************************************************************************//**
* @item CosyOS-II User
* @file Taskmgr.c
* @brief CosyOS-II 任务管理器
* @detail 当前配置为使用UART2,用户可自行调整。
正常情况下,下方代码中,您仅需调整:UART2_Isr、中断向量号、S2CON、S2TI、S2RI、S2BUF。
您需自行初始化串口、串口中断优先级、波特率等相关配置。
* @author 迟凯峰
* @versionV1.0.2
* @date 2024.05.11
******************************************************************************/
#include "..\System\os_link.h"
#if SYSCFG_DEBUGGING == __ENABLED__
void UART2_Isr(void) interrupt 8// using 3
{
if(S2CON & S2TI){
S2CON &= ~S2TI;
if(*s_debug_sendptr){
S2BUF = *s_debug_sendptr++;
}
else{
iDebugSend;
}
}
if(S2CON & S2RI){
S2CON &= ~S2RI;
if(s_debug_recvptr - s_debug_recvbuff < OS_DEBUGRECVBUFFSIZE - 1){
*s_debug_recvptr++ = S2BUF;
}
iDebugRecv;
}
}
#endif
由于使用了串口二,需要使用LINK1D的另一组串口,接线如下:
效果如下:
CosyOS
发表于 2024-11-21 12:49:13
大锤子 发表于 2024-11-21 09:52
向CosyOS成功迈出的第一步: 通过串口库助手观察任务管理器输出:
{:5_332:}
任务管理器相关命令:
开启任务管理器:taskmgr
退出任务管理器:exit
设置任务管理器更新速度:taskmgr /s=xxx
xxx: 50~5000, 单位毫秒。
命令结尾要加 回车换行 \r\n
要靠串口助手自动加,而不是写到命令中。
大锤子
发表于 2024-11-22 14:34:46
使用CosyOS点亮试验箱的流水灯:
1、在用户组中添加led.h 头文件,和 led.c源文件:
这里有个小疑问, led.c 文件中的两个变量是全局变量把, 任务是不是不可重入的;
#ifndef __LED_H
#define __LED_H
dExternTask(led_flow);// 在头文件中声明任务
#endif#include "..\User\led.h"
#include "..\System\os_link.h"
s_u8_t xdata ledIndex;
s_u8_t code ledNum[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
uCreateTask(led_flow, 1, 32,0,0) {
P6 = ~ledNum; //输出低驱动
ledIndex++;
if(ledIndex > 7)
{
ledIndex = 0;
}
uDelay_ms(300);
uEndTasking;
}
2、在初始化钩子中设置端口,并且打开led电源开关:
P6M1 = 0x00; P6M0 = 0xff; //设置为推挽输出
P40 = 0; //LED Power On
3、在启动钩子中启动任务:
/**************************************************************************//**
* @item CosyOS-II Hook
* @file start_hook.c
* @brief 启动钩子
* @detail 在启动任务中被调用,可在此启动用户任务。
* @serviceuStartTask(task, status); 启动任务
uStartTask_Ready(task); 启动任务并就绪
uStartTask_Suspend(task); 启动任务并挂起
* @author 迟凯峰
* @versionV3.0.0
* @date 2024.06.25
******************************************************************************/
#include "..\System\os_link.h"
#include "stdio.h"
#include "..\User\led.h"
void start_hook(void)
{
uStartTask(led_flow, 0);
}
看流水灯和任务管理器效果:
CosyOS
发表于 2024-11-22 17:10:24
大锤子 发表于 2024-11-22 14:34
使用CosyOS点亮试验箱的流水灯:
任务创建 要 注意 动态 或 静态 的问题,
uCreateTask:静态创建
uExternTask:静态声明
dCreateTask:动态创建
dExternTask:动态声明
静态创建的要静态声明,动态创建的要动态声明,否则编译器应该会有警告!
大锤子
发表于 2024-11-22 19:14:42
CosyOS 发表于 2024-11-22 17:10
任务创建 要 注意 动态 或 静态 的问题,
uCreateTask:静态创建
哦哦,原来如此,确实有告警,没来得及看原因。
大锤子
发表于 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:
内容如下:
led.c:
#include "..\System\os_link.h"
#include "..\User\led.h"
#define DIS_DOT 0x20
#define DIS_BLACK 0x10
#define DIS_ 0x11
s_u8_t code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black- H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
s_u8_t code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
s_u8_tLED8; //显示缓冲
s_u8_tdisplay_index;//显示位索引
uCreateTask(display_task, 6, 32, 0 ,0 ) {// 创建任务,名称为display_task,优先级为6,给定任务栈大小为32字节;
s_u8_t i;
for(i=0; i<8; i++) {
LED8 = 0x10; //上电消隐
}
display_index = 0;
refreshDisplay(12, 30, 0);
while (1) {
P7 = ~T_COM;
P6 = ~t_display];
if(++display_index >= 8) {
display_index = 0;//8位结束回0
}
uDelay_ms(1); // 1毫秒延时, 延时时间到后发送数据到595
}
uEndTasking;
}
void refreshDisplay(s_u8_t hour, s_u8_t minute, s_u16_t msecond) {
if(hour >= 10) {
LED8 = hour / 10;
}
else {
LED8 = DIS_BLACK;
}
LED8 = hour % 10;
LED8 = minute / 10;
LED8 = minute % 10;
if(msecond >= 500) {
LED8 |= DIS_DOT; //小时后的小数点做秒闪
}
}
void showKeyCode(s_u8_t keyCode) {
LED8 = keyCode / 10; //显示键码
LED8 = keyCode % 10; //显示键码
}led.h
#ifndef __LED_H
#define __LED_H
uExternTask(display_task);
void showKeyCode(s_u8_t keyCode);
void refreshDisplay(s_u8_t hour, s_u8_t minute, s_u16_t msecond);
#endifrtc.c
#include "..\System\os_link.h"
#include "..\User\rtc.h"
#include "..\User\led.h"
s_u8_thour,minute,second; //RTC变量
s_u16_t msecond;
void RTC(void)
{
if(++second >= 60)
{
second = 0;
if(++minute >= 60)
{
minute = 0;
if(++hour >= 24) {
hour = 0;
}
}
}
}
uCreateTask(rtc_task, 5, 32, 0, 0) {
hour = 12;
minute = 0;
second = 0;
msecond = 0;
while(1) {
msecond += 500;
if(msecond >= 1000) {
msecond = 0;
RTC();
}
refreshDisplay(hour, minute, msecond);
uDelay_ms(500);
}
uEndTasking;
}
void addHour(void) {
if(++hour >= 24) {
hour = 0;
}
refreshDisplay(hour, minute, msecond);
}
void decHour(void) {
if(--hour >= 24) {
hour = 23;
}
refreshDisplay(hour, minute, msecond);
}
void addMin(void) {
second = 0;
if(++minute >= 60) {
minute = 0;
}
}
void decMin(void) {
second = 0;
if(--minute >= 60) { // 这里就很巧妙,利用溢出
minute = 59;
}
}
rtc.h
#ifndef __RTC_H
#define __RTC_H
void addHour(void);
void decHour(void);
void addMin(void);
void decMin(void);
void RTC(void);
uExternTask(rtc_task);
#endifkey.c
#include "..\System\os_link.h"
#include "..\User\rtc.h"
#include "..\User\key.h"
#include "..\User\led.h"
s_u8_tKeyCode; //给用户使用的键码, 1~16有效
s_u8_t IO_KeyState, IO_KeyState1, IO_KeyHoldCnt; //行列键盘变量
s_u8_t code T_KeyTable = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};
void IO_KeyDelay(void)
{
s_u8_t i;
i = 60;
while(--i);
}
void IO_KeyScan(void) //50ms call
{
s_u8_tj;
j = IO_KeyState1; //保存上一次状态
P0 = 0xf0;//X低,读Y
IO_KeyDelay();
IO_KeyState1 = P0 & 0xf0;
P0 = 0x0f;//Y低,读X
IO_KeyDelay();
IO_KeyState1 |= (P0 & 0x0f);
IO_KeyState1 ^= 0xff; //取反
if(j == IO_KeyState1) //连续两次读相等
{
j = IO_KeyState;
IO_KeyState = IO_KeyState1;
if(IO_KeyState != 0) //有键按下
{
F0 = 0;
if(j == 0)F0 = 1; //第一次按下
else if(j == IO_KeyState)
{
if(++IO_KeyHoldCnt >= 20) //1秒后重键
{
IO_KeyHoldCnt = 18;
F0 = 1;
}
}
if(F0)
{
j = T_KeyTable;
if((j != 0) && (T_KeyTable != 0))
KeyCode = (j - 1) * 4 + T_KeyTable + 16; //计算键码,17~32
}
}
else IO_KeyHoldCnt = 0;
}
P0 = 0xff;
}
uCreateTask(key_task, 4, 32,0 ,0) {
while(1) {
IO_KeyScan();
if(KeyCode > 0) //有键按下
{
showKeyCode(KeyCode);
if(KeyCode == 25) //hour +1
{
addHour();
}
if(KeyCode == 26) //hour -1
{
decHour();
}
if(KeyCode == 27) //minute +1
{
addMin();
}
if(KeyCode == 28) //minute -1
{
decMin();
}
KeyCode = 0;
}
uDelay_ms(50);
}
uEndTasking;
}key.h
#ifndef __KEY_H
#define __KEY_H
uExternTask(key_task);
#endif3、修改初始化钩子和启动钩子
/**************************************************************************//**
* @item CosyOS-II Hook
* @file init_hook.c
* @brief 初始化钩子
* @detail 在主函数中首先被调用,适用于初始化时钟、GPIO、寄存器等工作。
* @author 迟凯峰
* @versionV3.0.0
* @date 2024.06.25
******************************************************************************/
#include "..\System\os_link.h"
void initGPIO(void) {
P0M1 = 0x30; P0M0 = 0x30; //设置P0.4、P0.5为漏极开路(实验箱加了上拉电阻到3.3V)
P1M0 = 0; P1M1 = 0;
P2M0 = 0; P2M1 = 0;
P3M0 = 0; P3M1 = 0;
P4M0 = 0; P4M1 = 0;
P5M0 = 0; P5M1 = 0;
P6M1 = 0xff; P6M0 = 0xff; //设置为漏极开路(实验箱加了上拉电阻到3.3V)
P7M1 = 0x00; P7M0 = 0x00; //设置为准双向口
}
void init_hook(void)
{
#define BAUD115200 // 串口波特率
#define TM2 (65536 - SYSCFG_SYSCLK / 4 / BAUD)
initGPIO(); // 初始化GPIO
AUXR= 0x00;// 允许访问内部xdata
P_SW2 = EAXFR | 0x01; // xxxx xxxx = 1000 0000 允许访问扩展RAM区特殊功能寄存器, 我是用的是STCH试验箱,因此这里需要切换串口二的引脚;
TMOD = 0x00; // 定时器0、1、2、3、4为16位自动重装载模式
AUXR = 0x45; // 定时器1、2为1T模式,串口1用定时器2做波特率发生器
SCON = 0x40; // 串口1工作模式为模式1
S2CON = 0x40;// 串口2工作模式为模式0,串口2用定时器2做波特率发生器
P_SW1 = 0xC0;// 串口1切换至P4.3/P4.4
TI = 1; // 用于printf
/* 定时器2 */
T2L = (unsigned char)TM2;
T2H = (unsigned char)(TM2 >> 8);
AUXR|= T2R;
/* UART2中断优先级为1级 */
IP2H &=~PS2H;
IP2 |= PS2;
/* INT0中断优先级为0级 */
IPH &=~PX0H;
PX0 = 0;
/* 任务管理器 */
#if SYSCFG_DEBUGGING == 1
S2CON |= S2REN;
IE2 |= ES2;
#endif
}
效果演示:
CosyOS
发表于 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,一并应用。
CosyOS
发表于 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 就可实现全部这些功能。
有兴趣的话,你自己尝试一下吧!
大锤子
发表于 2024-11-26 20:59:27
hsrzq 发表于 2023-5-6 14:00
膜拜大神,坐等向sdcc编译器的迁移
爬楼中,遇到了大佬
大锤子
发表于 2024-12-2 00:16:48
试验箱例程16 通过CosyOS实现改版
上一个版本存在一些问题,在迟老师的耐心细致的指导下,结合最新版的CosyOS 重新实现,最终只保留一个key_task;
思路:
key_task 做按键检查,使用矩阵键盘,行列扫描的方式实现;
原来的模拟RTC任务rtc_task 使用CosyOS的软件RTC实现;
原来的显示数据发送任务led_task 使用滴答钩子实现;
具体代码:
key_task.c:
#include "..\System\os_link.h"
#include "..\User\key.h"
#include "..\User\led.h"
s_u8_tKeyCode; //给用户使用的键码, 1~16有效
s_u8_t IO_KeyState, IO_KeyState1, IO_KeyHoldCnt; //行列键盘变量
s_u8_t code T_KeyTable = {0,1,2,0,3,0,0,0,4,0,0,0,0,0,0,0};
void IO_KeyDelay(void)
{
s_u8_t i;
i = 60;
while(--i);
}
void IO_KeyScan(void) //50ms call
{
s_u8_tj;
j = IO_KeyState1; //保存上一次状态
P0 = 0xf0;//X低,读Y
IO_KeyDelay();
IO_KeyState1 = P0 & 0xf0;
P0 = 0x0f;//Y低,读X
IO_KeyDelay();
IO_KeyState1 |= (P0 & 0x0f);
IO_KeyState1 ^= 0xff; //取反
if(j == IO_KeyState1) //连续两次读相等
{
j = IO_KeyState;
IO_KeyState = IO_KeyState1;
if(IO_KeyState != 0) //有键按下
{
F0 = 0;
if(j == 0)F0 = 1; //第一次按下
else if(j == IO_KeyState)
{
if(++IO_KeyHoldCnt >= 20) //1秒后重键
{
IO_KeyHoldCnt = 18;
F0 = 1;
}
}
if(F0)
{
j = T_KeyTable;
if((j != 0) && (T_KeyTable != 0))
KeyCode = (j - 1) * 4 + T_KeyTable + 16; //计算键码,17~32
}
}
else IO_KeyHoldCnt = 0;
}
P0 = 0xff;
}
uCreateTask(key_task, 4, 32,0 ,0) {
while(1) {
IO_KeyScan();
if(KeyCode > 0) //有键按下
{
s_rtc_ts u_rtc;
showKeyCode(KeyCode);
uGetTime(&u_rtc); // 获取RTC到本地
if(KeyCode == 25) //hour +1
{
if(++u_rtc.hour >= 24) {
u_rtc.hour = 0;
}
}
if(KeyCode == 26) //hour -1
{
if(--u_rtc.hour >= 24) {
u_rtc.hour = 23;
}
}
if(KeyCode == 27) //minute +1
{
u_rtc.second = 0;
if(++u_rtc.minute >= 60) {
u_rtc.minute = 0;
}
}
if(KeyCode == 28) //minute -1
{
u_rtc.second = 0;
if(--u_rtc.minute >= 60) {
u_rtc.minute = 59;
}
}
uSetTime(&u_rtc);
KeyCode = 0;
}
uDelay_ms(50);
}
uEndTasking;
}
tick_hook.c
/**************************************************************************//**
* @item CosyOS-II Hook
* @file tick_hook.c
* @brief 滴答钩子
* @detail 每个系统滴答周期,在系统滴答中断中都会被调用一次,
适用于每滴答周期/秒/分/时/日/月/年/...做一次的工作。
* @note1. 如果您在滴答钩子中调用服务,应调用滴答API。
2. 如果您在滴答钩子中调用自定义函数并且您的MCU内核为8051,自定义函数
可能需要添加using属性、或声明为相对寄存器访问。
demo1:
void your_function(void) MCUCFG_C51USING {... ...}
demo2:
#pragma NOAREGS
void your_function(void) {... ...}
#pragma AREGS
* @author 迟凯峰
* @versionV3.1.0
* @date 2024.11.26
******************************************************************************/
#include "..\System\os_link.h"
#include "..\User\led.h"
#if SYSCFG_TICKHOOK == __ENABLED__
void tick_hook(void) MCUCFG_C51USING
{
if(true){ /* 每滴答周期执行一次 */
refreshDisplay();
sendData();
}
#if SYSCFG_SOFTRTC == __ENABLED__
if(s_sign_every.halfsec){
s_sign_every.halfsec = false;
if(true){ /* 每半秒执行一次(每半秒,first tick)*/
setDot();
}
if(s_sign_every.second){
s_sign_every.second = false;
if(true){ /* 每秒钟执行一次(每秒,first tick)*/
clearDot();
}
if(s_sign_every.minute){
s_sign_every.minute = false;
if(true){ /* 每分钟执行一次(每分0秒,first tick)*/
}
if(s_sign_every.hour){
s_sign_every.hour = false;
if(true){ /* 每小时执行一次(每时0分0秒,first tick)*/
}
if(s_sign_every.day){
s_sign_every.day = false;
if(true){ /* 每天执行一次(每天0时0分0秒,first tick)*/
}
if(s_sign_every.month){
s_sign_every.month = false;
if(true){ /* 每月执行一次(每月1日0时0分0秒,first tick)*/
}
if(s_sign_every.year){
s_sign_every.year = false;
if(true){ /* 每年执行一次(每年1月1日0时0分0秒,first tick)*/
}
}
}
}
}
}
}
}
#endif
}
#endif
led.c
#include "..\System\os_link.h"
#include "..\User\led.h"
#define DIS_DOT 0x20 // 0010 0000,
#define DIS_BLACK 0x10
#define DIS_ 0x11
s_u8_t code t_display[]={ //标准字库
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black- H J K L N o P U t G Q r M y
0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1
s_u8_t code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码
s_u8_t LED8 = {1,2,3,0,0,0,0,0};
void sendData(void) MCUCFG_C51USING {
static s_u8_t display_index = 0;
P7 = ~T_COM;
P6 = ~t_display];
if(++display_index >= 8) {
display_index = 0;//8位结束回0
}
}
void refreshDisplay(void) MCUCFG_C51USING {
if(s_rtc.hour >= 10) {
LED8 = s_rtc.hour / 10;
} else {
LED8 = DIS_BLACK;
}
LED8 = (LED8 &DIS_DOT) | s_rtc.hour % 10; // 这里注意,否则会导致秒点不闪
LED8 = s_rtc.minute / 10;
LED8 = s_rtc.minute % 10;
}
void showKeyCode(s_u8_t keyCode) {
LED8 = keyCode / 10; //显示键码
LED8 = keyCode % 10; //显示键码
}
void setDot(void) {
LED8 |= DIS_DOT;
}
void clearDot(void) {
LED8 &= ~DIS_DOT;
}
效果展示:
最后:
率先使用了CosyOS的最新版本,任务管理器的内容更加美观易读。 滴答钩子中添加了半秒处理选项;