■ 问题提出


带有128KB缓存的AD7606模拟采集板 后面更新了不带板内缓冲区的C51程序。采集板与计算机之间存在两种实时数据通道:

  • 通过USB-RS232转接串口,波特率为460800
  • 通过WiFi-UART模块,波特率为460800,但是实际传输速率要小于460800

为了能够利用 STC WiFi下载程序 界面作为接受数据的缓冲界面,这样就需要能够利用ASCII码来高效传输二进制数据。

传统的方式通过C51的printf函数,将二进制转换成ASCII字符串通过串口发送出去,虽然这样有很强的可读性,但是存在着很大的转换效率低下:

  • 通常一个两字节(16bit)的二进制,最大需要6个字节(带有符号位)。比如有符号整数 0xd8ef : -10000。
  • 为了分割连续两个数字,其间还需增加一个空格(0x20)

因此,最大需要是踹死7个字节来传输一个16bit的数据。传输效率浪费了:ηascii=72\eta _{ascii} = {7 \over 2}ηascii​=27​

▲ ISP下载软件界面

■ Base64编码方式


在网页 What is Base64 Encoding and How does it work? | Base64Encoder 给出了Base64编码的具体方式。它将连续三个字节(24bit)转换成四个6bit组,按照下面的表格找到对应的ASCII码。

▲ Base64编码字符表格

这样的转换效率为ηbase64=43\eta _{base64} = {4 \over 3}ηbase64​=34​
通过Base64的转换比普通的ASCI字符效率提高了:
ηΔ=ηasciiηbase64=7/24/3=218=2.625\eta _\Delta = {{\eta _{ascii} } \over {\eta _{base64} }} = {{7/2} \over {4/3}} = {{21} \over 8} = 2.625ηΔ​=ηbase64​ηascii​​=4/37/2​=821​=2.625

在实际实现中,将原来的 “62”编码为$+$,修改为$*$,这样在下载程序界面可以避免换行的。整个显示是铺满Mem0界面。

■ C51编码程序和Python解码程序


1. C51的编码1

/*
**==============================================================================
** BASE64ASCII.C:             -- by Dr. ZhuoQing, 2020-06-04
**
**==============================================================================
*/
//------------------------------------------------------------------------------
#define BASE64ASCII_GLOBALS        1              // Define the global variables
#include "BASE64ASCII.H"
#include "c51basic.H"
//------------------------------------------------------------------------------
void Base64ASCIISendChar(unsigned char ucChar) {SendChar(ucChar);
}
//------------------------------------------------------------------------------
void Base64ASCIIInit(void) {g_ucBase64ASCIIBufferPoint = 0;
}
//------------------------------------------------------------------------------
void Base64ASCIIPushByte(unsigned char ucByte) {g_ucBase64ASCIIBuffer[g_ucBase64ASCIIBufferPoint ++] = ucByte;if(g_ucBase64ASCIIBufferPoint >= 3) {Base64ASCIIFlushBuffer();}
}
unsigned char Base64ASCII6BitChar(unsigned char ucBit) {if(ucBit < 26) return 'A' + ucBit;if(ucBit < 52) return (ucBit - 26) + 'a';if(ucBit < 62) return (ucBit - 52) + '0';if(ucBit == 62) return '*';if(ucBit == 63) return '/';return '=';
}
//------------------------------------------------------------------------------
void Base64ASCIIFlushBuffer(void) {unsigned char ucDim[4];unsigned char ucChar, ucNibble;if(g_ucBase64ASCIIBufferPoint == 0) return;ucChar = g_ucBase64ASCIIBuffer[0];ucNibble = ucChar << 4;ucDim[0] = Base64ASCII6BitChar(ucChar >> 2);ucChar = g_ucBase64ASCIIBuffer[1];ucDim[1] = Base64ASCII6BitChar((ucNibble & 0x30) | (ucChar >> 4));ucNibble = (ucChar & 0xf) << 2;ucChar = g_ucBase64ASCIIBuffer[2];ucDim[2] = Base64ASCII6BitChar(ucNibble | (ucChar >> 6));ucDim[3] = Base64ASCII6BitChar(ucChar & 0x3f);if(g_ucBase64ASCIIBufferPoint == 1) {ucDim[2] = '=';ucDim[3] = '=';} else if(g_ucBase64ASCIIBufferPoint == 2) {ucDim[3] = '=';}Base64ASCIISendChar(ucDim[0]);Base64ASCIISendChar(ucDim[1]);Base64ASCIISendChar(ucDim[2]);Base64ASCIISendChar(ucDim[3]);g_ucBase64ASCIIBufferPoint = 0;
}
//==============================================================================
//                END OF THE FILE : BASE64ASCII.C
//------------------------------------------------------------------------------
/*
**==============================================================================
** BASE64ASCII.H:            -- by Dr. ZhuoQing, 2020-06-04
**
**  Description:
**
**==============================================================================
*/
#ifndef __BASE64ASCII__
#define __BASE64ASCII__
//------------------------------------------------------------------------------
#ifdef BASE64ASCII_GLOBALS#define BASE64ASCII_EXT
#else#define BASE64ASCII_EXT extern
#endif // BASE64ASCII_GLOBALS
//------------------------------------------------------------------------------
//==============================================================================
void Base64ASCIISendChar(unsigned char ucChar);
//------------------------------------------------------------------------------
void Base64ASCIIInit(void);
BASE64ASCII_EXT unsigned char g_ucBase64ASCIIBuffer[3];
BASE64ASCII_EXT unsigned char g_ucBase64ASCIIBufferPoint;
void Base64ASCIIPushByte(unsigned char ucByte);
void Base64ASCIIFlushBuffer(void);
unsigned char Base64ASCII6BitChar(unsigned char ucbit);
//==============================================================================
//             END OF THE FILE : BASE64ASCII.H
//------------------------------------------------------------------------------
#endif // __BASE64ASCII__

