找回密码
 立即注册
查看: 1915|回复: 19

STC32G FreeRTOS入门(3):STC32G PK STC8--完胜

[复制链接]

该用户从未签到

63

主题

703

回帖

1万

积分

荣誉版主

积分
10904
发表于 2023-8-6 14:10:59 | 显示全部楼层 |阅读模式
一、STC8H系列单片机的试验结果
1)在上篇文章“STC8位单片机前后台任务编程中的问题”中给出了结论:对于STC8H单片机,使用KeilC51编译器,“printf”这个库函数不能在前后台任务中同时使用。并指出出错的原因不是单片机,也不是程序员,出错的原因是“printf”这个库函数。
2)为了证明这个结论,还可以明显地在前后台任务中分别使用输入输出缓冲区数组,用“gets+sscanf”库函数来代替“scanf”,用“sprintf+puts”库函数来代替“printf”,进一步分析原因所在。下图是完整的使用输入输出缓冲区的程序:
STC8H_缓冲区_01.jpg
STC8H_缓冲区_02.jpg
3)在后台任务中,使用“RX_Buf”数组作为缓冲区,用第60行和第61行代替注释掉的第59行“scanf”程序,用第65行和第66行代替注释掉的第64行“printf”程序。
在前台任务中,使用“TX_Buf”数组作为缓冲区,用第80行和第81行代替原来的“printf”程序。

对于STC8H8K64U单片机,运行的效果见下面视频:
4)从视频中可以看到,前台任务的输出是正确,后台任务的输出仍然是不正确的,见下面截屏:
STC8H_缓冲区_03.jpg
从图中可以看出,对于输入字符串“987654321,123456789”,库函数“gets”的输入正确的,由于第63行的赋值程序“Z=X+Y”肯定是正确的,所以结果输出的错误一定出在“sprintf”库函数上。
5)结论:对于STC8H单片机,使用KeilC51编译器,“sprintf”这个库函数同样不能在前后台任务中同时使用。
6)知识点:“sprintf”的输出中的“NaN”(Not a Number)是“非数字值”的意思,尤其会出现在浮点数转换中,比如要转换的数值是“无穷大”或者“无穷小”。

7)知识点:在使用上位机键盘输入时,应该像截屏中那样,用一个回车(\r)作为输入结束符,如果像视频中那样用回车换行(\r\n)作为结束符,库函数“gets”会把它作为两个输入,其中第二个是空串。
二、STC32G系列单片机的试验结果
8STC32G12K128STC最新推出的一款32位单片机,它与8位的STC8H8K64U有高度的兼容性,一般的STC8H程序,只要换一个头文件就行了。

为了观察32位的单片机与8位单片机的差别,我将上面的程序中的第13STC8H包含头文件换为STC32G的头文件进行了试验,将STC8H单片机与STC32G单片机进行PK。下面是同样的前面程序在STC32G12K128单片机上运行的结果:

9)从视频上可以看到运行结果是无论前台任务或者后台任务的运行结果都是正确的。下图是截屏:
正确.jpg
其中:X+Y=1111111000,这个结果是正确的。
10)知识点:明明小学生都知道“987654321+123456789=1111111110”,为什么上图的结果“987654321+123456789=1111111000”会是正确的呢?这是因为XYZ都是单精度浮点数变量,它们的精度只有7位有效数字,所以在其精度范围内,它是正确的。
11)结论:对于STC32G单片机,使用KeilC251编译器,在前后台任务中使用“sprintf”和“puts”库函数都是正确的。
STC32G+Keil C251STC8H+KeilC51 PK的结果:完胜
三、STC32G胜之必然

