《匠人手记》推荐网上购书渠道:
互动出版网(china-pub)购书入口   >>>
当当网(dangdang)购书入口   >>>
卓越亚马逊网 购书入口   >>>
淘宝网(taobao)购书入口   >>>
更多购书渠道……   >>> 

设为首页加入收藏联系匠人管理入口21IC首页21IC博客21IC社区侃单片机回复的贴参与的贴

天气预报
百宝日历
载入中...

百宝专栏

载入中...
最新货色

载入中...

粉丝评论

载入中...

载入中...



百宝信息

载入中...

百宝流量

(2006-07-01开始)


匠人手记

 匠人观点: 好记性不如烂笔头  
 黑色幽默:三鹿门——后世畅想

格雷码简介及格雷码与二进制的转换程序(C)
程序匠人 发表于 2005-6-2 20:35:00  阅读全文 | 回复(0) | 引用通告 | 编辑

格雷码简介
(摘自《格雷码的“权”、奇偶性及格雷码计数器的预置》)
  格雷码(英文:Gray Code, Grey Code,又称作葛莱码,二进制循环码)是1880年由法国工程师Jean-Maurice-Emlle
Baudot发明的一种编码[1] ,因Frank Gray于1953年申请专利“Pulse Code
Communication”得名。当初是为了机械应用,后来在电报上取得了巨大发展[2],现在则常用于模拟-数字转换[3]和转角-数字转换中[4] 。
  典型格雷码是一种具有反射特性和循环特性的单步自补码,它的循环、单步特性消除了随机取数时出现重大误差的可能,它的反射、自补特性使得求反非常方便[5] 。
  格雷码属于可靠性编码,是一种错误最小化的编码,因为它大大地减少了由一个状态到下一个状态时电路中的混淆。由于这种编码相邻的两个码组之间只有一位不同,因而在用于模-数转换中,当模拟量发生微小变化而可能引起数字量发生变化时,格雷码仅改变一位,这样与其它码同时改变两位或多位的情况相比更为可靠,即可减少出错的可能性.这就允许代码电路能以较少的错误在较高的速度下工作。
  格雷码在现代科学上获得了广泛的应用,人们还发现智力玩具九连环的状态变化符合格雷码的编码规律,汉诺塔的解法也与格雷码有关。
  除了已知的特点,格雷码还有一些鲜为人知的性质。多数数字电子技术和计算机技术的文献认为格雷码是无权码,只有J.F.A.
Thompson认为可以从格雷码直接转换成十进制数[6]。如果将格雷码的“权”及格雷码的奇偶性等性质在数学上给予证明,将有助于格雷码研究与应用的发展,有助于自动化技术的发展,还可有助于计算机科学的发展。

/*   格雷码与二进制的转换程序
 * 本程序采用递推的方法进行推导,可以转换0~2147483647之间的数(1~31位)
 * 推导方式如下(以三位格雷码为例):
 * 序号 格雷码 格雷码实值 二进制码 二进制实值
 *  0  000   0   000   0
 *  1  001   1   001   1
 *  2  011   3   010   2
 *  3  010   2   011   3
 *  4  110   6   100   4
 *  5  111   7   101   5
 *  6  101   5   110   6
 *  7  100   4   111   7
 *     由上面的数据可看出.如果,按照序号01327645的方式遍历格雷码.其编
 * 码实值是按自然数顺序排列.反之,如果按此顺序遍历其二进制实值.则会发
 * 现遍历过的数据的个数减一即为二进制码所对应格雷码的实值.再观察序号
 * 顺序,我们会发现: 如果把二进制码分半,前半部分从前向后遍历,后半部分
 * 从后向前遍历.如果分半部分可再分,则再将其分半.并按照前半部分从前向
 * 后遍历(分解),后半部分从后向前遍历的方式遍历(分解).直到不可分.即可
 * 实现按序号所描述顺序遍历二进制码.如果,按此顺序遍历二进制码,我们可
 * 以很方便地在序列中找到所要的二进制码与其对应的格雷码.本思想可以很
 * 方便地用递归实现.这样就实现了二进制到格雷码的转换.同样,格雷码到二
 * 进制的转换,也可以用相同的方法推出.为了加快运算,我们跳过不必要的遍
 * 历将递归改为递推.这样就实现了格雷码与二进制之间的快速转换.
 * 此算法的时间复杂度约为O(n),n为要转换数据的BIT数.
 * *****************************************************************
 *  补充说明:
 *  其它的转换方法还有
 *    1、查表法(建立一个二进制与格雷码的对应表)
 *    2、公式法(根据卡诺图建立一个二进制到格雷码的每一位的公式)
 */
 
