找回密码
 立即注册
楼主: tzz***

4组串口UART使用DMA收发 @STC32G,易用,高效,稳定 !精品实战代码

[复制链接]

该用户从未签到

19

主题

517

回帖

1634

积分

荣誉版主

积分
1634
 楼主| 发表于 2023-11-30 18:53:27 | 显示全部楼层
本帖最后由 tzz1983 于 2023-11-30 19:09 编辑
LAOXU 发表于 2023-11-30 14:49
两位大师, 帮忙看看, 如何解决不同类型的数据, 统一转换成 long类型.

对 char, int, long, 指针类 p, 都可 ...


直接赋值即可,例如: long a=11.0592;  这样的语句是合法的,  可显式转换,也可隐式转换, 舍去小数部分, 整数部分赋值给a,  赋值后a=11;
但是float可表示的数值范围比long大, 这是一种不安全的转换, 当数值大到无法用long表示时, 会舍去高位.   这和 long转换为char是一样的道理, 比如 char b=0x888UL;  结果是b=0x88; 高位被舍弃了, 放不下.
同理, long转换为float也是不安全的转换, 会发生精度损失. float可表示的数值范围更大, 但是精度没有long高.

你的说" long dat =  *(long*) &f; " ,  这个语句语法可以通得过, 但是没什么意义, 不知道你想干嘛, 做一件事总要有目的, 不能只是为了转换而转换吧
回复 支持 反对 送花