12)众所周知STC8H内核是8051CPU,只有ABR0~R7108位通用寄存器做常规程序处理用,而STC32G不同,它的内核是扩展的80251CPU,其通用的寄存器如下表:
80251寄存器.jpg
13STC32G单片机有832位的通用寄存器DR0DR4DR8DR12DR16DR20DR24DR28,这些32位通用寄存器都可进行32位的运算:整数加(ADD)、整数减(SUB)、比较(CMP)和逻辑运算,其中DR0DR4还可以进行32位的整数乘法(MUL32)、32位的无符号整数除法(DIVU32)和32位的有符号整数除法(DIVI32)。也正是由于STC32G单片机能够完整地实现了所有32位的整数运算,它是一款名副其实的“32位单片机”,而传统的80251CPU不包括32位的乘除运算,一般只称为“准32位内核”。
14STC32G单片机的832位的通用寄存器每个都可以拆为高低两个16位的通用寄存器,比如DR20拆为WR2016位和WR2216位两个16位寄存器,再比如DR4拆为WR416位和WR616位两个16位寄存器,共计1616位通用寄存器。
STC32G1616位通用寄存器,全部都可以进行16位的整数加、减、乘、除、比较和逻辑运算,其中乘除运算的结果是32位的。
由于每个32位寄存器与对应的两个16位寄存器不是独立的,对其中一个的运算都可能会影响到其他两个。
15STC32G单片机的低432位的通用寄存器DR0DR4DR8DR12每个都可以再拆分为48位通用寄存器,共计16个。
STC32G168位通用寄存器,全部都可以进行8位的整数加、减、乘、除、比较和逻辑运算,其中乘除运算的结果是16位的。
由于这4个低32位寄存器与对应的两个16位寄存器以及对应的48位寄存器不是独立的,对其中一个的运算都可能会影响到其他的寄存器。
16STC32G单片机的扩展80251CPU包含一个8051CPU的全子集,其中通用寄存器R0~R78051R0~R7寄存器对应,R11A寄存器对应,R10B寄存器对应。
17)结论:由于STC32G的通用寄存器数量是STC8H4倍,因此它使用的KeilC251编译器的库函数“sprintf”可以把这些通用寄存器作为局部临时变量使用,使得该函数是可重入的函数,因此在前台和后台任务中可以同时使用。

STC8H没有那么多通用寄存器可用,它使用的KeilC51编译器的库函数“sprintf”只能把局部临时变量放到RAM中,造成该函数是不可重入的函数,所以不能同时在前台和后台任务中使用。
下面是本文使用的范例程序:
FreeRTOS_003A_缓冲区_STC8H.rar (45.26 KB, 下载次数: 62)
FreeRTOS_003B_缓冲区_STC32G.rar (48.94 KB, 下载次数: 71)
回复 送花

