曼彻斯特解码程序

合集下载

曼彻斯特解码方法

曼彻斯特解码方法

曼彻斯特解码方法曼彻斯特解码方法是一种用于将二进制数据转换为可读文本的方法,它起源于1950年代的曼彻斯特大学。

这种解码方法被广泛应用于计算机科学和通信领域,特别是在网络通信中。

曼彻斯特解码方法的基本原理是将每个二进制位转换为一个时间间隔,通过这种方式来表示数据。

具体而言,如果一个二进制位为0,则对应的时间间隔为高电平持续一段时间,而如果一个二进制位为1,则对应的时间间隔为低电平持续一段时间。

通过解码这些时间间隔,我们可以恢复出原始的二进制数据。

曼彻斯特解码方法的优点之一是它具有很好的抗干扰性能。

由于每个二进制位都被表示为一个时间间隔,即使在信号传输过程中产生了一些噪声,我们仍然可以通过判断时间间隔的长短来正确解码数据。

这在无线通信和有线通信中都非常有用,因为信号的传输过程中常常会受到各种干扰。

另一个优点是曼彻斯特解码方法可以很容易地实现同步。

由于每个二进制位都被表示为一个时间间隔,接收方可以通过检测时间间隔的变化来确定数据的起始点,并与发送方进行同步。

这对于数据的正确接收非常重要,尤其是在高速数据传输中。

曼彻斯特解码方法虽然具有很多优点,但也存在一些限制。

首先,由于每个二进制位都需要表示为一个时间间隔,这导致了数据传输速率的下降。

相比于其他编码方法,曼彻斯特解码方法的传输速率较低。

其次,由于每个二进制位都需要表示为一个时间间隔,这意味着数据的传输距离受到限制。

在远距离传输中,由于信号衰减和传输延迟等问题,曼彻斯特解码方法可能会导致数据错误。

尽管存在一些限制,曼彻斯特解码方法仍然被广泛应用于许多领域。

在计算机网络中,以太网中的物理层就使用了曼彻斯特解码方法。

在无线通信中,蓝牙和红外线通信等也采用了曼彻斯特解码方法。

此外,在一些特殊的应用中,如音频和视频传输,曼彻斯特解码方法也得到了广泛应用。

曼彻斯特解码方法是一种将二进制数据转换为可读文本的方法,它具有抗干扰性能强、易于实现同步等优点。

尽管存在一些限制,但曼彻斯特解码方法仍然是计算机科学和通信领域中重要的编码方法之一。

AVR单片机 曼彻斯特编码 中断方式解码C程序文件

AVR单片机 曼彻斯特编码 中断方式解码C程序文件