//#define test
#i nclude <stdio.h>
#ifdef test
 #i nclude <time.h>
#endif
/**
 * 二进制转换成格雷码
 * @param lStart lValue所在区间下界
 * @param lEnd lValue所在区间上界
 * @param lValue 要转换的二进制数的实值
 * @return 返回格雷码对应的二进制数的实值
 * @see g2b() g2b 格雷码转换二进制
 * @see BtoG() BtoG 二进制转换格雷码
 * @see GtoB() BtoG 格雷码转换二进制
 * @author 黄毅
 * @useage a=b2g(0,15,4); //取得4所对应格雷码的二进制值 结果a等于6
 * @memo lValue的值必须在区间[lStart,lEnd]里,否则无法求得所求结果.相应地,如果区间越小,求得结
 *       果所用的时间就越少.而且lStart,lEnd的值必须为2的N次方减1. 通常lStart为0.为了方便求得
 *       其值,建议使用BtoG()函数来进行操作.不过这样会使计算时间加长到原来的120%~180%.
 */
unsigned long b2g(unsigned long lStart,unsigned long lEnd,unsigned
long lValue)
{
 unsigned long Start=lStart,End=lEnd,Temp=0,Counter=0;
 bool Type=true;
 while(Start<End)
  {
   Temp=(End+Start-1)>>1;
   if (lValue<=Temp)
   {
    if(!Type)
     Counter+=((End-Start+1)>>1);
    End=Temp;
    Type=true;
   }
   else
   {
    if(Type)
     Counter+=((End-Start+1)>>1);
    Start=++Temp;
    Type=false;
   }
  }
 return Counter;
}
/**
 * 格雷码转换成二进制
 * @param lStart lValue对应二进制数所在区间下界
 * @param lEnd lValue对应二进制数所在区间上界
 * @param lValue 要转换的格雷码的实值
 * @return 返回二进制数对应的格雷码的实值
 * @see b2g() b2g 二进制转换格雷码
 * @see BtoG() BtoG 二进制转换格雷码
 * @see GtoB() BtoG 格雷码转换二进制
 * @author 黄毅
 * @useage a=b2g(0,15,6); //取得6所对应二进制值的格雷码 结果a等于4
 * @memo lValue对应二进制数的值必须在区间[lStart,lEnd]里,否则无法求得所求结果.相应地,如果区
 *       间越小,求得结果所用的时间就越少.而且lStart,lEnd的值必须为2的N次方减1. 通常lStart为0.
 *       为了方便求得其值,建议使用GtoB()函数来进行操作.但会使计算时间加长到原来的105%~140%.
 */
unsigned long g2b(unsigned long lStart,unsigned long lEnd,unsigned
long lValue)
{
 unsigned long Start=lStart,End=lEnd,Counter=0,Temp=0;
 bool Type=true;
 while(Start<End)
  {
   Temp=Counter+((End-Start+1)>>1);
   if(Type^(lValue<Temp))
   {
    if(Type) Counter=Temp;
    Start=(Start+End+1)>>1;
    Type=false;
   }
   else
   {
    if(!Type) Counter=Temp;
    End=(Start+End-1)>>1;
    Type=true;
   }
  }
 return Start;
}
//b2g外壳程序,用来算lStart,lEnd;
long BtoG(unsigned long lValue)
{
 register unsigned long lV=lValue,lMax=1;
 while (lV>0)
 {
  lV>>=1;
  lMax<<=1;
 }
 if (lMax==0) return -1;
 return b2g(0,--lMax,lValue);
}
//g2b外壳程序
long GtoB(unsigned long lValue)
{
 register unsigned long lV=lValue,lMax=1;
 while (lV>0)
 {
  lV>>=1;
  lMax<<=1;
 }
 if (lMax==0) return -1;
 return g2b(0,--lMax,lValue);
}

