新闻  |   论坛  |   博客  |   在线研讨会
单片机浮点数的显示编程
tvb2058 | 2007-10-04 11:26:16    阅读:12035   发布文章

单片机浮点数的显示编程
 经常接到读者的来信来电,谈到学习单片机编程已有一定进步,可以进行定点数的显示。但这些读者对如何进行浮点数显示却一筹未展,毫无头绪。而工业自动化控制中会牵涉到大量的浮点数运算与显示,这里笔者根据一简单的实例来详细介绍一下浮点数的C语言显示设计。更多的C语言学习内容可上www.hlelectron.com查看。
 电路构成
 假设显示为5位数码管,其电路见图1(作者注:使用Protel99se打开)。其中最高位数码管作符号显示,其余的4位数码管进行浮点数显示。
 
 
 图1
 软件设计流程
 图2为主程序及定时器0中断程序的状态流程。主程序在上电时进行初始化,包括设置定时器初值及开中断等。无限循环过程中,不断调用取样子函数获取待显的浮点数,并将浮点数转为整数。浮点数转为整数的处理过程如下:
 首先判断取样获取的浮点数的正、负,若小于0,则符号位标志fu_hao清0,否则置1。下来,取浮点数的绝对值。再下来,判断浮点数的大小,若浮点数大于等于0而小于10,小数点标志point置0;若浮点数大于等于10而小于100,小数点标志point置1;若浮点数大于等于100而小于1000,小数点标志point置2;若浮点数大于等于1000而小于10000,小数点标志point置3。需说明的是:由于显示数值的数码管为4位,因此假设取样获得的浮点数范围从0.000~9999。
 T0定时中断程序,用于刷新浮点数的显示,它会根据小数点标志point的变化,自动点亮某位数码管的小数点。并且T0定时中断程序还会根据符号位标志fu_hao,熄灭最高位数码管或显示“-”。
 
 
 图2
 程序实例详解
 #include<REG51.H>   //51单片机头文件
 #include<math.H>   //调用绝对值计算库函数必需的头文件
 #define uchar unsigned char //变量类型的宏定义
 #define uint unsigned int
 uchar code DIS_SEG7[10]={0x3f,0x06,0x5b,0x4f,0x66,
                 0x6d,0x7d,0x07,0x7f,0x6f}; //0~9的数码管段码
 uchar code DIS_BIT[5]={0xfe,0xfd,0xfb,0xf7,0xef};//5位数码管位码
 //========================
 float x=-2000;    //定义取样获取的浮点数(作演示时初始化为-2000)
 uint disp_val;     //无符号整型变量作显示缓冲
 uchar point;     //无符号字符型变量作小数点标志point
 bit fu_hao;     //位变量作符号标志fu_hao
 float sampling(void);   //函数声明
 //************************
 void delay(uint k)    //定义延时子函数
 {
 uint data i,j;
 for(i=0;i<k;i++){
 for(j=0;j<60;j++)
 {;}}
 }
 //***************************
 void time0(void) interrupt 1  // T0定时中断服务程序
 { static uchar dis_cnt;
  TH0=-(2000/256);
  TL0=-(2000%256);
   if(++dis_cnt>4)dis_cnt=0; //扫描5位数码管的计数值
   switch(dis_cnt)
   {
   case 4: if(fu_hao==0)P0=0x40; //如果符号标志fu_hao为0,
 //则最高位(万)位数码管显示“-”。
     else P0=0x00;   //否则熄灭最高位(万)位数码管。
     P2=DIS_BIT[4];break;  //选中万位数码管。
   //**********************************
   case 3:if(point==0)P0=DIS_SEG7[disp_val/1000]|0x80; //如果小数点
 //标志point为0,则千位数码管显示且同时点亮小数点。
     else P0=DIS_SEG7[disp_val/1000]; //否则仅千位数码管显示。
     P2=DIS_BIT[3];break;  //选中千位数码管。
   //**********************************
   case 2:if(point==1) P0=DIS_SEG7[(disp_val%1000)/100]|0x80; //如果小数点标志point为1,则百位数码管显示且同时点亮小数点。
     else P0=DIS_SEG7[(disp_val%1000)/100];  //否则仅百位数码管            //显示。  
     P2=DIS_BIT[2];break;   //选中百位数码管。
   //**********************************
   case 1:if(point==2) P0=DIS_SEG7[(disp_val%100)/10]|0x80; //如果//小数点标志point为1,则十位数码管显示且同时点亮小数点。
     else P0=DIS_SEG7[(disp_val%100)/10]; //否则仅十位数码管显示。      P2=DIS_BIT[1];break;   //选中十位数码管。
   //**********************************
   case 0:if(point==3) P0=DIS_SEG7[(disp_val%10)]; //如果小数点标志point为1,则个位数码管显示且同时点亮小数点。
     else P0=DIS_SEG7[(disp_val%10)]; //否则仅个位数码管显示。
     P2=DIS_BIT[0];break;    //选中个位数码管。
   default:break;       //默认为退出
   }
 }
 //===========================
 void main(void)   // 定义主函数
 { float temp;   //定义浮点型局部变量
  delay(500);   //延时,待电源稳定
  TMOD=0x01;   //定时器T0方式1
  TH0=-(2000/256);  //2ms定时初值(晶振为12.000MHz)
  TL0=-(2000%256);
  ET0=1;TR0=1;  //开T0中断,启动T0
  EA=1;    //开CPU中断
  while(1)    //无限循环
  {
   temp=sampling(); //调用取样子函数获取待显的浮点数
   EA=0;    //进行浮点数处理前关闭中断
   //**************************
  if(temp<0)fu_hao=0; //若浮点数小于0,则符号位标志fu_hao清0
  else fu_hao=1;  //否则符号位标志fu_hao置1。
 
  temp=fabs(temp);  //取样获取的浮点数转成绝对值。
  
  if((temp>=0)&&(temp<10)) //若浮点数大于等于0而小于10 。
  {point=0;disp_val=(int)(temp*1000);}// 小数点标志point置0。
 
  if((temp>=10)&&(temp<100)) //若浮点数大于等于10而小于100。
  {point=1;disp_val=(int)(temp*100);} //小数点标志point置1。
 
  if((temp>=100)&&(temp<1000)) //若浮点数大于等于100而小于1000。
  {point=2;disp_val=(int)(temp*10);} //小数点标志point置2。
 
  if((temp>=1000)&&(temp<10000)) //若浮点数大于等于1000而小于10000。
  {point=3;disp_val=(int)temp;} //小数点标志point置3。
  //****************************
  EA=1; //浮点数处理完毕后打开中断
  delay(100); //延时,不是必须的
  }
 }
   //***********************************
  float sampling(void)  //定义浮点数取样子函数
  {
  if(x<-100)x=x+10;   //随便做浮点数的变化,以下同。
  else if((x>=-100)&&(x<-10))x=x+1;
  else if((x>=-10)&&(x<-1))x=x+0.01;
  else if((x>=-1)&&(x<0))x=x+0.001;
  //==============================
  else if((x>=0)&&(x<1))x=x+0.001;
  else if((x>=1)&&(x<10))x=x+0.01;
  else if((x>=10)&&(x<100))x=x+1;
  else x=x+10;
  if(x>2000)x=-2000;
  return x;     //返回取样值。
  }

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
dwwzl  2012-05-04 08:38:01 

很不错啊,受教了

推荐文章
最近访客