找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2500|回复: 20
收起左侧

如何让MCU串口十六进制转换为对应ASCII数字?

  [复制链接]
ID:668693 发表于 2022-3-10 19:06 | 显示全部楼层 |阅读模式
想在程序中将寄存器内容用ASCII方式发送出来,大家有没有好的想法
回复

使用道具 举报

ID:824490 发表于 2022-3-10 20:20 | 显示全部楼层
//定义一个结构体,用于存放转换字节
typedef struct {
  unsigned char reg_h;
  unsigned char reg_l;
}asc_code;
///////////////////////////////////////////////////////////
//把8位(1字节)二进制转为ASCII码以方便显示
//byte  : 待转换的16进制变量
//返回值: ASCII码
asc_code byte2ascii(unsigned char byte)
{
asc_code temp;
temp.reg_h= byte/16<10? byte/16+0x30:byte/16+0x37;         //如果值小于10(0x0a),则+0x30,否则+0x37
temp.reg_l= byte%16<10? byte%16+0x30:byte%16+0x37;
return temp;
}
回复

使用道具 举报

ID:668693 发表于 2022-3-10 20:40 来自手机 | 显示全部楼层
名字不是重点 发表于 2022-3-10 20:20
//定义一个结构体,用于存放转换字节
typedef struct {
  unsigned char reg_h;

我是直接判断寄存器然后加0x30,高位的话在移位继续判断
回复

使用道具 举报

ID:879809 发表于 2022-3-10 20:41 | 显示全部楼层
  1. ch[0]="0123456789abcdef"[i>>4];
  2. ch[1]="0123456789abcdef"[i&0xf];
复制代码
回复

使用道具 举报

ID:824490 发表于 2022-3-10 20:53 | 显示全部楼层
发表于 2022-3-10 20:40
我是直接判断寄存器然后加0x30,高位的话在移位继续判断

移位更好。速度快,效率高。
回复

使用道具 举报

ID:401564 发表于 2022-3-11 20:12 | 显示全部楼层
名字不是重点 发表于 2022-3-10 20:53
移位更好。速度快,效率高。

Keil环境下写的8051,乘法加法位移都是通过加法实现的,并不是我们想象的"位移"
ADC中常用的ADC_RES*256+ADC_RESL
你用位移也是一样的,都是通过加法实现的,并不会因为你用了位移,效率就高了
不信你写个代码仿真看一下编译后的汇编代码就知道了
别的编程环境就不知道了
回复

使用道具 举报

ID:824490 发表于 2022-3-11 23:46 | 显示全部楼层
Y_G_G 发表于 2022-3-11 20:12
Keil环境下写的8051,乘法加法位移都是通过加法实现的,并不是我们想象的"位移"
ADC中常用的ADC_RES*256+A ...

谨慎表示怀疑:
//定义一个结构体,用于存放转换字节
typedef struct {
  unsigned char reg_h;
  unsigned char reg_l;
}asc_code;
///////////////////////////////////////////////////////////
//把8位(1字节)二进制转为ASCII码以方便显示
//byte  : 待转换的16进制变量
//返回值: ASCII码
asc_code byte2ascii(unsigned char byte)
{
asc_code temp;

temp.reg_h= byte/16<10? byte/16+0x30:byte/16+0x37;         //方法1
temp.reg_l= byte%16<10? byte%16+0x30:byte%16+0x37;

//temp.reg_h= byte>>4<10? byte/16+0x30:byte/16+0x37;         //方法2
//temp.reg_l= byte&0x0f<10? byte%16+0x30:byte%16+0x37;


return temp;
}

void main()

{
unsigned char tt=0xf3;
asc_code temp;

temp= byte2ascii(tt)  ;

while(1) ;//模拟运行到这里得出结果;


}


这两种代码中,各自编译后的情况:
前两行:
Build target 'Target 1'
compiling test.c...
linking...
Program Size: data=13.0 xdata=0 code=336
"test" - 0 Error(s), 0 Warning(s).
后两行:
Build target 'Target 1'
compiling test.c...
linking...
Program Size: data=13.0 xdata=0 code=320 //少那么一点点。
"test" - 0 Error(s), 0 Warning(s).

运行到结果:
前两行花费0.00024550 @24M;
后两行花费0.00024050 @24M;//快那么一点点。。


欢迎指点!

回复

使用道具 举报

ID:624769 发表于 2022-3-12 02:22 | 显示全部楼层
名字不是重点 发表于 2022-3-11 23:46
谨慎表示怀疑:
//定义一个结构体,用于存放转换字节
typedef struct {

还是那句话,结构体是给有钱人玩的。

typedef        unsigned char        u8;
typedef        unsigned short        u16;

u8 code        ASCII_Code[]        = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

u16        HEX2ASCII(u8 dat)
{
        u16 temp;
        temp = (ASCII_Code[dat>>4] << 8);
        temp |= ASCII_Code[dat&0x0f];
        return        temp;
}

void        main()
{
        u8        tt        = 0xf3;
        u16        temp;
        temp =        HEX2ASCII(tt);
        while(1);
}


Build target 'Target 1'
compiling TestC.C...
assembling Transfer.asm...
linking...
Program Size: data=15.0 xdata=0 code=59
"TestC" - 0 Error(s), 0 Warning(s).

运行到结果:
花费0.00020650 @24M;(启动后初始是:0.00019450, 即,实际耗时0.00001200)


回复

使用道具 举报

ID:824490 发表于 2022-3-12 09:34 | 显示全部楼层
188610329 发表于 2022-3-12 02:22
还是那句话,结构体是给有钱人玩的。

typedef        unsigned char        u8;

学习了~~
回复

使用道具 举报

ID:731155 发表于 2022-3-12 10:59 | 显示全部楼层
188610329 发表于 2022-3-12 02:22
还是那句话,结构体是给有钱人玩的。

typedef        unsigned char        u8;

这代码写的水平高啊
回复

使用道具 举报

ID:401564 发表于 2022-3-12 13:22 | 显示全部楼层
名字不是重点 发表于 2022-3-11 23:46
谨慎表示怀疑:
//定义一个结构体,用于存放转换字节
typedef struct {

我只看过ADC的高低位结合的汇编代码和32位和以下的乘法,位移的对比,汇编代码中并没有位移指令,全部都是通过加法实现,代码都是一样
至于结构体的运算,没用过,不发表意见
回复

使用道具 举报

ID:401564 发表于 2022-3-12 13:36 | 显示全部楼层
188610329 发表于 2022-3-12 02:22
还是那句话,结构体是给有钱人玩的。

typedef        unsigned char        u8;

我感觉你对于"效率"和"代码长度"太执着了,处处带着汇编的思想去用C
如果是我,我一定会先用sprintf,单单这个函数,要占用1K和内存,效率更是慢得不用说的
但如果我用的单机是有8K或者是17K的内存,串口函数只要不是有意有去让它变慢,一个串口函数是绝对有足够时间执行的
那么,整体下来,C代码简单了,工作量小了,功能也更多了,代码空间也足够用,我实在是找不到不用它的理由
要是我,我一定是先一直浪费着这个函数占用的空间,肯定是要等到代码写下去之后,发现空间不够用了,我才会考虑用别的方法
回复

使用道具 举报

ID:624769 发表于 2022-3-12 16:20 | 显示全部楼层
本帖最后由 188610329 于 2022-3-12 18:09 编辑
Y_G_G 发表于 2022-3-12 13:36
我感觉你对于"效率"和"代码长度"太执着了,处处带着汇编的思想去用C
如果是我,我一定会先用sprintf,单单 ...

额…………, 首先,我辩解一下,我对"效率"和"代码长度"确实比较在意, 但是,并没有“太执着” 。可能,你把我和某人搞混了,记得有一篇我忘了是谁发的,关于“效率”的帖子,我俩都有参与过讨论,你的观点是不需要去考虑,我的观点是可以考虑,但是不需要去太过执着,如果在低端机跑复杂程序,那么,就要提高效率,减小代码,如果机器本来就高端,程序也不复杂,就没有必要花精力和时间去提高那一丁点的效率,以及一丁点的代码长度。也许,你是把我和发帖人搞混了??

其次,你说的很对,我很多时候,都会用汇编思想去用C,这个好像是不受控制的,下意识的,就会出现,但是,我对此并不觉得不好,因为可以不需要刻意而为,就能在一定程度上提高运行效率,以及缩小代码长度,何乐而不为呢?
其实在这个论坛里,我最佩服的三个人你是其中之一,不仅仅是你懂得多,对各种问题都有了解,而且回答比较热心,关键是,虽然有时你用词会比较尖锐,但是直指问题中心,也从来不会通过贬低别人来抬高自己,所以,对你,我其实也算神交已久了。
而且,你也算是 C 和 ASM 双修, 我一直认为,其实我们有一点心得是可以互相交流的,只不过,与我不同的是,你是从汇编,转去的C, 我以前是学B的,玩单片机才去学的C 发现 学不下去了,才开始转去的汇编。
所以,我和你对 C 与 汇编 这两个东西的印象会 完全不同,
你会觉的,C全面优于汇编,
我会觉得,C除了(通用性,易读易写)不可否认之外,对于单片机控制而言,是完全不如汇编的。好像我越来越多时候,离不开汇编了,我也知道,这对今后和别人代码交流是不利。

聊到这里,我顺便请教一个问题,在C语言里面, 我们如果定义一个数组:  u16  Buf[32];   用来存放16位的数据, 但是,定时的需要把数据 存入Eeprom, 那么就需要分别操作 高,低 8位, 比较麻烦,我现在的做法是:
ASM 文件:
PUBLIC        U16_Buf,U8_Buf

DATA_Transfer        Segment DATA
RSEG        DATA_Transfer
U16_Buf:
U8_Buf:                    DS        64

END


C 文件:
extern        u16        U16_Buf[32];
extern        u8        U8_Buf[64];


利用这样两个文件,来作出两个 目标地址其实一样,但是步进不同的两个数组,那么通过 对两个数组操作,达到16位,8位的无缝切换,这里我就想问一下,C下面,应该有可以直接达到这个目的的方法,但是我找了很多资料,没有找到这个方法,不知道能否指点一二, 毕竟我也想一点点摆脱对汇编的依赖。
回复

使用道具 举报

ID:47286 发表于 2022-3-12 19:35 | 显示全部楼层
188610329 发表于 2022-3-12 02:22
还是那句话,结构体是给有钱人玩的。

typedef        unsigned char        u8;

程序写的真漂亮 佩服

这样的结果是把0x4f编程 "4" "f" 对么 如果是 这有啥意义啊 用于1602的显示么 那等显示时还得再拆temp

讲真 一直没想明白楼主的要求是啥目的 寄存器不就跟一排8个拨动开关一样么 要设置啥就扳到1 那显示的话变成1010 0011这种方式不是更直观么 显示个16进制格式的ASCII做啥用啊
回复

使用道具 举报

ID:47286 发表于 2022-3-12 19:45 | 显示全部楼层
Y_G_G 发表于 2022-3-12 13:36
我感觉你对于"效率"和"代码长度"太执着了,处处带着汇编的思想去用C
如果是我,我一定会先用sprintf,单单 ...

您用51片子干一件事 而且只干好这一件事 那么这想法当然没问题

但穷人不这么想 通常穷人希望51也能当个系统用 比如我这样的 哪怕做个开闭灯泡的板子 也想着不光能稳定 可靠 长久的开闭 还能监控电压 电流变化 可以调光 可以纪录系统状态 保存故障码 容错 支持故障回报和查询 还需要通过通讯和系统协同 而且通讯是频繁的 等等等等 没准还会有更多想法和要求 这种时候 对每次的执行效率就可能会要求很高 至少自我要求比较高 所以我比较喜欢那位大佬的思路 虽然不是必须每次都追求高效率 但能做到为什么不呢 对我来说 限制功能想象的因素只有运算速度 只要速度够 功能就可以继续加下去
回复

使用道具 举报

ID:401564 发表于 2022-3-12 20:13 | 显示全部楼层
dzbj 发表于 2022-3-12 19:45
您用51片子干一件事 而且只干好这一件事 那么这想法当然没问题

但穷人不这么想 通常穷人希望51也能当 ...

行吧,就这样吧
回复

使用道具 举报

ID:168971 发表于 2023-11-1 18:09 | 显示全部楼层
188610329 发表于 2022-3-12 02:22
还是那句话,结构体是给有钱人玩的。

typedef        unsigned char        u8;

说的没错,厉害厉害
回复

使用道具 举报

ID:883242 发表于 2023-11-1 20:35 | 显示全部楼层
hei51com 发表于 2022-3-12 10:59
这代码写的水平高啊

高什么高啊!地板早就把答案写出来了,而且地板的写法跟8楼本质完全一样,但是比8楼优雅了太多,但是你们就没有一个人能看懂???
回复

使用道具 举报

ID:939553 发表于 2023-11-1 21:08 | 显示全部楼层
和上面大佬的思路差不多,我个人常用的,仅参考
unsigned char code ASCLIB[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
void printf_tx_len_hextoasc(unsigned char *in_buff , unsigned int buff_len)
{
       
        while(buff_len-- > 1)
        {
                printf("%c",ASCLIB[*in_buff >> 4]);
                printf("%c",ASCLIB[*in_buff++ & 0x0f]);
                printf("%c",0x20);
        }
       
        //最后一个字节
        printf("%c",ASCLIB[*in_buff >> 4]);
        printf("%c",ASCLIB[*in_buff & 0x0f]);
}
回复

使用道具 举报

ID:1097337 发表于 2023-11-2 10:57 | 显示全部楼层
188610329 发表于 2022-3-12 16:20
额…………, 首先,我辩解一下,我对"效率"和"代码长度"确实比较在意, 但是,并没有“太执着” 。可能 ...

高手间切磋,谦虚豁达,小小白们非常受益。
谢谢各位赐教。
关注了!
回复

使用道具 举报

ID:1097337 发表于 2023-11-2 11:17 | 显示全部楼层

果然简单又易懂。收藏了。
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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