使用道具 举报

  • TA的每日心情
    开心
    昨天 10:04
  • 签到天数: 122 天

    [LV.7]常住居民III

    9

    主题

    92

    回帖

    590

    积分

    高级会员

    积分
    590
    发表于 2023-11-16 21:11:43 | 显示全部楼层
    版主的意思是STC32系列是不是比STC8系列更适合使用实时操作系统??

    点评

    是的  详情 回复 发表于 2023-11-17 15:03
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    63

    主题

    703

    回帖

    1万

    积分

    荣誉版主

    积分
    10904
     楼主| 发表于 2023-11-17 15:03:44 | 显示全部楼层
    lzzasd 发表于 2023-11-16 21:11
    版主的意思是STC32系列是不是比STC8系列更适合使用实时操作系统??

    是的
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    5

    主题

    89

    回帖

    401

    积分

    中级会员

    积分
    401
    发表于 2024-1-7 13:03:37 | 显示全部楼层
    本帖最后由 13918210822 于 2024-1-7 13:07 编辑

    最近为了使用STC32F上使用多任务RTOS, 再梳理一遍指令表
    发现STC32栈指针是16位SPX(DR60), 加上一个24位DPTR(DR56)

    所以,合适的讲STC32其实是一个指令在编译器支持下兼容8051的增强的8/16位机,32位乘除是通过MDU32协处理模组支持,可通过总线通过DMA反馈结果。

    从历史上将,80251的指令集出现在ARM之前,属于8位到32位过渡阶段的一个产品。
    如果真的要完整支持32位指令,应该从底层开始扩展一个80351的指令集出来。
    当然,这需要时间也需要STC以及爱好者的共同热诚。毕竟无论是FPGA验证还是底层工具链都是一条长路。

    实事求是,

    附上总结的指令表(STC32F参考规格书附录A)

    80251寄存器影射表.xlsx

    20.61 KB, 下载次数: 24

    点评

    你将 24位寻址/16M空间,和 32位数据总线混为一谈,还是典型的没认真思考 [attachimg]32145[/attachimg] [attachimg]32146[/attachimg]  详情 回复 发表于 2024-1-7 14:25
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    551

    主题

    9459

    回帖

    1万

    积分

    管理员

    积分
    14001
    发表于 2024-1-7 14:25:01 | 显示全部楼层
    13918210822 发表于 2024-1-7 13:03
    最近为了使用STC32F上使用多任务RTOS, 再梳理一遍指令表
    发现STC32栈指针是16位SPX(DR60), 加上一个24位DPT ...

    你将 24位寻址/16M空间,和 32位数据总线混为一谈,还是典型的没认真思考

    截图202401071424114107.jpg
    截图202401071424564496.jpg

    截图202401071426047814.jpg

    截图202401071426388522.jpg








    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    5

    主题

    89

    回帖

    401

    积分

    中级会员

    积分
    401
    发表于 2024-1-7 15:16:51 | 显示全部楼层
    本帖最后由 13918210822 于 2024-1-7 15:23 编辑
    神农鼎 发表于 2024-1-7 14:25
    你将 24位寻址/16M空间,和 32位数据总线混为一谈,还是典型的没认真思考

    举个例子,说明32位指令不全,比如立即数装载就要2条指令
    ; line 48:         volatile long c1 = 0x7EFDFF02, c2 =0x80000003;
            MOV      WR6,#0FF02H
            MOV      WR4,#07EFDH
            MOV      c1?140,DR4
            MOV      WR6,#03H
            MOV      WR4,#08000H
            MOV      c2?141,DR4
    ; line 49:     c1 += c2;
            MOV      DR0,c2?141
            MOV      DR4,c1?140
            ADD      DR4,DR0
            MOV      c1?140,DR4


    究其根源,251没有 MOV DRj, #32


    251指令表

    251指令表
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    551

    主题

    9459

    回帖

    1万

    积分

    管理员

    积分
    14001
    发表于 2024-1-7 15:50:15 | 显示全部楼层
    这不影响 STC32 是 32位数据总线
    你去看看 M0, 没除法,成本的考量


    另外我请教下,如果指令长度限定是 32位及以下长,
    如何编写一条指令:将32位立即数送到某个地址的寄存器 !
    寄存器地址放哪,如何执行某个指定动作

    ===要考虑成本,如何设计这条指令/请32位长度搞定

    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    119

    回帖

    657

    积分

    高级会员

    积分
    657
    发表于 2024-1-7 16:30:52 | 显示全部楼层
    13918210822 发表于 2024-1-7 15:16
    举个例子,说明32位指令不全,比如立即数装载就要2条指令
    ; line 48:         volatile long c1 = 0x7EFDF ...

    ARM和RISC-V都没有一条指令装载32位立即数
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    119

    回帖

    657

    积分

    高级会员

    积分
    657
    发表于 2024-1-7 16:32:27 | 显示全部楼层
    13918210822 发表于 2024-1-7 15:16
    举个例子,说明32位指令不全,比如立即数装载就要2条指令
    ; line 48:         volatile long c1 = 0x7EFDF ...

    有MOV DRj, #16位立即数
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    1

    主题

    119

    回帖

    657

    积分

    高级会员

    积分
    657
    发表于 2024-1-7 16:46:23 | 显示全部楼层
    13918210822 发表于 2024-1-7 15:16
    举个例子,说明32位指令不全,比如立即数装载就要2条指令
    ; line 48:         volatile long c1 = 0x7EFDF ...

    ARM和RISC-V还都没有直接寻找指令,比如算C1=C2+C3,用ARM的话要这样:
    LDR R0,=C2
    LDR R1,[R0]
    LDR R0,=C3
    LDR R2,[R0]
    ADD R1,R2
    LDR R0,=C1
    ST R1,[R0]
    而STC32的话是这样
    MOV DR0,C2
    MOV DR4,C3
    ADD DR0,DR4
    MOV C1,DR0
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-5-17 08:46 , Processed in 0.141906 second(s), 72 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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