96
{
97
if ((capbuf[j] + capbuf[j+1] + capbuf[j+2] + capbuf[j+3])%2 != capbuf[j+4])
98
{
99
return ; //行偶校验失败
100
}
101
}
102
PrintString("找到啦!\r\n");
103
for (i = 0, j = 0; i < 5; i++, j += 10)
104
{
105
num = capbuf[j] << 7;
106
num |= capbuf[j+1] << 6;
107
num |= capbuf[j+2] << 5;
108
num |= capbuf[j+3] << 4;
109
num |= capbuf[j+5] << 3;
110
num |= capbuf[j+6] << 2;
57 void UARTInit(void)
58 {
59
UCSR0B |= (1<<TXEN0)|(1<<RXEN0);
60
UBRR0H = 0;
61
UBRR0L = 12;
62
UCSR0C = 0x6;
63 }
64
65 void UARTSend(char c)
66 {
67
while(!(UCSR0A & (1 << UDRE0)));

曼彻斯特编解码电路设计毕业设计

曼彻斯特编解码电路设计毕业设计

毕业设计(论文)题目名称:曼彻斯特编解码电路设计学生姓名:院(系):电子信息学院专业班级:电气10602指导教师:辅导教师:时间:2010年3月15日至2010年6月10日目录毕业设计(论文)开题报告 (V)曼彻斯特编解码电路设计 (12)Manchester encoding and decoding circuit (13)前言 0曼彻斯特编解码电路设计 (1)1 选题背景 (1)普通NRZ码存在的问题 (1)应用背景 (1)2 方案论证 0曼彻斯特码简介 0曼彻斯特编解码解析 0曼彻斯特编解码具体实现方式 (1)方案选择 (2)3 硬件电路设计 (5)系统实物照片展示 (5)系统的硬件框图 (6)AT89S52单片机简介 (7)单片机外围电路 (9)信号调理电路 (13)4 软件设计 (16)资源利用 (16)曼彻斯特码编解码方式分析 (18)程序流程图 (19)编码实现 (21)改良方向 (24)参考文献 (26)致谢 (27)附录1:地下液位测量系统实物照片 (28)长江大学毕业设计(论文)任务书学院(系)电子信息学院专业电气工程及自动化班级电气10602学生姓名熊香春指导教师/职称吴爱平/讲师1.毕业设计(论文)题目曼彻斯特编解码电路设计2.毕业设计(论文)起止时刻:2010年3月15日-2010年6月10日3.毕业设计(论文)所需资料及原始数据(指导教师选定部份)所需资料:(1)《MCS-51单片机原理与应用》(2)《单片机的C语言编程》(3) 通信原理原始数据传输速度为20Kb/S,一帧数据有16个字节,一帧的命令有2个字节。

4.毕业设计(论文)应完成的主要内容(1)利用C语言编程实现曼彻斯特编码、解码模块,并在PROTUES软件中仿真;(2)设计曼彻斯特信号调理电路;(3)毕业论文中必需包括如下内容:大体原理介绍、整体框图、软件流程图、软件原理介绍、源程序清单。

5.毕业设计(论文)的目标及具体要求利用单片机和C语言编程实现曼彻斯特编码、解码模块,并在PROTUES软件中仿真通过;通过单片机最小系统,辅之外围电路,能够实现编解码。

曼彻斯特码

曼彻斯特码

曼彻斯特码1、将10111001换成曼彻斯特编码.解:根据基本曼彻斯特编码原理和差分曼彻斯特编码原理将10111001换成曼彻斯特编码如下表:原码基本曼彻斯特编码差分曼彻斯特编码10111001 1001101010010110 10100110010101102、曼彻斯特码的编码原理是:由每位的中间为采样时间,如果电平由高电平跳变为低电平,则为“1”;反之则为“0”;3、差分曼彻斯特码的编码原理是:由每位的开始是否存在电压跳变,如果有,则为“0”,反之为“1”。

今天看了一下从fpga上下的曼彻斯特编解码的程序,感觉不是很清楚,仿真了一下,更迷茫了,大家看看为啥这程序要这么编呢?程序比较长,不过写的应该还是不错的,看了后应该有收获。

总的思路是这样:1 通过一个高频的时钟检测wrn信号,如果检测到上升沿,则表明开始编码,将输入的8位数据转为串行,并编码,然后输出。

2 定时信号是从高频时钟16分频后得到的,在wrn上升沿后16分频使能,在编码结束后禁止分频输出。

3 no_bits_sent记录串行输出的位数,应该是从0010到1001输出串行信号,到1010时编码结束,输出tbre表明编码完成。

问题是no_bits_sent在到了1010后还是会继续增加,直到1111,然后clk1x_enable 就为0,无法分频,clk1x就为一直流信号。

这样当clk1x_enable再次为1的时候,no_bits_sent也不会增加,在1111上不变,clk1x_enable又会回到0了。

//***************************************************************************** *** File Name: me.v* Version: 1.0* Date: January 22, 2000* Model: Manchester Encoder Chip** Company: Xilinx*** Disclaimer: THESE DESIGNS ARE PROVIDED "AS IS" WITH NO WARRANTY* WHATSOEVER AND XILINX SPECIFICALL Y DISCLAIMS ANY* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR* A PARTICULAR PURPOSE, OR AGAINST INFRINGEMENT.** Copyright (c) 2000 Xilinx, Inc.* All rights reserved*******************************************************************************/module me (rst,clk16x,wrn,din,tbre,mdo) ;input rst ;input clk16x ;input wrn ;input [7:0] din ;output tbre ;output mdo ;wire clk1x ;reg clk1x_enable ;wire clk1x_disable ;reg [3:0] clkdiv ;reg [3:0] no_bits_sent ;wire mdo ;reg tbre ;reg [7:0] tsr ;reg [7:0] tbr ;reg parity ;reg wrn1 ;reg wrn2 ;// form 2 FF register for write pulse detectionalways @(posedge rst or posedge clk16x)if (rst)beginwrn2 <= 1'b1 ;wrn1 <= 1'b1 ;endelsebeginwrn2 <= wrn1 ;wrn1 <= wrn ;end// Enable clock when detect edge on write pulsealways @(posedge rst or posedge clk16x)beginif (rst)clk1x_enable <= 1'b0 ;else if (wrn1 == 1'b1 && wrn2 == 1'b0)clk1x_enable <= 1'b1 ;else if (no_bits_sent == 4'b1111)clk1x_enable <= 1'b0 ;end// Generate Transmit Buffer Register Empty signalalways @(posedge rst or posedge clk16x)beginif (rst)tbre <= 1'b1 ;else if (wrn1 == 1'b1 && wrn2 == 1'b0)tbre <= 1'b0 ;else if (no_bits_sent == 4'b1010)tbre <= 1'b1 ;elsetbre <= 1'b0 ;end// Detect edge on write pulse to load transmit bufferalways @(posedge rst or posedge clk16x)beginif (rst)tbr <= 8'h0 ;else if (wrn1 == 1'b1 && wrn2 == 1'b0)tbr <= din ;end// Increment clockalways @(posedge rst or posedge clk16x)beginif (rst)clkdiv <= 4'b0000 ;else if (clk1x_enable == 1'b1)clkdiv <= clkdiv + 1 ;endassign clk1x = clkdiv[3] ;// Load TSR from TBR, shift TSRalways @(posedge rst or posedge clk1x)beginif (rst)tsr <= 8'h0 ;else if (no_bits_sent == 4'b0001)tsr <= tbr ;else if (no_bits_sent >= 4'b0010 && no_bits_sent < 4'b1010) begintsr[7:1] <= tsr[6:0] ;tsr[0] <= 1'b0 ;endend// Generate Manchester data from NRZassign mdo = tsr[7] ^ clk1x ;// Generate parityalways @(posedge rst or posedge clk1x) beginif (rst)parity <= 1'b0 ;elseparity <= parity ^ tsr[7] ;end// Calculate number of bits sentalways @(posedge rst or posedge clk1x) beginif (rst)no_bits_sent <= 4'b0000 ;else if (clk1x_enable)no_bits_sent <= no_bits_sent + 1 ;// else if (no_bits_sent == 4'b1111) else if (clk1x_disable)no_bits_sent <= 4'b0000 ;endassign clk1x_disable = !clk1x_enable ; endmodule测试程序:(其中的系统函数编译有问题,可以删去)`timescale 1 ns / 1 nsmodule me_tf ;reg [7:0] din ;reg rst ;reg clk ;reg wr ;wire mdo ;wire ready ;me u1 (rst,clk,wr,din,ready,mdo) ; initial beginrst = 1'b0 ;clk = 1'b0 ;din = 8'h0 ;wr = 1'b0 ;me.clk1 = 1'b0 ;me.count = 3'b0 ;endinteger me_chann ;initial beginme_chann = $fopen("me.rpt") ;$timeformat(-9,,,5) ;endparameter clock_period = 10 ;setup_time = clock_period/4 ;always #(clock_period/2) clk = ~clk ;initial begin$fdisplay(me_chann, "Verilog simulation of Manchester encoder\n\n:); $shm_open("me.shm") ;$shm_probe("AS") ;$fmonitor(me_chann,"%ime=%t,rst=%b,wr=%b,me.clk=%b,din=%h,me.count=%b ,mdo=%b,ready=%b",$time,rst,wr,clk,me.clk1,din,me.count,mdo,ready) ; #5 rst = 1'b1;#15 rst = 1'b0 ;#(3 * clock_period - setup_time) din = 8'hff ;#(1 * clock_period) wr = 1'b1 ;#(1 * clock_period) wr = 1'b0 ;#(20 * clock_period) din = 8'haa ;#(1 * clock_period) wr = 1'b1 ;#(1 * clock_period) wr = 1'b0 ;#(20 * clock_period) din = 8'h00 ;#(1 * clock_period) wr = 1'b1 ;#(1 * clock_period) wr = 1'b0 ;#(20 * clock_period) din = 8'hf0 ;#(1 * clock_period) wr = 1'b1 ;#(1 * clock_period) wr = 1'b0 ;#(20 * clock_period) din = 8'h0f ;#(1 * clock_period) wr = 1'b1 ;#(1 * clock_period) wr = 1'b0 ;#(100 * clock_period) ;$fdisplay (me_chann,"\nSimulation of Manchester encoder complete."); $finish ;endendmodule。

曼彻斯特解码原则 125K EM4100系列RFID卡解码源程序分析资料

曼彻斯特解码原则 125K EM4100系列RFID卡解码源程序分析资料

曼彻斯特解码原则+125K EM4100系列RFID卡解码源程序分析曼彻斯特解码原则1.曼彻斯特编码曼彻斯特编码(Manchester Encoding),也叫做相位编码(PE),是一个同步时钟编码技术,被物理层使用来编码一个同步位流的时钟和数据。

曼彻斯特编码被用在以太网媒介系统中。

曼彻斯特编码提供一个简单的方式给编码简单的二进制序列而没有长的周期没有转换级别,因而防止时钟同步的丢失,或来自低频率位移在贫乏补偿的模拟链接位错误。

在这个技术下,实际上的二进制数据被传输通过这个电缆,不是作为一个序列的逻辑1或0来发送的(技术上叫做反向不归零制(NRZ))。

相反地,这些位被转换为一个稍微不同的格式,它通过使用直接的二进制编码有很多的优点。

曼彻斯特编码,常用于局域网传输。

在曼彻斯特编码中,每一位的中间有一跳变,位中间的跳变既作时钟信号,又作数据信号;从高到低跳变表示"1",从低到高跳变表示"0"。

还有一种是差分曼彻斯特编码,每位中间的跳变仅提供时钟定时,而用每位开始时有无跳变表示"0"或"1",有跳变为"0",无跳变为"1"。

对于以上电平跳变观点有歧义:关于曼彻斯特编码电平跳变,在雷振甲编写的<<网络工程师教程>>中对曼彻斯特编码的解释为:从低电平到高电平的转换表示1,从高电平到低电平的转换表示0,模拟卷中的答案也是如此,张友生写的考点分析中也是这样讲的,而《计算机网络(第4版)》中(P232页)则解释为高电平到低电平的转换为1,低电平到高电平的转换为0。

清华大学的《计算机通信与网络教程》《计算机网络(第4版)》采用如下方式:曼彻斯特编码从高到低的跳变是0 从低到高的跳变是1。

两种曼彻斯特编码是将时钟和数据包含在数据流中,在传输代码信息的同时,也将时钟同步信号一起传输到对方,每位编码中有一跳变,不存在直流分量,因此具有自同步能力和良好的抗干扰性能。

RFID—曼彻斯特解码器

RFID—曼彻斯特解码器

谢谢观赏
RFID标签芯片
—曼彻斯特简码器
电路与系统
冯海洋
2012.3.4
曼彻斯特简码器
功能描述
曼彻斯特解码器的功能是对模拟前端解调出来的 曼彻斯特码进行解码,并提取同步时钟。 具体分为四步:
1.对曼彻斯特码进行同步,消除可能产生的毛刺。 2.对数据的帧头进行识别。 3.对分隔符进行识别。 4.对数据进行解码
一个曼彻斯特码是由两个NRZ码构成。
曼彻斯特简码器
上升沿检测方法
根据数据延迟输出可以很好的判读上升沿,其具体实现 电路如下:
曼彻斯特简码器
下降沿检测方法
根据数据延迟输出可以很好的判读下降沿,其具体实现 电路如下:
曼彻斯特简码器
电路设计
根据其功能描述进行设计,本设计中主要部分为一 个状态机,其状态转移图如下:
曼彻斯特简码器
曼彻斯特码
曼彻斯特码是由NRZ码构成的,其共有四种状态,分 别如下:
曼彻斯特简码器 曼彻斯特解码算法
当NRZ为“01”的时候,曼彻斯特码为“0”;当 NRZ为“10”的时候,曼彻斯特码为“1”;当 NRZ为“11”和“00”的时候,曼彻斯特码不存 在。因为时钟频率为1.28MHz,而曼彻斯特码 的传输速率为40KHz,所以只需要设计一个32 位计数器,在计数器计数到一半的时候进行判 断。若其为上升沿,则输出为“0”;若其为下 降沿,则输出为“1”。
曼彻斯特简码器
状态机描述
S_quiet :当复位时候进入此状态,此状态下检测到的输入数据为低电平,若检 测到上升沿则转换至S_preamble_detect状态,否则状态保持不变。 S_preamble_detect:帧头检测域,由一个持续时间至少为400s的稳定的无调制 的载波组成。此状态下,输入数据一直为高电平,若检测到数据的下降沿,状态 转换至S_preamble状态,否则状态保持不变。 S_preamble:检测帧头9个“01”。利用计数器对“01”的个数进行计数。若结果 为9 时,则说明帧头正确,状态转换至S_delimiter 状态;若结果为10,则说明该信 号为阅读器发送的再同步信号,此时,解码器输出再同步信号resynce,状态转换 至S_quiet状态;否则状态转换至S_quiet状态。

matlab 曼彻斯特码编解码

matlab 曼彻斯特码编解码

matlab 曼彻斯特码编解码Matlab是一种用于科学计算和工程领域的编程语言和开发环境。

在通信领域中,编码和解码技术起着重要的作用。

曼彻斯特编码是一种常用的线路编码方式,可以将数字信号转换为对应的数据序列,以便在传输过程中进行可靠的数据传输。

本文将介绍如何使用Matlab进行曼彻斯特码的编码和解码。

一、曼彻斯特编码曼彻斯特编码是一种基于时钟信号的线路编码方式,它将每个比特分为两个时钟周期,每个时钟周期内信号的电压变化表示不同的数据。

具体来说,当输入数据为1时,信号在一个时钟周期内由高电平变为低电平,而当输入数据为0时,信号在一个时钟周期内由低电平变为高电平。

这种编码方式能够提高传输的可靠性和抗干扰能力。

在Matlab中,可以使用以下代码实现曼彻斯特编码:```matlabfunction manchesterCode = encodeManchester(data)N = length(data);manchesterCode = zeros(1, 2*N);for i = 1:Nif data(i) == 1manchesterCode(2*i-1) = 1;elsemanchesterCode(2*i) = 1;endendend```上述代码中,encodeManchester函数接受一个输入数据序列,并返回对应的曼彻斯特编码序列。

首先,我们获取输入数据的长度N,并初始化一个长度为2N的输出序列manchesterCode。

然后,对于输入数据中的每个比特,若为1,则在输出序列的奇数索引位置处设置为1,若为0,则在输出序列的偶数索引位置处设置为1。

最后,返回曼彻斯特编码序列。

二、曼彻斯特解码对于接收到的曼彻斯特编码序列,我们需要进行解码操作,将其还原为原始的数据序列。

在曼彻斯特编码中,每个时钟周期内信号的电压变化表示一个比特的数据。

因此,我们可以根据电压变化的情况来判断数据的取值,例如,当信号由高电平变为低电平时,表示该比特为1,而当信号由低电平变为高电平时,表示该比特为0。

简单的曼彻斯特编码的C语言实现

简单的曼彻斯特编码的C语言实现

简单的曼彻斯特编码的C语言实现曼彻斯特编码是减小信号交流分量,实现固定信号占空比的基本方法。

用C语言实现如下:#include <stdio.h>#define uint8_t unsigned char#define uint16_t int#define BOOL int#define TRUE 1#define FALSE 0BOOL app_ManchesterEncode(uint8_t *indata,uint8_t *outdata,uint16_t inlength);BOOL app_ManchesterDecode(uint8_t *indata,uint8_t *outdata,uint16_t inlength);uint8_t indata[10]={0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0x43,0xb8};uint8_t middata[20];uint8_t outdata[10];uint16_t inlength;int main(){int length=10;int i=0;app_ManchesterEncode(indata,middata,length);if(app_ManchesterDecode(middata,outdata,length*2)==FALSE)printf("decode failed!\n");printf("in:");for(i=0;i<length;i++)printf(" %2.2x",indata[i]);printf("\n");printf("mid:");for(i=0;i<length*2;i++)printf(" %2.2x",middata[i]);printf("\n");printf("out:");for(i=0;i<length;i++)printf(" %2.2x",outdata[i]);printf("\n");}BOOL app_ManchesterEncode(uint8_t *indata,uint8_t *outdata,uint16_t inlength) {uint16_t i=0;uint8_t j=0;for(i=0;i<inlength;i++){outdata[2*i]=0;outdata[2*i+1]=0;for(j=0;j<8;j++)if(j<4)outdata[2*i+1]|=(((indata[i]>>j)&0x01)?2:1)<<j*2;elseoutdata[2*i]|=(((indata[i]>>j)&0x01)?2:1)<<(j*2-8);}return TRUE;}BOOL app_ManchesterDecode(uint8_t *indata,uint8_t *outdata,uint16_t inlength) {uint16_t i=0;uint8_t j=0;for(i=0;i<inlength/2;i++){outdata[i]=0;for(j=0;j<8;j++){if(j<4){if((indata[2*i+1]>>(j*2)&0x03)==0x01);else if((indata[2*i+1]>>(j*2)&0x03)==0x02)outdata[i]|=0x01<<j;else{printf("at i=%d j=%d data:%2.2x ",i,j,indata[2*i+1]&0x03);return FALSE;}}else{if((indata[2*i]>>(j*2-8)&0x03)==0x01);else if((indata[2*i]>>(j*2-8)&0x03)==0x02)outdata[i]|=0x01<<j;else{printf("at i=%d j=%d\n",i,j);return FALSE;}}}}return TRUE;}。

曼彻斯特编码和解码的FPGA电路设计

曼彻斯特编码和解码的FPGA电路设计
2.2
曼彻斯特码是通过电平的跳变来对二进制数据“0”和“1”进行编码的,对于何种电平跳变对应何种数据,实际上有两种不同的数据约定:第一种约定是由G. E. Thomas,Andrew S. Tanenbaum等人在1949年提出的,它规定“0”是由低到高的电平跳变表示,“1”是由高到低的电平跳变;第二种约定则是在IEEE 802.4(令牌总线)以及IEEE 802.3(以太网)中规定,按照这样的说法,由低到高的电平跳变表示“1”,由高到低的电平跳变表示“0”。在实际工程上,这两种约定在一定范围内均有应用。为了便于描述,若无特殊说明,本篇论文中的曼彻斯特码的编码规则均采用第二种约定,即从低电平跳变到高电平表示“1”,从高电平跳变到低电平表示“0”。
The thesismainly discusses the theory of theManchestercode anditscoding rules, it also explains itscharacteristics and use range.The theory puts forward theManchestercoding and decoding proposals and conducts the hardwaresimulatingonthesynchronized signal pick-up module with the VHDL language.This proposal has successfully met the requirement ofManchestercode date transfer and it is also sample in the circuit and stable in the capability.
曼彻斯特编码是串行数据传输的一种重要的编码方式。和最常用的NRZ码相比,曼彻斯特码具有很多优点。例如,消除了NRZ码的直流成分,具有时钟恢复和更好的抗干扰性能,这使它更适合于信道传输。

曼彻斯特解码原则+125K EM4100系列RFID卡解码源程序分析

曼彻斯特解码原则+125K EM4100系列RFID卡解码源程序分析

曼彻斯特解码原则+125K EM4100系列RFID卡解码源程序分析曼彻斯特解码原则1.曼彻斯特编码曼彻斯特编码(Manchester Encoding),也叫做相位编码(PE),是一个同步时钟编码技术,被物理层使用来编码一个同步位流的时钟和数据。

曼彻斯特编码被用在以太网媒介系统中。

曼彻斯特编码提供一个简单的方式给编码简单的二进制序列而没有长的周期没有转换级别,因而防止时钟同步的丢失,或来自低频率位移在贫乏补偿的模拟链接位错误。

在这个技术下,实际上的二进制数据被传输通过这个电缆,不是作为一个序列的逻辑1或0来发送的(技术上叫做反向不归零制(NRZ))。

相反地,这些位被转换为一个稍微不同的格式,它通过使用直接的二进制编码有很多的优点。

曼彻斯特编码,常用于局域网传输。

在曼彻斯特编码中,每一位的中间有一跳变,位中间的跳变既作时钟信号,又作数据信号;从高到低跳变表示"1",从低到高跳变表示"0"。

还有一种是差分曼彻斯特编码,每位中间的跳变仅提供时钟定时,而用每位开始时有无跳变表示"0"或"1",有跳变为"0",无跳变为"1"。

对于以上电平跳变观点有歧义:关于曼彻斯特编码电平跳变,在雷振甲编写的<<网络工程师教程>>中对曼彻斯特编码的解释为:从低电平到高电平的转换表示1,从高电平到低电平的转换表示0,模拟卷中的答案也是如此,张友生写的考点分析中也是这样讲的,而《计算机网络(第4版)》中(P232页)则解释为高电平到低电平的转换为1,低电平到高电平的转换为0。

清华大学的《计算机通信与网络教程》《计算机网络(第4版)》采用如下方式:曼彻斯特编码从高到低的跳变是0 从低到高的跳变是1。

两种曼彻斯特编码是将时钟和数据包含在数据流中,在传输代码信息的同时,也将时钟同步信号一起传输到对方,每位编码中有一跳变,不存在直流分量,因此具有自同步能力和良好的抗干扰性能。

曼彻斯特解码程序

曼彻斯特解码程序

曼彻斯特解码1、变量定义 (2)2、Manchest初始化 (2)3、Manchest解码信号翻转 (3)4、过滤错误的卡号 (4)5、获取正确的卡号 (5)6、Manchest获取卡号数据 (6)7、通过中断采样获取刷卡数据 (9)1、变量定义#define TH1_370US_H 0XFE //晶振11.0592MHZ,12T模式#define TL1_370US_L 0XAB#define SIGNAL_FLIP_TIME 10 //每隔100ms翻转一次读卡信号#define REPEAT_TIME 5 //500ms后重复读卡#define CLEAR_CARD_TIME 20 //2S后清除卡号数据#define MANCHEST_TIME 5sbit PULSE = P3^2;sbit RFEN = P3^5; //曼彻斯特解码脉冲信号sbit MANCHEST0= P3^2; //wiegand0sbit MANCHEST1= P3^3; //wiegand1uchar code CheckingTab[32]={ //接收到10组卡号的偶校验0X00,0X01,0X01,0X00,0X01,0X00,0X00,0X01, //这里数值是低五位的偶校验值0X01,0X00,0X00,0X01,0X00,0X01,0X01,0X00,0X01,0X00,0X00,0X01,0X00,0X01,0X01,0X00,0X00,0X01,0X01,0X00,0X01,0X00,0X00,0X01};uchar WGCardBuf[5]; //卡号uchar CopyCardBuf[5]; //备份卡号uchar ManchestBuf[11]; //暂存接收到的11组数据uchar idata g_ucManchestTime = MANCHEST_TIME; //uchar idata g_ucDWithCardTime= 0; //隔500ms处理该卡号uchar idata g_ucPreambleFlag = 0;uchar idata g_ucERAgainTimer = 0; //每隔100ms翻转一次RFENuchar idata g_ucStoreGroupCnt= 0; //接收到几组数据,这里为11组才可能正确uchar idata g_ucEGroupBitCnt = 0; //每组数据有5个为,5=4位卡号+1位偶校验uchar idata g_ucPreambleCount= 0; //9位为1的引导码uchar idata g_ucRemvoeCardTime=0; //隔多久清除以前的卡号数据,这里为3s2、Manchest初始化/******************************************************************** 函数原型:ManchestInit功能:曼彻斯特解码变量初始化输入:无输出:无说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ void ManchestInit(void) //初始化读卡参数{RFEN = 1;g_ucPreambleFlag = 0;g_ucStoreGroupCnt = 0;g_ucEGroupBitCnt = 5;g_ucPreambleCount = 9;g_ucERAgainTimer = SIGNAL_FLIP_TIME;}3、Manchest解码信号翻转/******************************************************************** 函数原型:ProcessManchestSignal功能:manchest解码的翻转信号输入:无输出:无说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ void ProcessManchestSignal(void){if((g_ucDWithCardTime!=0)&&(--g_ucDWithCardTime==0)){}if((g_ucRemvoeCardTime!=0)&&(--g_ucRemvoeCardTime==0)){CopyCardBuf[0] = 0; //清除卡号缓冲区CopyCardBuf[1] = 0;CopyCardBuf[2] = 0;CopyCardBuf[3] = 0;CopyCardBuf[4] = 0;}RFEN = ~RFEN;g_ucPreambleFlag = 0;g_ucPreambleCount= 9;if(RFEN){EX0 = 1;EX1 = 1;}else{EX0 = 0;EX1 = 0;}}4、过滤错误的卡号/******************************************************************** 函数原型:CalibrationCardData功能:一张卡号,如果出现全部相同的数字或者该卡号只有两种数据,则认为是错误的卡号。

曼彻斯特编码算法

曼彻斯特编码算法

曼彻斯特编码算法详解一、引言曼彻斯特编码是一种被广泛使用的,针对模拟信号的编码方式。

它是由英国科学家弗雷德里克·威廉·汤姆林森(Frederick William Tomlinson)在1880年代后期发明的。

由于其简单性、鲁棒性和兼容性,曼彻斯特编码在许多应用中都得到了广泛的使用,包括以太网和许多类型的数据通信系统。

二、工作原理曼彻斯特编码的原理是将每一个比特的周期划分为两个相等的时间段。

每个时间段又被进一步划分为两个相等的子时间段。

然后根据比特的值,在这个时间段内,信号会有一个跳变或者没有跳变。

如果比特是1,那么在下一个时间段内,信号会有一个跳变;如果比特是0,那么在下一个时间段内,信号不会有一个跳变。

这种跳变既包含了比特的信息,也作为同步的信号使用。

三、编码规则以下是曼彻斯特编码的基本规则:将每个比特拆分成两个时间间隔,第一个时间间隔代表该比特的值(1或0),第二个时间间隔代表该比特值的相反值。

1. 比特1:信号在一个时间段内保持稳定,然后在下一个时间段内跳变。

2. 比特0:信号在一个时间段内保持稳定,然后在下一个时间段内保持与前一个时间段相同的状态(即不跳变)。

四、优点和应用曼彻斯特编码有以下优点:1. 自同步:由于每个比特的开始都有跳变,所以接收器可以通过检测这个跳变来实现位同步。

2. 错误检测:由于每个比特都被编码为两个不同的电平,所以可以很容易地实现错误检测。

如果接收到的比特与发送的比特不同,那么可以立即发现错误。

3. 简单:曼彻斯特编码的实现非常简单,只需要一个电压比较器和一个触发器就可以实现。

曼彻斯特编码广泛应用于以太网、令牌环等网络技术中。

此外,它还被用于数字音频和视频传输、硬盘驱动器、射频识别(RFID)等领域。

五、缺点尽管曼彻斯特编码有许多优点,但它也有一些缺点:1. 效率低:由于每个比特都被编码为两个电平,所以曼彻斯特编码的效率比其它一些编码方式(如二进制或不归零制)低。

曼彻斯特码编解码的FPGA设计与实现

曼彻斯特码编解码的FPGA设计与实现

曼彻斯特码编解码的FPGA设计与实现首先,我们需要了解曼彻斯特编码的原理。

曼彻斯特编码将原始数据流分为两个时钟周期,每个时钟周期分为两个等时长的时间片。

根据原始数据的高低电平来确定时间片内信号的取值。

如果原始数据为0,则在时间片的中间边沿处信号发生跳变;如果原始数据为1,则在时间片的开始边沿处信号发生跳变。

编码后的数据流中,跳变表示1,不跳变表示0。

接下来,我们将使用FPGA设计和实现曼彻斯特码编解码器。

首先,我们需要在FPGA上实现一个时钟产生器,用于生成系统的时钟信号。

然后,我们可以使用FPGA上的逻辑门和触发器来实现曼彻斯特编解码逻辑。

对于曼彻斯特编码器,我们可以使用一个D触发器和一个异或门来实现。

D触发器的输入连接到原始数据流,时钟信号作为时钟输入。

异或门的一个输入连接到D触发器的输出,另一个输入连接到D触发器的Q输出。

异或门的输出即为编码后的数据流。

对于曼彻斯特解码器,我们可以使用两个D触发器和一个与门来实现。

第一个D触发器的输入连接到编码后的数据流,时钟信号作为时钟输入。

第二个D触发器的输入连接到第一个D触发器的Q输出,时钟信号作为时钟输入。

与门的一个输入连接到第一个D触发器的Q输出,另一个输入连接到第二个D触发器的Q输出。

与门的输出即为解码后的数据流。

在设计和实现时,我们需要注意时钟的频率和时序的约束。

FPGA提供了丰富的开发工具和资源,我们可以使用Verilog或VHDL等HDL语言进行设计和仿真。

使用FPGA开发板进行验证和测试时,可以将编解码器的输入和输出连接到开发板的IO接口上,通过外部设备进行数据输入和输出,然后通过开发板上的LED或显示屏等显示解码结果。

总结而言,曼彻斯特码编解码的FPGA设计和实现需要借助FPGA的逻辑门和触发器等资源,使用Verilog或VHDL等HDL语言进行设计和仿真,最终通过开发板进行验证和测试。

通过这种方式,我们可以实现高效可靠的曼彻斯特码编解码器,满足通信系统对于数据传输的需求。

曼彻斯特解码原则+125K EM4100系列RFID卡解码源程序分析

曼彻斯特解码原则+125K EM4100系列RFID卡解码源程序分析

曼彻斯特解码原则+125K EM4100系列RFID卡解码源程序分析曼彻斯特解码原则1.曼彻斯特编码曼彻斯特编码(Manchester Encoding),也叫做相位编码(PE),是一个同步时钟编码技术,被物理层使用来编码一个同步位流的时钟和数据。

曼彻斯特编码被用在以太网媒介系统中。

曼彻斯特编码提供一个简单的方式给编码简单的二进制序列而没有长的周期没有转换级别,因而防止时钟同步的丢失,或来自低频率位移在贫乏补偿的模拟链接位错误。

在这个技术下,实际上的二进制数据被传输通过这个电缆,不是作为一个序列的逻辑1或0来发送的(技术上叫做反向不归零制(NRZ))。

相反地,这些位被转换为一个稍微不同的格式,它通过使用直接的二进制编码有很多的优点。

曼彻斯特编码,常用于局域网传输。

在曼彻斯特编码中,每一位的中间有一跳变,位中间的跳变既作时钟信号,又作数据信号;从高到低跳变表示"1",从低到高跳变表示"0"。

还有一种是差分曼彻斯特编码,每位中间的跳变仅提供时钟定时,而用每位开始时有无跳变表示"0"或"1",有跳变为"0",无跳变为"1"。

对于以上电平跳变观点有歧义:关于曼彻斯特编码电平跳变,在雷振甲编写的<<网络工程师教程>>中对曼彻斯特编码的解释为:从低电平到高电平的转换表示1,从高电平到低电平的转换表示0,模拟卷中的答案也是如此,张友生写的考点分析中也是这样讲的,而《计算机网络(第4版)》中(P232页)则解释为高电平到低电平的转换为1,低电平到高电平的转换为0。

清华大学的《计算机通信与网络教程》《计算机网络(第4版)》采用如下方式:曼彻斯特编码从高到低的跳变是0 从低到高的跳变是1。

两种曼彻斯特编码是将时钟和数据包含在数据流中,在传输代码信息的同时,也将时钟同步信号一起传输到对方,每位编码中有一跳变,不存在直流分量,因此具有自同步能力和良好的抗干扰性能。

曼砌斯特解码

曼砌斯特解码

/**********************************************曼彻斯特编码调制的非接触ID卡通用读卡程序编制ID卡每位的脉宽为512us,每半位的脉宽256usCPU为Atmel公司的A T89S52芯片,晶振11.0592MHz读卡采用边沿检测方式,只要跳变边沿脉宽在要求的脉宽范围内就是合法脉宽每位脉宽要求490us-530us,半位要求为230us-280us,可根据调试更改定时器时间2010年3月11日东北大学通信与智能控制工作室/******************头文件********************/#include <REG52.h>#include <absacc.h>#include <intrins.h>/******************宏定义*********************/#define uchar unsigned char#define uint unsigned int#define ulint unsigned long int//#define SYSCLK 11059200 //使用外部晶振11.0592MHz//#define BAUD_RATE 2400 //这里没有采用//#define TCLK SYSCLK/12 ////#define TIME_COUNT (-(TCLK/BAUD_RA TE)) //+0x20 ////#define T1_1B_H TIME_COUNT >> 8 ////#define T1_1B_L TIME_COUNTsbit RF_DATA_IN =P3^2; //读卡卡号输入端,这里为外部0终端,最好改为普通的I/O sbit RF_LED_ON =P1^4; //原理机电平提取端,这里接在了原理机74HC14的第二次取反后sbit RUN_LED =P2^4; //测试用sbit RUN_LED1 =P2^3; //测试用sbit RUN_LED2 =P2^5; //测试用sbit RUN_LED3 =P2^6; //测试灿?sbit DIDA =P2^2; //蜂鸣器接口,高电平时蜂鸣,低电平时停止蜂鸣/****************全局变量**********************/uchar Read_RF_Data[11]; //从卡号输入端读取的暂存数据uchar Card_ID[10]; //卡号暂存数组uchar data ID_Data[6]; //暂存经效验后的正确数据uint data TIMER_1=0; //判断定时时用uchar RX0_DAT=0; //硬件串口接收到的字节数据uchar SUART0_RXD[10]; //硬件串口接收ID号数组uchar SUART0_NUM=0; //硬件串口计数变量bit Check_Data_bit; //效验请求标志位bit Check_Data_Ok =0; //校验正确标志位/****************函数列表***********************/void Recive_RF_Data(void);void Check_Data(void);void watchdog_init(void);void Clern_Number(void);void dogFeed(void);void delay0_2ms(uint count);void UART_TXD(uchar Data[],uchar Num); //这里两个发送函数是一样的,由于出现了语法错误,这里定义为了两个void UART0_TXD(uchar Data[],uchar Num);/**********************************************初始化程序**********************************************/void Data_start(void){TMOD=0x21; //T0方式1,T1工作于方式2TH1=0x00; //初始化T1计时器TL1=0x00;TR1=0;SCON=0x50; //串行口初始化// PCON=0x80; //SMOD位设置TH0=0x00; //初始化T0计时器TL0=0x04; //这里从0x0004开始,参考程序中是这个数值,改为从其他数开始也可以TR0=0;ES=1; //开放串行口中断EA=1; //开放总中断}/**********************************************I/O初始化程序,这里根据需要可修改**********************************************/void PORT_Init (void){P0=0xFF; //P1=0xFF; //P2=0xF0; // 蜂鸣器引脚采用的是P2.2,电路图中是P2.3,P2.2为高时蜂鸣器蜂鸣,为低时停止蜂鸣,这点注意初始化时要为0P3=0xCF; //}/**********************************************初始化程序,和data_start有点重复**********************************************/void UART0_Init (void){ES = 0; //禁止串口0中断SCON = 0x50; //串口工作方式1:8位(先低位)数据和//一位停止位,可变波特率.REN=1允许接收//清发送和接收中断标志RI、TIES = 1; //开UART0中断PCON = 0x00; //1/32PS = 1; //UART0中断优先级为高ES = 1; //串行中断允许}/****************************************************************************** *delay:延时子程序*延时时间待测******************************************************************************* /void delay(void){int t;for(t=0;t<200;t++);dogFeed(); //喂狗}/****************************************************************************** *delay_1s :延时子程序******************************************************************************* /void delay_long(int time){int t;for(t=0;t<time;t++){delay();dogFeed(); //喂狗}}/****************************************************************************** Timer2_Init:T2定时器初始化设置T2CON中的TCLK或RCLK选择定时器T2工作为波特率发生器方式,T2为串口UART0的波特率发生器:2400波特率, 该方式下T2计时脉冲为晶振频率的1/2(而不是1/12)晶振频率波特率=---------------- 2400BPD: FF 7032x[65536-(RCAP2H, RCAP2L)] 9600BPD: FF DC这里波特率改为了9600;******************************************************************************* /void Timer2_Init(void){TR2=0; //停T2定时器T2CON &= ~0x02; //T2为定时方式T2CON |= 0x30; //RX和TX都使用T2时钟RCAP2H = 0xFF; //9600波特率对应16位自动重加载寄存器赋值0xFFDCRCAP2L = 0xDC; //TH2 = RCAP2H; //TL2 = RCAP2L; //TR2 = 1; //启动T2}/****************************************************************************** **********看门狗初始化初始化时需要在reg52.h文件中声明看门狗寄存器地址语法为:sfr WDTRST = 0xA6;******************************************************************************* **********/void watchdog_init(void){WDTRST=0x1E;WDTRST=0xE1;}/***********************************看门狗子程序*****************************************功能:8ms不喂狗复位AT89S52内置看门过为13位定时器,最大计数8191个机器周期最大计时为8191*(12/11059200)=8.8878ms8ms不喂狗单片机复位******************************************************************************* **********/void dogfeed(void){WDTRST=0x1E;WDTRST=0xE1;//喂狗指令}/*********************************************//*接收RF数据*//*********************************************/void Recive_RF_Data(void){/////////////////////定义局部变量uchar header,pc;uchar temp;uchar temp1 =0x00;uint temp2;uchar ByteCounter; //字节计数器uchar *PData;uchar BitCounter; //位计数器////////////////////初始化变量值header=0;pc=4;PData=Read_RF_Data;temp=0;temp1=0;ByteCounter=0;BitCounter=5;/////////////////////检测一个稳定的低电平str://WATCHDOG=~WA TCHDOG;dogFeed();if(RF_DATA_IN==0)if(RF_DATA_IN==0)if(RF_DATA_IN==0)if(RF_DATA_IN==0)if(RF_DATA_IN==0){_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();////////////////////检测一个起始位电平while(RF_DA TA_IN==0) dogFeed(); //当电平由低向高跳变时启动计时器TR0=1; //此处喂狗挺关键的,当无卡时为低电平,无卡时在此等待不能喂狗_nop_(); //_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();// dogFeed();////////////////////检测9个"header"while(RF_DA TA_IN==1); //检测字头第一个高点平,为1时计时,这里的字头为末尾和开始的组合TR0=0;TF0=0;TIMER_1=TH0;TIMER_1=(TIMER_1<<8)+TL0;TH0=0x00;TL0=0x04;//temp2=0x01EC; //这里改为530us,计算方法为(0x01EC-0x0004)*12/11059200=0x01E8*12/11059200=488*1.0850694=530ustemp2=0x01FC; //这里改为547us,可根据调试调整参数if(TIMER_1>temp2){goto str;} //这里只要第一个字头在490us-547us之间就行//temp2=0xf9;temp2=0x01C7; //这里对应的时间为490usif(TIMER_1<temp2) // <490us{goto str;}RUN_LED3 =!RUN_LED3; //检测到第一个字头LED闪烁一次do //接下来检测8位其余字头1{TIMER_1=0;//WATCHDOG=~WA TCHDOG;dogFeed();while(RF_DA TA_IN==0) dogFeed(); //为低电平时等待,为高电平时跳出,计时开始TR0=1;_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();while(RF_DA TA_IN==1); //为1时计时开始// RUN_LED2 =!RUN_LED2;TR0=0;TF0=0;TIMER_1=TH0;TIMER_1=(TIMER_1<<8)+TL0;TH0=0x00;TL0=0x04;temp2=0x00FE; // 对应的时间为271us//temp2=0x012B; // >320usif(TIMER_1>temp2) //这里为曼码,半位时间为256us{ //这里只要检测半位脉宽在220us-271us之间就行,可根据调试调整计时参数header=0;goto str;}temp2=0x00CF;if(TIMER_1<temp2) // <220us{header=0;goto str;}header++;// RUN_LED2 =!RUN_LED2;}while(header<8); //8位高电平字头检测完毕退出RUN_LED2 =!RUN_LED2; //相应指示灯闪烁一次TR0=0;TF0=0;///////////////////如果9个"header"都对,开始接收卡内数据//TH0=0xff; //time:300us//TL0=0x6a;TH0=0xFE; //time:320us 这里采用计数溢出计时的TL0=0xD8; //计数方法为:(0xFFFF-0xFED8)*12/11059200=320us,采样到中间位置TR0=1;if(header==8){do{do{while(TF0==0); //等待320us,进入数据位的前半位TF0=0;if(RF_DATA_IN==1) temp=1;else temp=0;RUN_LED1 =!RUN_LED1;while(RF_DA TA_IN==temp) //检测电平是否跳变{ //等待跳变,当跳出跳变时又从新开始计时,计时大小为300usif(TF0==1) //如果300us计时到还未跳变,视为非法电平!!!{TR0=0;TF0=0;goto str;}}TH0=0xFE; //time:300us,从新赋值,开始计时TL0=0xEB;// TL0=0xD8; //time:320us// temp=~RF_DATA_IN;temp1=(temp1<<1)|temp; //采用循环的方式赋给临时变量BitCounter--;dogFeed();}while(BitCounter>0); //一个字节完否*(PData+ByteCounter)=temp1; //将一字节数据存入缓存数组temp1=0;BitCounter=5;ByteCounter++;//WATCHDOG=~WA TCHDOG;dogFeed();}while(ByteCounter<10);do{//WATCHDOG=~WA TCHDOG;dogFeed();while(TF0==0); //等待一个位周期TF0=0;if(RF_DATA_IN==1) temp=1;else temp=0;// RUN_LED1 =!RUN_LED1;while(RF_DA TA_IN==temp) //检测电平跳变否?{if(TF0==1) //如果300us计时到还未跳变,视为非法电平!!!{TR0=0;TF0=0;goto str;}}//TH0=0xff; //time:300us//TL0=0x6a;TH0=0xFE; //time:300usTL0=0xEB;//1TL0=0xD8; //time:320ustemp=~RF_DATA_IN;temp1=(temp1<<1)|temp;pc--;}while(pc); //一个字节完否Read_RF_Data[10]=temp1; //将一字节数据存入缓存数组///////////////////检测最后一个停止位while(TF0==0);TR0=0;TF0=0;if(RF_DATA_IN==1) temp=1;else temp=0;while(RF_DA TA_IN==temp) //检测电平跳变否?{if(TF0==1) //如果300us计时到还未跳变,视为非法电平!!!{TR0=0;TF0=0;goto str;}}temp=~RF_DATA_IN;dogFeed();if(temp==0) //如果停止位正确{Check_Data_bit=1; //置效验请求标志//RUN_LED2 =!RUN_LED2;}else //如果停止位不正确{Clern_Number(); //清除}}}}/*********************************************效验数据**这里只进行了行校验,没有进行列校验*参考的部分程序也只进行了行校验*********************************************/void Check_Data(void){/////////////////////定义局部变量uchar temp;uchar temp1;uchar ByteCounter; //数组计数器uchar ByteCounter1;uchar *PData;uchar *PData1;////////////////////初如化变量值PData=Read_RF_Data;PData1=ID_Data; //ID_Data暂存经效验后的正确数据temp=0;temp1=0;ByteCounter=0;ByteCounter1=0;Check_Data_Ok =0;/////////////////////循环效验//WATCHDOG=~WA TCHDOG;dogFeed();/////////////////////行校验for(ByteCounter1=0;ByteCounter1<5;ByteCounter1++)//有5个字节数据{temp=(((*(PData+ByteCounter))&0x10)>>4)+(((*(PData+ByteCounter))&0x08)>>3)+(((*(PData+ByteCounter))&0x04)>>2)+(((*(PData+ByteCounter))&0x02)>>1);if((temp&0x01)==((*(PData+ByteCounter))&0x01))//效验低4位{temp1=(*(PData+ByteCounter)&0xfe)<<3;ByteCounter++;temp=(((*(PData+ByteCounter))&0x10)>>4)+(((*(PData+ByteCounter))&0x08)>>3)+(((*(P Data+ByteCounter))&0x04)>>2)+(((*(PData+ByteCounter))&0x02)>>1);if((temp&0x01)==((*(PData+ByteCounter))&0x01))//效验高4位{*(PData1+ByteCounter1)=temp1|((*(PData+ByteCounter)&0xfe)>>1);//高低位生成一个字节存入数组ByteCounter++;}else{ByteCounter1=5;//只要有一组不对则退出效验Clern_Number();//并清所有数据}}else{ByteCounter1=5;//只要有一组不对则退出效验Clern_Number();//并清所有数据}// WATCHDOG=~W ATCHDOG;dogFeed();}/////////////////////列校验//......因没有必要所以先省略此处.........///////////////////////生成校验和,并发送出去if(ByteCounter==10){Check_Data_Ok =1;delay0_2ms(1000);}}//************************************************************/*清暂存器*///************************************************************void Clern_Number(void){uchar i;// WATCHDOG=~W ATCHDOG;dogFeed();for(i=0;i<10;i++){Read_RF_Data[i] =0;Card_ID[i] =0;SUART0_RXD[i] =0;}for(i=0;i<5;i++)ID_Data[i]=0; //卡号数据也进行清除}/****************************************************************************** *UART_TXD:向PC发送卡号数据这里定义了两个,和下面的一样,更改语法数据后可合为一个******************************************************************************** /void UART_TXD(uchar Data[],uchar Num){uchar i=0;uchar *PData;PData=Data;EX0=0;ES=0;for(i=0;i<Num;i++)//有Num组号码要发送{SBUF=*(PData+i);// SBUF =addr;while(TI==0);TI=0;//等待数据发送出去delay();//等待后再发dogFeed();}}/****************************************************************************** *UART0_TXD: 向PC发送卡号数据,这里为PC向读卡器发过命令后的向PC发送可以和上面的进行合并******************************************************************************* /void UART0_TXD(uchar Data[],uchar Num){uchar i=0;uchar *PData;PData=Data;EX0=0;ES=0;for(i=0;i<Num;i++)//有Num组号码要发送{SBUF=*(PData+i);// SBUF =addr;while(TI==0);TI=0;//等待数据发送出去delay();//等待后再发送dogFeed();}}/***************************************************** 延时时间还有待测量*****************************************************/ void delay0_2ms(uint count){uint k;while(count--!=0){for(k=0;k<50;k++){//WATCHDOG=~W ATCHDOG;dogFeed();}}}/***************************************************** 蜂鸣器蜂鸣函数可以单独写成子程序,这里没有运用*****************************************************/ /*void dida(uchar j){uchar i;for(i=0;i<j;i++){DD=0;delay_long(20);delay1ms(30);DD=~DD;delay1ms(30);}}*///*****************************************************/*将ID_Data中的5字节数据转换成Card_ID中的10字节数据*///*****************************************************void trans(void){Card_ID[0] = (ID_Data[0] >> 4) & 0x0F;Card_ID[1] = ID_Data[0] & 0x0F;Card_ID[2] = (ID_Data[1] >> 4) & 0x0F;Card_ID[3] = ID_Data[1] & 0x0F;Card_ID[4] = (ID_Data[2] >> 4) & 0x0F;Card_ID[5] = ID_Data[2] & 0x0F;Card_ID[6] = (ID_Data[3] >> 4) & 0x0F;Card_ID[7] = ID_Data[3] & 0x0F;Card_ID[8] = (ID_Data[4] >> 4) & 0x0F;Card_ID[9] = ID_Data[4] & 0x0F;dogFeed();}//*****************************************************/*码型转换方法1*///*****************************************************void hex_to_assic_1(void){ulint Card_Num;uchar i;trans();dogFeed();Card_Num = (ulint)(Card_ID[9]) + (ulint)(16)*(ulint)(Card_ID[8]) + (ulint)(256)*(ulint)(Card_ID[7]) + (ulint)(4096)*(ulint)(Card_ID[6]) + (ulint)(65536)*(ulint)(Card_ID[5]) + (ulint)(1048576)*(ulint)(Card_ID[4]);for(i = 9;i > 1;i--){Card_ID[i] =(Card_Num%10)+48; //48为ASCII码的值,0为48,1为49,依次类推。

曼切斯特编解码51程序

曼切斯特编解码51程序

#include "Manchester.h"/*******************************************************************************程序说明基于单片机的曼彻斯特编码程序,功能是将一个8位的数据(一个字节)进行曼彻斯特编码曼彻斯特编码的原则是:电平从高到低跳变表示'1',电平从低到高跳变表示'0'*******************************************************************************//*******************************************************************************曼彻斯特编码函数参数DataIn:将要进行编码的单字节数据返回值manchesterOut:编码后返回的与参数对应的曼彻斯特编码值*******************************************************************************/unsigned int CharToManchester(unsigned char Encode_Data){uint ManchesterOut = 0;uchar i = 0;for(i=0;i<8;i++){if(( Encode_Data&0x80)==0x80) //说明该位为1{ManchesterOut = ManchesterOut + 1; //写1ManchesterOut = ManchesterOut << 1;//左移一位,相当于在最低位写0if(i<7){ManchesterOut <<= 1;//移位准备编码下一位Encode_Data <<= 1; //待编码数据左移1位,为下一位数据编码做准备}}else if(( Encode_Data&0x80)==0)//说明该位为0{ManchesterOut <<= 1;//不写1移位相当于写0ManchesterOut += 1;//写1if(i<7){ManchesterOut <<= 1;//移位准备编码下一位Encode_Data <<= 1; //待编码数据左移1位,为下一位数据编码做准备}}}return ManchesterOut;//返回编码后的16位值}/*******************************************************************************曼彻斯特译码函数参数Manchester_In:将要进行编码的单字节数据返回值Decode_Data:译码后返回的与参数对应的值*******************************************************************************/uchar ManchesterToChar(uint Manchester_In){uchar Decode_Data = 0;uchar j = 0;uchar error=0;for(j=0;j<8;j++){if((Manchester_In&0xc000)==0x8000) //说明该位为10{Decode_Data = Decode_Data+1;if(j<7){Decode_Data <<= 1;//移位准备译码下一位Manchester_In<<= 2; //待译码数据左移2位,为下一位数据译码做准备}}else if((Manchester_In&0xc000)==0x4000) //说明该位为01{//Decode_Data = Decode_Data<<1; //直接左移1位代表写0if(j<7){Decode_Data <<= 1;//移位准备译码下一位Manchester_In<<= 2; //待译码数据左移2位,为下一位数据译码做准备}}else{error=1;break;}}。

曼彻斯特编码与解码实验

曼彻斯特编码与解码实验

计算机通信网实验一 曼彻斯特编码与解码实验一、实验目的1.掌握曼彻斯特编解码原理;2.了解如何利用曼彻斯特的时钟特征实现收/发时钟同步及其实现方法。

二、预习要求1.复习曼彻斯特编解码原理; 2.复习软件Maxpluss Ⅱ的使用方法。

三、实验原理1.编码原理在曼彻斯特编码方式中,每一位的中间有一个跳变,位中间的跳变为时钟,也作为数据。

从高电平到低电平的跳变表示数据“1”(称为“1”跳变)。

从低电平到高电平的跳变表示数据“0”(称为“0”跳变)。

因此发送时钟必须在发送数据位的中间进行采样,即发送时钟TxC 的频率应为数据TxD 频率的两倍。

2.解码原理解码可通过解码器来实现,解码器从曼彻斯特码中分离出接收数据RxD 与接收时钟RxC 。

具体方法是:解码器从曼码中分别提出“1”跳变和“0”跳变信号,但需区分位中跳变与位间跳变,前者是表示数据的跳变,后者是当数据中有连续“1”信号或连续“0”信号时产生的不反应数据特征的无效跳变。

解码器提取位中跳变后,可将其转换为二进制1212(1)D触发器在编码中的作用。

(2)D触发器的时钟信号为何用2TxC?2.解码电路(1)图中如何提取Mc中的“1”跳变和“0”跳变信号的,试解释4个非门和YH1的作用。

(2)八位移位寄存器的作用是取得延迟信号,用于封住YF门以便除去无效的位间跳Q)的输出,是否可选择用其它输出?为变。

延迟时间应如何选取?为何选用第七位(7什么?(3)移位寄存器的时钟为什么要用8TxC(TxC的8倍频信号),如选用16TxC或4TxC 将会如何?八、实验报告要求1.绘制编解码电路图(给定或自行设计均可);2.描绘8TxC、TxC、Mc、A、B、B’、C、D、Q G1、Q G2、RxD、RxC各点信号波形图;3.回答思考题。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

曼彻斯特解码1、变量定义 (2)2、Manchest初始化 (2)3、Manchest解码信号翻转 (3)4、过滤错误的卡号 (4)5、获取正确的卡号 (5)6、Manchest获取卡号数据 (6)7、通过中断采样获取刷卡数据 (9)1、变量定义#define TH1_370US_H 0XFE //晶振11.0592MHZ,12T模式#define TL1_370US_L 0XAB#define SIGNAL_FLIP_TIME 10 //每隔100ms翻转一次读卡信号#define REPEAT_TIME 5 //500ms后重复读卡#define CLEAR_CARD_TIME 20 //2S后清除卡号数据#define MANCHEST_TIME 5sbit PULSE = P3^2;sbit RFEN = P3^5; //曼彻斯特解码脉冲信号sbit MANCHEST0= P3^2; //wiegand0sbit MANCHEST1= P3^3; //wiegand1uchar code CheckingTab[32]={ //接收到10组卡号的偶校验0X00,0X01,0X01,0X00,0X01,0X00,0X00,0X01, //这里数值是低五位的偶校验值0X01,0X00,0X00,0X01,0X00,0X01,0X01,0X00,0X01,0X00,0X00,0X01,0X00,0X01,0X01,0X00,0X00,0X01,0X01,0X00,0X01,0X00,0X00,0X01};uchar WGCardBuf[5]; //卡号uchar CopyCardBuf[5]; //备份卡号uchar ManchestBuf[11]; //暂存接收到的11组数据uchar idata g_ucManchestTime = MANCHEST_TIME; //uchar idata g_ucDWithCardTime= 0; //隔500ms处理该卡号uchar idata g_ucPreambleFlag = 0;uchar idata g_ucERAgainTimer = 0; //每隔100ms翻转一次RFENuchar idata g_ucStoreGroupCnt= 0; //接收到几组数据,这里为11组才可能正确uchar idata g_ucEGroupBitCnt = 0; //每组数据有5个为,5=4位卡号+1位偶校验uchar idata g_ucPreambleCount= 0; //9位为1的引导码uchar idata g_ucRemvoeCardTime=0; //隔多久清除以前的卡号数据,这里为3s2、Manchest初始化/******************************************************************** 函数原型:ManchestInit功能:曼彻斯特解码变量初始化输入:无输出:无说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ void ManchestInit(void) //初始化读卡参数{RFEN = 1;g_ucPreambleFlag = 0;g_ucStoreGroupCnt = 0;g_ucEGroupBitCnt = 5;g_ucPreambleCount = 9;g_ucERAgainTimer = SIGNAL_FLIP_TIME;}3、Manchest解码信号翻转/******************************************************************** 函数原型:ProcessManchestSignal功能:manchest解码的翻转信号输入:无输出:无说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ void ProcessManchestSignal(void){if((g_ucDWithCardTime!=0)&&(--g_ucDWithCardTime==0)){}if((g_ucRemvoeCardTime!=0)&&(--g_ucRemvoeCardTime==0)){CopyCardBuf[0] = 0; //清除卡号缓冲区CopyCardBuf[1] = 0;CopyCardBuf[2] = 0;CopyCardBuf[3] = 0;CopyCardBuf[4] = 0;}RFEN = ~RFEN;g_ucPreambleFlag = 0;g_ucPreambleCount= 9;if(RFEN){EX0 = 1;EX1 = 1;}else{EX0 = 0;EX1 = 0;}}4、过滤错误的卡号/******************************************************************** 函数原型:CalibrationCardData功能:一张卡号,如果出现全部相同的数字或者该卡号只有两种数据,则认为是错误的卡号。

输入:uchar *pCard,uchar ucCount输出:0或1说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ uchar CalibrationCardData(uchar *pCard,uchar ucCount){uchar ucCnt = 0;uchar ucVal = 0;uchar ucVerify = 0;uchar ucVerifyCnt= 0;ucVerify = 0;ucVal = pCard[0];for(ucCnt=1;ucCnt<ucCount;ucCnt++) //和第一个数相同的共有多少个{if(ucVal==pCard[ucCnt]){ucVerify++;}}if(ucVerify!=ucCount-1) //所有数据都相同?{ //不是ucVal = pCard[0];for(ucCnt=1;ucCnt<ucCount;ucCnt++){if(ucVal != pCard[ucCnt]) //找出和第一个数不同的数{break;}}ucVal=pCard[ucCnt];ucCnt++;ucVerifyCnt=0;while(ucCnt<ucCount){if(ucVal==pCard[ucCnt]){ucVerifyCnt++;} //和这个数相同的数有几个ucCnt++;}ucVerify = ucVerify + ucVerifyCnt; //两种数共有多少个if(ucVerify==(ucCount-2)) //这张卡只有两种数据{return 1; //则认为错误卡号}else{return 0; //不止两种数据}}else{return 1; //错误卡号}}5、获取正确的卡号/******************************************************************** 函数原型:DealWithCardData功能:处理卡号数据输入:无输出:0或1说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ uchar DealWithCardData(void){uchar ucCnt = 0;uchar ucValH = 0;uchar ucValL = 0;ucValH=CalibrationCardData(ManchestBuf,10);if(ucValH==0) //卡号正确{for(ucCnt=0;ucCnt<5;ucCnt++) //获取卡号{ucValH = ManchestBuf[2*ucCnt];ucValL = ManchestBuf[2*ucCnt+1];ucValH = (ucValH<<4) | ucValL;ManchestBuf[ucCnt] = ucValH;}return 0;}else //卡号错误{return 1;}}6、Manchest获取卡号数据/******************************************************************** 函数原型:ProcessManchest功能:停止位为0、行校验、列校验、输入:无输出:0或1说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*--------------------------------------------------------------------*2012-02-14 Oscar First********************************************************************/ void ProcessManchest(void){uchar ucCnt = 0;uchar ucVal = 0;uchar ucValue = 0;uchar ucVerify= 0;RFEN = 0;g_ucERAgainTimer = SIGNAL_FLIP_TIME;ucVal=ManchestBuf[10]&0X01; //获取停止位if(ucVal==0) //判断停止位是否为0{ //曼彻斯特编码的停止位为0 ucVerify=ManchestBuf[10]>>1; //获取列偶校验值for(ucCnt=0;ucCnt<10;ucCnt++) //获取行、列偶校验值{ucValue=ManchestBuf[ucCnt]&0X1F;if(CheckingTab[ucValue]!=0) //行校验是否正确{ucVerify = 1; //不正确break; //结束}ucVal = ManchestBuf[ucCnt]; //行校验通过ucVal = ucVal>>1; //移除行校验位ucVal = ucVal & 0X0F; //计算卡号ManchestBuf[ucCnt]=ucVal; //暂存卡号ucVerify=ucVal ^ ucVerify; //列校验}ucVerify = ucVerify&0X0F; //获取列校验值if(ucVerify==0) //列校验正确?{ucVal=DealWithCardData(); //正确,获取卡号if(ucVal==0){for(ucCnt=0;ucCnt<5;ucCnt++) //和上次卡号数据对比是否相等{if(CopyCardBuf[ucCnt]!=ManchestBuf[ucCnt]){break;}}if(ucCnt==5) //连续两次接收到是同一张卡号{if(g_ucDWithCardTime==0) //{for(ucCnt=0;ucCnt<5;ucCnt++)//暂存卡号{CopyCardBuf[ucCnt] = ManchestBuf[ucCnt];WGCardBuf[ucCnt] = ManchestBuf[ucCnt];}g_ucTask |= 0X04;EX0 = 1; //开外部中断EX1 = 1;g_ucDWithCardTime = REPEAT_TIME;}else{EX0 = 1; //开外部中断EX1 = 1;g_ucDWithCardTime = REPEAT_TIME;g_ucRemvoeCardTime= CLEAR_CARD_TIME;} //2S后清除卡号缓冲区}else{for(ucCnt=0;ucCnt<5;ucCnt++) //赋卡号,与下一次接收卡号匹配{CopyCardBuf[ucCnt] = ManchestBuf[ucCnt];}RFEN= 1;EX0 = 1;EX1 = 1;g_ucDWithCardTime = 0;g_ucRemvoeCardTime= CLEAR_CARD_TIME;} //2S后清除卡号缓冲区}else{RFEN= 1; //读取线圈数据EX0 = 1; //开中断EX1 = 1;}}else{EX0 = 1;EX1 = 1;}}else{EX0 = 1;EX1 = 1;}}7、通过中断采样获取刷卡数据/******************************************************************** ********************************************************************* *************************以下为曼彻斯特解码程序********************** *************通过外部中断0、1和定时器TI匹配解码卡号****************** ********************************************************************* ********************************************************************/ /******************************************************************** 函数原型:Int0Routine功能:触发Timer1采样输入:无输出:无说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ void Int0Routine(void) interrupt 0{if(MANCHEST0!=1){TH1 = TH1_370US_H;TL1 = TL1_370US_L;TR1 = 1;ET1 = 1;TF1 = 0;EX0 = 0;EX1 = 0;}}/******************************************************************** 函数原型:Int1Routine功能:触发Timer1采样输入:无输出:无说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ void Int1Routine(void) interrupt 2{if(MANCHEST1!=1){TH1 = TH1_370US_H;TL1 = TL1_370US_L;TR1 = 1;ET1 = 1;TF1 = 0;EX0 = 0;EX1 = 0;}}/******************************************************************** 函数原型:Timer1Routine功能:触发Timer1采样输入:无输出:无说明:无*-------------------------------------------------------------------- *修改时间| 修改者| 备注*-------------------------------------------------------------------- *2012-02-14 Oscar First********************************************************************/ void Timer1Routine(void) interrupt 3{uchar ucVal =0; //暂存获取数据TR1=0;if(g_ucPreambleFlag) //9个1到了?{if(PULSE){g_ucPreambleCount--;if(g_ucPreambleCount==0) //在PULSE==1的情况下如果g_ucPreamble_Count{ //还能减到0说明有连续的1出现IE0 = 0;IE1 = 0;EX1 = 1;EX0 = 1;g_ucPreambleFlag = 1;g_ucStoreGroupCnt= 0;g_ucEGroupBitCnt = 5;g_ucPreambleCount= 9;return;}}else{ //只要有低电平出现就重新付值,g_ucPreambleCount = 0X09; //看有否连续的高电平出现}ucVal = ManchestBuf[g_ucStoreGroupCnt];ucVal = ucVal<<1;if(PULSE) //为高{ucVal |= 1; //置位}else{ucVal &=0XFE;}ManchestBuf[g_ucStoreGroupCnt] = ucVal;if(g_ucEGroupBitCnt>5){IE0 = 0;IE1 = 0;EX1 = 1;EX0 = 1;g_ucPreambleFlag = 0;g_ucStoreGroupCnt= 0;g_ucEGroupBitCnt = 5;ManchestBuf[0] = 0;return;}g_ucEGroupBitCnt--;if(g_ucEGroupBitCnt==0){g_ucStoreGroupCnt++;if(g_ucStoreGroupCnt<11){IE0 = 0;IE1 = 0;EX1 = 1;EX0 = 1;g_ucEGroupBitCnt = 5;return;}if(g_ucStoreGroupCnt==11) //11组数据接收完成{EX0 = 0; //关中断EX1 = 0;TR1 = 0;g_ucTask |= 0X02; //置处理卡号标志return;}if(g_ucStoreGroupCnt>11){IE0 = 0;IE1 = 0;EX1 = 1;EX0 = 1;g_ucPreambleFlag = 0;g_ucEGroupBitCnt = 5;g_ucStoreGroupCnt= 0;ManchestBuf[0] = 0;return;}}else{IE0 = 0;IE1 = 0;EX1 = 1;EX0 = 1;} //11组字节收齐了?}else{if(PULSE){g_ucPreambleCount--;if(g_ucPreambleCount==0) //够不够9个1?{g_ucPreambleFlag = 1;g_ucStoreGroupCnt= 0;g_ucEGroupBitCnt = 5;g_ucPreambleCount= 9;}}else{g_ucPreambleCount = 9;}IE0 = 0;IE1 = 0;EX1 = 1;EX0 = 1;}}。

相关文档
最新文档