2. Python解码程序

def Base64Ascii2Bit(ascii):ascii = int(ascii)if ascii >= ord('A') and ascii <= ord('Z'): return ascii - ord('A')if ascii >= ord('a') and ascii <= ord('z'): return ascii - ord('a') + 26if ascii >= ord('0') and ascii <= ord('9'): return ascii - ord('0') + 52if ascii == ord('*'): return 62if ascii == ord('/'): return 63return 0
def Base64Ascii2Byte(fourb):data = bytearray()bits0 = Base64Ascii2Bit(fourb[0])bits1 = Base64Ascii2Bit(fourb[1])bits2 = Base64Ascii2Bit(fourb[2])bits3 = Base64Ascii2Bit(fourb[3])data.append(bits0 * 4 + int(bits1 / 16))data.append((bits1 & 0xf) * 16 + int(bits2 / 4))data.append((bits2 & 0x3) * 64 + bits3)if fourb[2] == ord('=') and fourb[3] == ord('='):data = data[0:1]return dataif fourb[3] == ord('='):return data[0:2]return data
def Base64Ascii2Data(ascii):data = bytearray()length = len(ascii)for i in range(int(length / 4)):bytedata = Base64Ascii2Byte(ascii[i*4:i*4+4])if len(bytedata) > 0:data.extend(bytedata)valdim = [x*256+y for x,y in zip(data[0::2], data[1::2])]valdim = [(d & 0x7fff) - (d & 0x8000) for d in valdim]return valdim

 

■ 最大采样速率测试结果


经过测试,在 带有128KB缓存的AD7606模拟采集板 上,对八个通道进行周期为1毫秒的采集,实际上传速率为 16kByte/s。再乘以编码增益ηbase64=43\eta _{base64} = {4 \over 3}ηbase64​=34​,则实际上传速率为:21.3kByte/秒.

▲ 通过AD7606采集板采集到的两个通道的信号波形