使用道具 举报

  • TA的每日心情
    开心
    3 小时前
  • 签到天数: 145 天

    [LV.7]常住居民III

    12

    主题

    98

    回帖

    1430

    积分

    金牌会员

    积分
    1430
    发表于 2023-11-30 23:31:55 | 显示全部楼层
    学习学习,谢谢
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 132 天

    [LV.7]常住居民III

    37

    主题

    868

    回帖

    3940

    积分

    荣誉版主

    积分
    3940
    发表于 2023-12-1 11:03:28 | 显示全部楼层
    tzz1983 发表于 2023-11-30 18:53
    直接赋值即可,例如: long a=11.0592;  这样的语句是合法的,  可显式转换,也可隐式转换, 舍去小数部分, 整 ...

    上次杨老师, 发了一个贴子, 对比 C251 和 C51 的 VSPRINTF 函数,  C251 上是可重入的,  C51 上是不可重入的,

    结果 杨老师 判  C251 完胜 C51 !

    且不论 杨老师 用高级别的 16位机 去 PK 8位机, 降维打击, 这完胜的不光采.  我用 DSP 去 PK C251 也完胜

    一时兴起, 编写一个 C51上用的 真正可重入的  VSPRINTF 函数, 不同于 C51 自带的假重入, C51的重入, 只有两层, 多层同会出错 !  

    此 VSPRINTF 可重入函数, 使用多层宏定义,  避开 PRINTF 函数, 格式化字符串和附加的参数, 占用固定存储器的问题, 所有参数和中间变量, 全部放大堆栈中, 实现真正的可重入.

    请帮忙

    点评

    这种个人兴趣的事情就自己去研究吧  发表于 2023-12-1 13:12
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 132 天

    [LV.7]常住居民III

    37

    主题

    868

    回帖

    3940

    积分

    荣誉版主

    积分
    3940
    发表于 2023-12-1 11:12:16 | 显示全部楼层
    此 VSPRINTF 可重入函数, 一般的 整型, 指针型, 字符串 等, 编写的比较 轻松.

    难度最大的 是 二进制浮点数 转  十进制浮点数 , 此程序不是一般的难编写, 不是 二进制浮点数 转  十进制浮点数 的算法难,

    而是有条件限制 , 除了 受 中断保护 入栈的 十几个寄存器 可用, 其他一切 中间局部变量, 数据缓冲区等, 必须全部都要, 也只能放在 SP堆栈中 !

    做到真正的重入, 总之, 一言难尽, 难啊~~~

    点评

    应该也不难, 指数就是左移或右移, 不过没研究那么深了,哈哈  发表于 2023-12-1 13:05
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 132 天

    [LV.7]常住居民III

    37

    主题

    868

    回帖

    3940

    积分

    荣誉版主

    积分
    3940
    发表于 2023-12-1 11:19:04 | 显示全部楼层
    你的方法不可用, 因为 强制 将 浮点数, 转换成了 long 类型数了 (已不是原来的浮点数了)

    我的实际应用要求是, 数据不做任何转换, 直接当参数传送到 R4-R7

    点评

    你的目的是传递参数, 而不是真的要转换. 是你表达不明确, 传递参数很简单, 你编一个同功能函数, 去看反汇编就知道该怎么做了  发表于 2023-12-1 13:09
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 132 天

    [LV.7]常住居民III

    37

    主题

    868

    回帖

    3940

    积分

    荣誉版主

    积分
    3940
    发表于 2023-12-1 11:22:31 | 显示全部楼层
    在写法上, 要与 原

    extern int vprintf  (const char *, char *);
    extern int vsprintf (char *, const char *, char *);

    完全相同
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 132 天

    [LV.7]常住居民III

    37

    主题

    868

    回帖

    3940

    积分

    荣誉版主

    积分
    3940
    发表于 2023-12-1 17:28:30 | 显示全部楼层
    LAOXU 发表于 2023-12-1 11:19
    你的方法不可用, 因为 强制 将 浮点数, 转换成了 long 类型数了 (已不是原来的浮点数了)

    我的实际应用要求 ...

    NO !

    单一的传递参数很简单, 关健是 printf 函数, 格式化字符串和附加的参数, 不管什么类型的数据, 都往里装, , 占用固定存储器(不重入), 所以不能用, 而附加的参数等原始数据, 不充许转换, 要求准确传送, 并且要编过编译器, 否则编译通不过, 难在这一点上.
    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 132 天

    [LV.7]常住居民III

    37

    主题

    868

    回帖

    3940

    积分

    荣誉版主

    积分
    3940
    发表于 2023-12-1 18:01:05 | 显示全部楼层
    本帖最后由 LAOXU 于 2023-12-1 18:02 编辑

    tzz1983  应该也不难, 指数就是左移或右移, 不过没研究那么深了,哈哈

    ===============================================================

    二进制浮点数 转  十进制浮点数 , 运算复杂,  需要使用 大量的中间局部变量, 数据缓冲区等, 这些都不能占用任何明面上的 片内与片外 RAM,

    不能使用任何 C51编译器 识别和固定使用的, 以及回收可重复使用的 RAM.

    受 中断保护 入栈的 寄存器 , 共 13个 8位的,  R0-R7 , A, B, PSW, DPH, DPL

    你想想, 浮点数输入, 占用 4字节 (R4-R7), A, B, PSW, 逻辑运算和数学运算要占用, DPH 和 DPL,  XRAM 和 CODE 读写数据要占用,

    连 R0,R1 都要让一个出来, 给片内 RAM 寻址读写数据用,  还剩下 3个 8位的 寄存器, 能派多大用处?

    printf 函数, 相信你用过, 格式化字符串和附加的参数 一大串, 都要占内存, 一经占内存就变成不可重入的了,

    vprintf 函数,  比printf 函数,  还多了一个指针, 输出的格式化数据, 不是直接通过串口送出, 而是写入缓冲区, 可以用 PUTS 函数发送,

    也可以通过 DMA, 将输出缓冲区的数据发送.


    此程序的难点, 不是在于写个规范标准程序, 而是要求, 不能占用 单片机的任何明面上的  RAM 资源, 以达到真正的可重入函数级别,

    唯一能放数据的地方就是 SP 堆栈了, 彻底不占用 单片机任何明面上的  RAM 资源,  而 C51不像 C251, 不支持堆栈寻址(没这方面任何指令).

    所以我说, 不是一般的难编写, 有几次写程序, 写着写着就彻底绝望了, 没有一个多余的字节(寄存器)能给我可用. 程序转不出啊~~~

    回复 支持 反对 送花

    使用道具 举报

  • TA的每日心情
    开心
    9 小时前
  • 签到天数: 132 天

    [LV.7]常住居民III

    37

    主题

    868

    回帖

    3940

    积分

    荣誉版主

    积分
    3940
    发表于 2023-12-1 18:05:41 | 显示全部楼层
    有句古话说

    巧妇难为无米之炊

    大概就能真正表达我的心情了

    点评

    你即然研究过了, 那肯定知道可变参数的传递规则了, 不知道的话再百度一下, 就可以知道了. 传递参数搞定 至于转换算法, 没有研究过, 就不深入讨论了. 主要还是没有动力呀, 这东西搞出来有什么用吗. 偶尔用一下, 想办  详情 回复 发表于 2023-12-1 22:23
    回复 支持 反对 送花

    使用道具 举报

    该用户从未签到

    19

    主题

    517

    回帖

    1634

    积分

    荣誉版主

    积分
    1634
     楼主| 发表于 2023-12-1 22:23:29 | 显示全部楼层
    本帖最后由 tzz1983 于 2023-12-1 22:33 编辑
    LAOXU 发表于 2023-12-1 18:05
    有句古话说

    巧妇难为无米之炊

    你即然研究过了, 那肯定知道可变参数的传递规则了, 不知道的话再百度一下, 就可以知道了. 传递参数搞定
    至于转换算法, 没有研究过, 就不深入讨论了.  主要还是没有动力呀, 这东西搞出来有什么用吗. 偶尔用一下, 想办法避免重入就行了.
    再说了, 数据太大就改用指数形式显示, 用十进制+小数显示反而不合适, 一大堆的0.
    还有就是单位, 比如电阻值显示,  小的我用毫欧, 欧, K欧, M欧, 单位一变, 永远也无需那么多0 .  实际上有效位永远就那么几位
    不过你喜欢研究也好的, 对自身提高还是比较有用的, 放心好了, 堆栈不会被你打穿的, 万一打穿了, 那也是使用者留的空间不够. 跟你没关系. 不过你也要省着点用, 不能故意去打穿啊
    回复 支持 反对 送花

    使用道具 举报

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

    本版积分规则

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

    GMT+8, 2024-4-28 11:54 , Processed in 0.078091 second(s), 71 queries .

    Powered by Discuz! X3.5

    © 2001-2024 Discuz! Team.

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