main()
{
 long input=0;
#ifdef test
//程序测试部分
 clock_t cStart,cEnd;
 unsigned long dTime;
 cStart=clock();
 for (input=0;input<9999999;input++)
  BtoG(32768);
 cEnd=clock();
 dTime=(cEnd-cStart);
 printf("BtoG: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
//------------------------------------------------------
 cStart=clock();
 for (input=0;input<9999999;input++)
  b2g(0,65535,32768);
 cEnd=clock();
 
 dTime=(cEnd-cStart);
 printf("b2g: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
//------------------------------------------------------
 cStart=clock();
 for (input=0;input<9999999;input++)
  GtoB(32768);
 cEnd=clock();
 dTime=(cEnd-cStart);
 printf("GtoB: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
//------------------------------------------------------
 cStart=clock();
 for (input=0;input<9999999;input++)
  g2b(0,65535,32768);
 cEnd=clock();
 dTime=(cEnd-cStart);
 printf("g2b: %ld / %ld\n",dTime,CLOCKS_PER_SEC);
#else
//程序演试部分
 printf("Input(HEX):");
 scanf("%x",&input);
 while (input!=-1)
 {
  printf("------BtoG------\nBinary:%08Xh\nGray 
:%08Xh\n------GtoB------\nGray 
:%08Xh\nBinary:%08Xh\n----------------\n",input,BtoG(input),input,GtoB(input));
  printf("Input(HEX):");
  scanf("%x",&input);
 }
#endif

看《匠人手记》,与匠人同行!北航出版,正在热卖!

发表评论:
载入中...

芯片专题

器件专题

软件专题

硬件专题

综合专题

项目专题

原创专题

器件检测
LCD LED
按键 触摸键
E2PROM
电池 电机
电阻 电容 电感

指令系统
软件算法
编程规范
滤波算法
串行通讯

PCB设计
I2C PWM
红外遥控
充电技术
中断 ADC 

匠人手记
匠人夜话
网络心路
一周热点串烧
从零开始玩PIC
DIY旋转时钟

广告5号位 [投放]


学习板、开发板、编程器、下载器、仿真器(查看详情……)

广告3号位 [投放]

站内搜索


站外搜索


百度  google
mp3  歌词 
图片  FLASH 
知道  文档
新闻  词典 
地图  mp3 
软件  天网 
雅虎  爱问 
搜狗  讯雷 
网讯  华军 
天空 

21IC器件搜索
百宝箱分站
  • 《匠人的百宝箱》21IC站
  • 《匠人的百宝箱》21IC笔记团队
  • 《匠人手记》21IC书友会
  • 《匠人的百宝箱》MCUBLOG站
  • 《匠人的百宝箱》MCUBLOG笔记团队
  • 《匠人的百宝箱》EDN站
  • 《匠人手记》EDN书友会
  • 《匠人的百宝箱》与非网站
  • 《匠人的百宝箱》新浪站
  • 《匠人的百宝箱》百度站
  • 《匠人的百宝箱》网易126站
  • 《匠人的百宝箱》网易163站
  • 《匠人的百宝箱》互动出版网站
  • 广告4号位 [投放]

     
     

    匠人原创

    往日酷贴

     
     
     

    大千八卦

    友情连接

    新浪新闻:
    新浪财经:
    AK58新闻:
    新浪股票:
    新浪股票:
    证券之星:

     [更多酷站连接]

     

     

    [欢迎交换连接]

    [百宝箱之与非门分舵]

    [电脑圈圈的家当]

    [IC921的博客]

    [柔月阁]

    [八楼的呼吸]

    [hotpower 的水潭]

    [xwj的文君阁]

    [所长的BLOG]

    [阿摆手记]

    [电子伙伴]

    [unaided的笔记]

    [小飞的笔记]

    [单片机开发联盟]

    [网址之家]

    [好东西网址大全]

    [美萍中文精选]

    [数字电视之家]

    [SMARTCODE电子书斋]

    [软件开发之窗]

    [Armoric]

    [我爱研发网]

    [infernal的笔记]

    [雄鹰的空中加油站]

    [SunK]

    [逍遥电子]

    [ningpanda的博客]

    [C-Design]

    [一网见天下]

    [海边淘沙]

    [嵌入式365]

    [水牛的仓库]

    [股剩是怎样炼成的]

    [PIC论坛]

    [ICC AVR开发网]

    [中国高校自动化网]

     

     

     

    MCU博客-中国电子工程师博客网 

    大学生电子网 

     

     

     

     

     

    !!! 《匠人的百宝箱》 !!!