#------------------------------------------------------------
stm32cmd('ad5v')
stm32cmd('CLEAR')
stm32cmd('adascii 1000 8 1')
val = stm32val()[10]
while True:time.sleep(.2)valnew = stm32val()[10]if valnew == val: breakval = valnew
tspbeep(1200, 200)
stm32cmd("COPY")
time.sleep(.5)
pastestr = bytes(clipboard.paste(), 'utf-8')
data = Base64Ascii2Data(pastestr)
plt.plot(data[0::8], label='Channel1')
plt.plot(data[1::8], label='Channel2')
plt.xlabel("sample")
plt.ylabel("Voltage(V)")
plt.legend(loc='upper right')
plt.grid(True)
plt.show()

■ 结论


通过Base64编码,将原来的3个字节的数据编码成4个字节的ASCII字符,可以在适合ASCII存储显示的界面完成二进制数据的传递。这大大提高数据的传输效率。

//==============================================================================
//                    PROCESS THE DEBUG BUFFER
//------------------------------------------------------------------------------
void SerialDebugProcessBuffer(void) {unsigned int nNumber, nChannel, nWaitTime, i, j;int nData[8];unsigned int nNum;SerialDebugBuffer2Argument();if(g_ucSDANumber == 0) return;if(strcmp("hello",                (char *)STD_ARG[0]) == 0)printf("%s is ready !\r\n", VERSION_STRING);else IFARG0("ad") {sscanf(SDA(1), "%d", &nNumber);sscanf(SDA(2), "%d", &nChannel);sscanf(SDA(3), "%d", &nWaitTime);g_ucWaitMS = 0;for(i = 0; i < nNumber; i ++) {while(g_ucWaitMS != nWaitTime);g_ucWaitMS = 0;AD7606Convert();AD7606ReadData(nData, 4);for(j = 0; j < nChannel; j ++) {nNum = nData[j];SendChar((unsigned char)(nNum >> 8));SendChar((unsigned char)nNumber);}}}else IFARG0("adtext") {sscanf(SDA(1), "%d", &nNumber);sscanf(SDA(2), "%d", &nChannel);sscanf(SDA(3), "%d", &nWaitTime);g_ucWaitMS = 0;for(i = 0; i < nNumber; i ++) {while(g_ucWaitMS != nWaitTime);g_ucWaitMS = 0;AD7606Convert();AD7606ReadData(nData, 4);for(j = 0; j < nChannel; j ++) {nNum = nData[j];printf("%d ", nNum);}}} else IFARG0("adascii") {sscanf(SDA(1), "%d", &nNumber);sscanf(SDA(2), "%d", &nChannel);sscanf(SDA(3), "%d", &nWaitTime);g_ucWaitMS = 0;Base64ASCIIInit();for(i = 0; i < nNumber; i ++) {while(g_ucWaitMS != nWaitTime);g_ucWaitMS = 0;AD7606Convert();AD7606ReadData(nData, 4);for(j = 0; j < nChannel; j ++) {nNum = nData[j];Base64ASCIIPushByte((unsigned char)(nNum >> 8));Base64ASCIIPushByte((unsigned char)nNum);                }}Base64ASCIIFlushBuffer();} else IFARG0("ad5v") {OFF(AD7606_RANGE);        } else IFARG0("ad10v") {ON(AD7606_RANGE);}else printf("Error command : %s !\r\n", STD_ARG[0]);
}

  1. C51工程文件:C51\STC\Tools\AD7606\Sample8G1KNoBuffer\Sample8G1KNoBuffer.uvproj ↩︎

