STM32基带HDB3编解码系统设计(附完整代码)
Posted 阿汪先生
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32基带HDB3编解码系统设计(附完整代码)相关的知识,希望对你有一定的参考价值。
【STM32】基带HDB3编解码系统设计
一、设计背景及说明
长期以来,人类进行信息交互的基本方式不外乎语言、文字和图像。随着数字技术的发展,三大信息网:电话、电视、和因特网在数字通信的平台上融为一体的趋势日益加速。一方面是通信技术一日千里的发展,技术更新的周期越来越短;另一方面是人们对信息数量和质量的需求不断增长,如何更加有效、更加可靠、更加安全的传输信息,成为人们非常关注的问题。
数字通信具有许多优良的特性,数字处理的灵活性使得数字传输系统中传输的数字信息既可以来自计算机,电传机等数据终端的各种数字代码,也可以是来自模拟信号经过数字化处理后的脉冲编码PCM信号等。在原理上,数字信息可以直接用数字代码序列表示和传输,但是在实际的传输中,视系统的要求和信道的情况,一般需要进行不同形式的编码,并且选用一组取值有限的离散波形表示这些取值离散的波形可以是数字带通信号,也可以是数字基带信号。数字基带信号的传输是数字通信系统的重要组成部分之一。
在数字通信中,一般由信源发出的数字基带信号含有丰富的低频分量,甚至直流分量,这些信号往往不宜直接用于传输,易产生码间干扰进而直接影响传输的可靠性,为了使基带信号能适合在基带HDB3编码的设计信道中传输,通常需要经过基带信号变换。而为了用更短的代码表达同样多的信息,人们提出了压缩代码长度地方法,并发明了多种压缩方法和实施方案,统称为信源编码。为了及时发现并纠正信息传输中出现的错误,人们采用了各种检错和纠错技术,由此发展起来了信道编码技术,它使通信更加可靠。在编码过程中,不同码型有不同的特点和不同的用途。例如AMI码的传号交替反转,这种码型无直流成分和很小的低频成分,利于在一般的基带信道中传输,但它可能出现四连0现象,不利于接收端的定时信号提取。
为了保持AMI码的优点而克服其缺点提出了HDB3码三阶高密度双极性码。HDB3码具有编码规则简单,无直流,低频成份少,可打破长连“0”和对定时信号的恢复十分有利等优点。综合上述情况,本文提出了基于C语言的HDB3编码的设计方案。设计方面包括规划基于C语言的HDB3编码设计的总体方案,合理利用各种软硬件资源;基于C语言的HDB3编码的软件实现。
二、设计目标与任务
2.1 设计目标
信号在信道的传输过程中,如何才能保证信号失真最小且编码与译码的准确性是本次电子设计研究的目标。一个完整的通讯系统,当信号经过一定距离的传送后,总会受到干扰、移相和衰减,因而需要对数字信号进行再生。从信源输出的信号一般是0 1两种状态的单极性NRZ码,在进行数字信号传输时,考虑到传输信道的特点,将信息比特变换为适合于在信道中传输的数字信号,即进行线路编码。
传统的基带信号含有丰富的直流和低频分量,这些信号不适宜在信道中传输。为了使得终端机编码输出的由0和1组成的单极性数码流适应于传输信道的特性,还必须经过码型变换,即对信号进行编码。选择编码码型时一般应考虑几方面的因素,比如从线路码流中容易提取时钟,码型中不宜含有直流分量,高、低频成分应尽量减少,设备应简单,易于实现码型变换和码型反变换的调试等。
2.2 设计任务
(1)CPU采用FPGA或STM32或其它。
(2)在观测点2能够看到AD采样之后的原始数据流,可以用CPU IO口进行输出。
(3)在观测点3与观测点2进行对比,验证编码的正确性。
(4)完成相关数据的本地显示。
三、设计原理
3.1 HDB3 码的介绍
HDB3码即三阶高密度双极性码(High Density Bipolar of Order3,简称:HDB3码)是一种适用于基带传输的编码方式,“三阶” 通俗讲就是最多3个连0码元,“ 高密度双极性”就是没有直流分量,不会连续出现+1或-1,它是为了克服AMI码的缺点而出现的,具有能量分散,抗破坏性强等特点。
三阶高密度双极性码用于所有层次的欧洲E-carrier系统,HDB3码将4个连续的"0"位元取代成"000V"或"B0OV"。这个做法可以确保连续的相隔单数的一般B记号。
3.2 HDB3 的编码转换规则
HDB3码的编码规则主要分为3步:
1.先将消息代码变换成AMI码,若AMI码中连0的个数小于4,此时的AMI码就是HDB3码;
2.若AMI码中连0的个数大于等于4,则将每4个连0小段的第4个0变换成与前一个非0符号(+1或-1)同极性的符号,用表示(+V,-V);
3.为了不破坏极性交替反转,当相邻V符号之间有偶数个非0符号时,再将该小段的连0码元段的第1个0变换成+B或-B,B的符号与前一非零符号的相反,并让后面的非零符号从符号开始再交替变化。
例如:
消息代码: 10000100001 100001 1
AMI码: +10000-10000+1-10000+1-1
HDB3码:+1 000+V-1000-V+1-1 +B00+V-1 +1
HDB3码: +1000+1-1000-1 +1-1 +100+1-1 +1
3.3 HDB3 码的解码转换规则
虽然编码很复杂,但解码规则很简单,就是把原来的取代节(4个连零)找到即可,若3连"0"前后非零脉冲同极性,则将最后一个非零元素译为零,如+1000+1就应该译成10000", 否则不用改动;若2连"0"前后非零脉冲极性相同,则两零前后都译为零,如-100-1, 就应该译为0000,否则也不用改动。再将所有的-1变换成+1后,就可以得到原消息代码。
例如:
HDB3: 0+1 00-1000-1 +1000+1-1 +1-1 00-1 +1 00-1
译码: 01 001 00001000011000000100 1
四、设计过程
4.1 HDB3码的系统结构与方案设计
4.2 HDB3码硬件电路设计与搭建
在硬件电路中,我们使用了STM32作为CPU,实验室信号发生器作为信号源(使用模拟电压信号),使用STM32上的LED屏作为显示模块,形成一个简单的硬件电路完成HDB3码的编码与解码。
4.3 HDB3码的软件设计过程
4.3.1 HDB3码编码译码功能设计
HDB3编码主要分为3个部分消息码转换为AMI码,由于AMI码存在一定缺点,再进行HDB3编码,HDB3码编码判断当出现4个连0时,第4个0变为V,加V后根据规则判断第1个0是否需要变为B(V和B本质上均为1)。
AMI码部分:对定义长度数组进行循环判断,当源码为0时,AMI码一定为0,当源码为1时,进行判断,第奇数个1 时AMI码为+1,第偶数个1 时AMI码为+1,此时完成源码到AMI码转换。
HDB3码编码部分:对定义长度数组进行循环判断,当源码为0时,判断连0个数是否大于4,当连0个数大于4时,此时第4位为V码,根据初始定义V码极性为正,对后续V码进行正负交替变换,并更新最后一个V码状态,确定V码正负状态后,需要对每一个V码及它对应的前一个信码的符号进行判断,若极性不同,则需要增加同极性补码B。如果第一位源码为1,则对应HDB3码的信码极性为+1,此后正负交替即可,将编码结果保存在相应数组中。
HDB3码译码部分:对HDB3码进行译码,对定义长度数组进行循环判断,当HDB3码为0时,译码结果一定为0,当HDB3码为1或-1时,如果当前HDB3码极性与前一个信码极性相同且连续0的个数大于等于2个,则当前HDB3码是V码,译码结果为0;如果连续0的个数等于2个,则前一个信码是补信码,译码结果为0;如果当前HDB3码是信码(含B及B’),则译码结果是1,完成HDB3译码,将译码结果保存在相应数组中。
4.3.2 AD转换模块
在AD转换模块中,将模拟信号经ADC通道1读入,存入buff数组中,经过精度转换计算出电压值(有效值),由于STM32自身运算速率及LCD屏扫描频率的限制,我们对输入的瞬时信号的最大幅度进行检测,仅取最大幅度的有效值为最终电压值,由于LCD显示函数对小数点的显示的不支持,为简化操作,我们将有效值电压以mV为单位(X1000倍)显示在波形区域的左侧。同时我们在LCD屏上以0.3V/格的单位精度画出buff数组中存储的输入信号的波形图(幅值为有效值)。
五、结论
5.1 调试的过程与结果展示
验证一:通过上图可以观察到,通过红绿两路信号进行作差,得到紫色波形,即HDB3编码波形,结果验证正确。
验证二:通过上图可以观察到,通过红绿两路信号进行作差,得到紫色波形,即HDB3编码波形,结果验证正确。
验证三:通过上图可以观察到,通过红绿两路信号进行作差,得到紫色波形,即HDB3编码波形,结果验证正确。
六、附录
(一)做的过程中编的一些函数
1、AMI码 HDB3码 .c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LENGTH 500 // sequence length
void AMI_Encoding(char *AMI, const char *source, int len);
void HDB3_Encoding(char *hdb3, const char *source, int len);
void HDB3_Decoding(char *source, const char *hdb3, int len);
/*
主函数,程序开始
*/
int main()
unsigned int i = 0;
FILE *file = NULL;
char SOURCE[LENGTH];
char AMI[LENGTH];
char HDB3[LENGTH];
char SOURCE1[LENGTH];
file = fopen("test_out.txt","w");
if(file == NULL)
printf("Error!");
exit(1);
srand((unsigned)time(NULL));//设置随机数种子
fprintf(file,"source: ");
for(i = 0; i < LENGTH ; i++)
//生成随机0、1序列,写入文件
*(SOURCE+i) = (rand())&0x01;
fprintf(file," %d ",*(SOURCE+i));
AMI_Encoding(AMI,SOURCE,LENGTH);
fprintf(file,"\\r\\nAMI: ");
for(i = 0; i < LENGTH ; i++)
//AMI码写入文件
if(*(AMI+i) >= 0)
fprintf(file," %d ",*(AMI+i));
else
fprintf(file,"%d ",*(AMI+i));
HDB3_Encoding(HDB3,SOURCE,LENGTH);
fprintf(file,"\\r\\nHDB3: ");
for(i = 0; i < LENGTH ; i++)
//HDB3码写入文件
if(*(HDB3+i) >= 0)
fprintf(file," %d ",*(HDB3+i));
else
fprintf(file,"%d ",*(HDB3+i));
HDB3_Decoding(SOURCE1,HDB3,LENGTH);
fprintf(file,"\\r\\ndecoding:");
for(i = 0; i < LENGTH ; i++)
//HDB3译码结果写入文件
fprintf(file," %d ",*(SOURCE1+i));
fclose(file);
for(i = 0; i < LENGTH ; i++)//check
//比较HDB3译码结果与源码是否相同
if(*(SOURCE1+i) != *(SOURCE+i))
printf("decode error %d",i+1);
break;
return 0;
/*
Encode the source code as AMI code.
*/
void AMI_Encoding(char *AMI, const char *source, int len)
unsigned int i = 0;
unsigned int cnt_1 = 0;
for(i = 0; i< len; i++)
if(!source[i])//0
//源码是0的位置,AIM码一定是0
*(AMI+i) = 0;
else//1
//源码第奇数个1转换为AMI码的1,第偶数个1转换为AMI码的-1
cnt_1++;
*(AMI+i) = (cnt_1&0x01)?1:-1;
/*
Encode the source code as HDB3 code.
*/
void HDB3_Encoding(char *hdb3, const char *source, int len)
unsigned int i = 0;
unsigned int cnt_0 = 0; //记录连续0的个数
char last_b = 0; //记录上一个信码(含B及B')极性,初始化为0保证第一个信码极性为+1
char last_v = -1; //记录上一个V码极性,初始化为-1保证第一个V码极性为+1
for(i = 0; i < len; i++)
if(!source[i])
//源码为0
cnt_0++;
if(cnt_0 >= 4)
//连续0的个数大于4
cnt_0 = 0;
*(hdb3+i) = (last_v&0x80)?1:-1;//保证V码极性交替变化
last_v = *(hdb3+i);//更新last_v
if((last_v != last_b))
//如果当前V码与前一个信码极性不同,则增加同极性的补信码
*(hdb3+i-3) = last_v;
last_b = last_v;//更新last_b
else
*(hdb3+i) = 0;
else
//源码为1
cnt_0 = 0;
if(!last_b)
//如果是第一个为1的源码,则对应HDB3码的信码极性为+1
*(hdb3+i) = 1;
last_b = 1;
else
*(hdb3+i) = (last_b&0x80)?1:-1;//保证信码极性交替变化
last_b = *(hdb3+i);//更新last_b
/*
Decode HDB3 code.
*/
void HDB3_Decoding(char *source, const char *hdb3, int len)
unsigned int i = 0;
unsigned int cnt_0 = 0; //记录连续0的个数
char polarity = 0; //记录前一个信码(含B及B')极性
for(i = 0; i < len; i++)
if(!(*(hdb3+i)))
//HDB3码为0,译码结果一定是0
cnt_0++;
*(source+i) = 0;
else
//HDB3码为1或-1
if((*(hdb3+i) == polarity)&&(cnt_0 >= 2))
//如果当前HDB3码极性与前一个信码极性相同且连续0的个数大于等于2个
//则当前HDB3码是V码,译码结果为0
*(source+i) = 0;
if(cnt_0 == 2)
//如果连续0的个数等于2个,则前一个信码是补信码,译码结果为0
*(source+i-3) = 0;//修改补信码处的译码结果
else
//当前HDB3码是信码(含B及B'),译码结果是1
*(source+i) = 1;
polarity = *(hdb3+i);//记录信码极性
cnt_0 = 0;
2、HDB3编译源程序(写入数组中).c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LENGTH 12 // sequence length
void AMI_Encoding(char *AMI, const char *source, int len);
void HDB3_Encoding(char *hdb3, const char *source, int len);
void HDB3_Decoding(char *source, const char *hdb3, int len);
/*
主函数,程序开始
*/
int main()
unsigned int i = 0;
char SOURCE[LENGTH];//源码
char AMI[LENGTH];//编码生成AMI码
char HDB3[LENGTH];//编码生成HDB3码
char SOURCE1[LENGTH];//对HDB3码进行译码
srand((unsigned)time(NULL));//设置随机数种子
printf("源码: ");
for(i = 0; i < LENGTH ; i++)
//生成随机0、1序列,写入数组SOURCE
*(SOURCE+i) = (rand())&0x01;
printf(" %d ",*(SOURCE+i));
printf("\\n");
printf("AMI码: ");
AMI_Encoding(AMI,SOURCE,LENGTH);
for(i = 0; i < LENGTH ; i++)
//AMI码写入数组AMI
if(*(AMI+i) >= 0)
printf(" %d ",*(AMI+i));
else
printf("%d ",*(AMI+i));
printf("\\n");
printf("HDB3码: ");
HDB3_Encoding(HDB3,SOURCE,LENGTH);
for(i = 0; i < LENGTH ; i++)
//HDB3码写入数组HDB3
if(*(HDB3+i) >= 0)
printf(" %d ",*(HDB3+i));
else
printf("%d ",*(HDB3+i));
printf("\\n");
printf("译码结果:");
HDB3_Decoding(SOURCE1,HDB3,LENGTH);
for(i = 0; i < LENGTH ; i++)
//HDB3译码结果写入数组SOURCE1
printf(" %d ",*(SOURCE1+i));
printf("\\n");
for(i = 0; i < LENGTH ; i++)//check
//比较HDB3译码结果与源码是否相同
if(*(SOURCE1+i) != *(SOURCE+i))
printf("decode error %d",i+1);
break;
return 0;
/*
@Encode the source code as AMI code.
*/
void AMI_Encoding(char *AMI, const char *source, int len)
unsigned int i = 0;
unsigned int cnt_1 = 0;
for(i = 0; i< len; i++)
if(!source[i])//0
//源码是0的位置,AIM码一定是0
*(AMI+i) = 0;
else//1
//源码第奇数个1转换为AMI码的1,第偶数个1转换为AMI码的-1
cnt_1++;
*(AMI+i) = (cnt_1&0x01)?1:-1;
/*
Encode the source code as HDB3 code.
*/
void HDB3_Encoding(char *hdb3, const char *source, int len)
unsigned int i = 0STM32基带HDB3编解码系统设计(附完整代码)
Matlab基于μ律15折线的PCM语音编解码系统(GUI设计simulink附完整代码)
Matlab基于μ律15折线的PCM语音编解码系统(GUI设计simulink附完整代码)