AD7606数据采集板使用ASCII码传递BINARY数据相关推荐

  1. c语言中 字母对应的数值,c语言字母对应ascii码 实型数据,与字符型数据

    知识点:实型的定义方法和实型常量的表达方法; 重要程度:★★★★ 1.实型常量 在C语言中,实型常量有两种表示形式:小数形式和指数形式. (1)小数形式 规则如下:1. 有且仅有一个小数点. 2. 左 ...

  2. bcd转ascii码 流程图_4-20mA转RS485,MODBUS数据采集模块

    原标题:4-20mA转RS485,MODBUS数据采集模块 产品概述: WJ20产品实现传感器和主机之间的信号采集,用来检测模拟信号.WJ20系列产品可应用在 RS-232/485总线工业自动化控制系 ...

  3. matlab数据转换为tecplot格式[ASCII码格式下的plt文件]

    matlab数据转换为tecplot格式[ASCII码格式下的plt文件] 1 tecplot能读取的的常见ASCII格式 1.1 文件格式与文件头 1.2 zone相关的格式 2 一维数据 3 二维 ...

  4. 解决Python中TCP数据转为json后中文变为Ascii码的问题

    我们我们有时候会使用TCP直接传输JSON数据,这时候正确解析数据就很关键了,最近在使用Python解析TCP传输的JSON数据时就遇到了中文不能正常显示的问题. 原因分析 TCP接口数据转为json ...

  5. C语言中字符数据超过127,如何用C语言显示ascii码超过127的字符

    C语言的程序代码如下: #include "stdio.h" main() {inti; for (i=1;i<256;i++) { printf("%c &quo ...

  6. ascii码值为负数_作为2020年的程序员,你还在为编码问题困惑?

    如果你是一个生活在2020年的程序员,却不了解字符.字符集.编码和Unicode这些基础知识.那你可要小心了,要是被我抓到你,我会让你在潜水艇里剥六个月洋葱来惩罚你. --来源网络 基本概念科普 为了 ...

  7. java ascii码转字符_一文让你读懂JAVA.IO、字符编码、

    1 JAVA.IO字节流 inputstream.png LineNumberInputStream和StringBufferInputStream官方建议不再使用,推荐使用LineNumberRea ...

  8. BCD编码和ASCII码

    计算机里,字母,各种字符以及指挥计算机执行操作的指令,均用二进制数的组合表示,称为二进制编码 目录 ASCII码(汇编语言程序设计的时候会常用) BCD码(了解) ASCII码(汇编语言程序设计的时候 ...

  9. 密码译码(ASCII码详解)

    刚写完一个单片机的代码,再发这个博客就感觉不适应,但是今天我翻了一眼专栏,发现好久没有常规的更新了,那么今天,我们就来用C++来编写一个代码:密码译码 先看一眼题目: 要将"China&qu ...

最新文章

  1. jquery中ajax请求后台数据成功后既不执行success也不执行error解决方法
  2. python读取中文文件乱码-详解Python的json文件读取及中文乱码显示问题解决方法...
  3. html5长按保存,iOS UIWebView仿微信H5页面实现长按保存图片功能
  4. android java 打开snd,使用SndPlaySound从内存中播放WAV
  5. 漫画:什么是 “元宇宙” ?
  6. Shadow Defender 语言文件并注册
  7. array用法 numpy_Numpy统计计算、数组比较,看这篇就够了
  8. MySQL与Oracle的语法区别详细对比 (转)
  9. 21天Jenkins打卡Day10-自动触发项目构建
  10. Ubuntu12.04中安装ns-allinone-2.34
  11. 如何在html中使用特殊字体
  12. 数学建模:线性规划—投资的收益和风险模型 (Python 求解)
  13. 千牛通知栏常驻是什么意思_我告诉你小米常驻通知是什么意思
  14. linux进入rescue,进入Linux rescue模式后有几种方法引导系统
  15. 程序媛字节裸辞后,都干了些什么....
  16. (云服务器学习)部署python程序到云服务器
  17. Linux内核cgroup使用介绍
  18. 不放心的dblink--手工关闭dblink
  19. 我的天空 我的未来 我的梦
  20. 【1】基于TQ2440的MP3设计——【1、总体方案设计】

热门文章

  1. php或js判断网站访问者来自手机或者pc端源码
  2. DUILIB中获取flash,webbrowser control的方法
  3. 连接远程ms sql server 2000企业版时出现错误:10061的解决方法
  4. js词法作用域(静态作用域)
  5. GET和POST两种基本请求方法的区别
  6. WHAT THE DATA SAYS ABOUT KUBERNETES DEPLOYMENT PATTERNS
  7. 麻烦大家看了我的文章觉得有用就关注我下
  8. Java DNS查询内部实现
  9. params(C# 参考)
  10. 网络营销之微微博营销