⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 test idata printf.c

📁 小车单片机数据采集程序包括红外线、超声波、罗盘以及跟上位机ARM7的串口通讯。
💻 C
字号:
#include <reg52.h>
#include <stdio.h>
#include <intrins.h>
#define uchar unsigned char
uchar a;        
uchar  bdata select;//选通道值
sbit flag0=select^0;
sbit flag1=select^1;
sbit flag2=select^2;

unsigned int count1,count2,tmp4,tmp5;   //count1,count2为超声波用

float count;
sbit P0_0=P0^0;
sbit P0_1=P0^1;
sbit P0_2=P0^2;
sbit P0_3=P0^3;


sbit re_de1=P0^4;
sbit re_de2=P0^5;
sbit re_de3=P0^6;
uchar code meter_address_return[2]={0xac,0xca};    //设置RS485接口接收端所使用变量的定义与说明.      
float idata array1[8]={5.142,6,7,7,8,8,8,8}; //超声波数组
float idata array2[5]={6.587,256,6.78,4,5};         //红外数组.
float idata array3[2]={5.148,78.09};                //码盘.
float idata array4=57.1987;                         //罗盘.
uchar idata transfer[8]={0};                        //sprintf函数使用的数组。 
uchar idata meter_address[2]={0xac,0xca};    //设置RS485接口接收端所使用变量的定义与说明.
uchar idata rs485_status=0x00;               //RS485接口在数据接收过程中所处的状态.
uchar idata rs485_data;           //RS485接口所接收的数据.
uchar idata m_meteraddrc=0x00;    //数据帧地址段计数器.
uchar idata m_meterdatlen;   //数据帧数据段的长度.
uchar idata m_meterdatbuf[8];//数据帧数据段.
uchar idata m_meterdatac;    //数据帧数据段计数器.
uchar idata m_metercheck=0x00;    //数据帧累加和检验码.
uchar idata m_metersyscheck=0x00; //中断接收程序计算所得到的累加和校验码.
uchar idata m_sendaddrcode;   //发送方地址
uchar idata m_receiveaddrcode;//接收方地址.


uchar d,e;
uchar bdata c;     //定义C可位寻址的字节
uchar z[5];   //定义一个数组用于接收5路红外线的信息
sbit z0=c^0; //z0为第0路红外.
sbit z1=c^1; //z1为第1路红外.
sbit z2=c^2; //z2为第2路红外.
sbit z3=c^3; //z3为第3路红外.
sbit z4=c^4; //z4为第4路红外.
sbit e1=P1^5;  
sbit e2=P1^6;
sbit e3=P1^7;


uchar dis1,dis2;    //分别记录tmp1,tmp2有值 
int count3,count4;   //count3,count4码盘计数用.
#define r 0.022
uchar  tmp1,tmp2;
sbit P0_7=P0^7;






/*超声波测距,中断处理*/
void interrupt0() interrupt 0                 //外部中断int0
{
	TR0=0;                                   //停止定时器,测距
	tmp4=TL0;tmp5=TH0;                       //读入TL0和TH0数据
 	count1=tmp4+tmp5*256;                    //读TH0,TL0中的值,
	count=(count1-51712)*12/(11.0592*1000000)*337.57/2;//在常温为10摄氏度为337.57m/s.
    a=1;
    if(count<0.265)
    { count=-1;
	}
	 
                 
}

void timer0_int() interrupt 1               //定时器T0溢出中断
{
	TR0=0;       
	count=0;                              //返回0表明无障碍物
	a=1;

}


void interrupt1() interrupt 2           //  外部INT1中断.
{ 
     e=P1;
	 e=e^0xff;
	 c=e;        //把值赋给c
	 IE1=0;      //清外部1.
	 EX1=0;     //关闭外部中断1.
	 z[0]=z0;   //以下把红外线信息放入到z数组中去.
	 z[1]=z1;
	 z[2]=z2;
	 z[3]=z3;
	 z[4]=z4;
 
}

//计算车轮走过的路程。 
float road(int a,uchar b)     //计算车轮走过的路程。
{    
     float sum=0;    //路程。
     sum=a*2*2*3.14*r+2*b*2*3.14*r/8;
	 return(sum);
}


//数据通信用.
void delayms(int ms)//采用11.0592MHZ晶振,理论上5ms,实际检测为5.2ms
// 延时程序。
{						
	unsigned char i;
	while(ms--)
	{
		for(i = 0; i < 120; i++);
	}
   
}

void send_frame()           //发送一个数据帧
{
     
     uchar data i;
     re_de1=0;     //设置RS485进入发送状态.设置MAX485(3)接收
     re_de2=0;     //设置MAX485(2)接收
     re_de3=1;     //设置MAX485(1)发送.
       
     m_metercheck=0x00;   //和校验清零.
     SBUF=0xac;           //发送帧起始符.
     while(!TI);
	 TI=0;
	 m_metercheck+=0xac;  //更新累加和的校验信息
     SBUF=0xca;           
     while(!TI);
	 TI=0;
	 m_metercheck+=0xca;  //更新累加和的校验信息
     SBUF=m_sendaddrcode;      //发送发送方地址信息.
     while(!TI);
	 TI=0;  
	 m_metercheck+=m_sendaddrcode;     //更新累加和的校验信息
     SBUF=m_receiveaddrcode;           //发送接收方的地址信息.
     while(!TI);
	 TI=0;
	 m_metercheck+=m_receiveaddrcode;  //更新累加和的校验信息
     for(i=0;i<8;i++)
     {
        SBUF=transfer[i];
        while(!TI);
	    TI=0;
	    m_metercheck+=transfer[i];  //更新累加和的校验信息
     }
     SBUF=m_metercheck;                 //发送累加和校验码.
     while(!TI);
	 TI=0;
	 SBUF=0x55;                         //发送结束符号
	 while(!TI);
	 TI=0;
	 re_de1=1;                          //设置MAX485进入接收状态,设置MAX485(3)发送.
     re_de2=0; 
     re_de3=0;                          //设置MAX485(1)接收.
}


void send_frameagain()     //请求重发函数.
{
      m_sendaddrcode=0x20;
      m_receiveaddrcode=0x10;
      transfer[0]=0xff;
	  transfer[1]=0xff;
	  transfer[2]=0xff;
	  transfer[3]=0xff;
	  transfer[4]=0xff;
	  transfer[5]=0xff;
	  transfer[6]=0xff;
	  transfer[7]=0xff;
	  send_frame();
}

void send_ultrasonic()             //发送超声波信息函数。
{
     uchar i;
	 m_sendaddrcode=0x30;
     m_receiveaddrcode=0x10;
     for(i=0;i<8;i++)
     {
        sprintf(transfer,"%8.4f",array1[i]);  //将一路超声波信息转换为8个ASCII。
        m_sendaddrcode=0x30+i;
        send_frame();
    }
}
void send_infrared()                         //发送红外线信息函数。
{   
     uchar i;
	 m_sendaddrcode=0x20;
     m_receiveaddrcode=0x10;
     for(i=0;i<5;i++)
     {
        sprintf(transfer,"%8.4f",array2[i]);  //将一路超声波信息转换为8个ASCII。
       
        send_frame();
    }
}
void send_mapan()                             //发送码盘信息函数。
{
     uchar i;
	 m_sendaddrcode=0x40;
     m_receiveaddrcode=0x10;
     for(i=0;i<2;i++)
     {
        sprintf(transfer,"%8.4f",array3[i]);  //将一路码盘信息转换为8个ASCII。
        m_sendaddrcode=0x40+i;
        send_frame();
    }
}
void send_compass()
{    
      m_sendaddrcode=0x50;
      m_receiveaddrcode=0x10;
      sprintf(transfer,"%8.4f",array4);    //将罗盘信息转换为8个ASCII。
      send_frame();                                                   
}             
              



void com_isp()interrupt 4 using 1  //接收RS485的接口从ARM上传来的数据.
{
     if(RI)
     {
       RI=0;      //清除接收中断.
       rs485_data=SBUF;  //暂存接收到的数据.
       if(rs485_status==0x00) //如果RS485接收中断程序处于状态0
       {
          if(rs485_data==meter_address_return[m_meteraddrc])
          {
            m_meteraddrc++;            //如果对应位置的地址数据一致,则更新数据段地址计数器
          }
          else
          {
              m_meteraddrc=0x00;      //准备重新接收数据帧地址信息
          }
          if(m_meteraddrc==2)         //判断地址表中的2个字节是否结束
          {
             m_meteraddrc=0x00;
             rs485_status=0x01;       //更新RS485接收中断程序的状态
          }
       }
       else if(rs485_status==0x01)   //如果接收中断程序状态处于1,则接收发送方的地址
       {
               
              m_sendaddrcode=rs485_data; //保存发送方的地址
              rs485_status=0x02;         //更新RS485接收中断程序的状态  
       } 
       else if(rs485_status==0x02)      //如果接收中断程序状态处于2,则接收接收方的地址.
       {
              m_receiveaddrcode=rs485_data;//保存接收方的地址.
              m_meterdatac=0x00;        //复位数据段计数器.
              rs485_status=0x03;        //更新RS485接收中断程序的状态  
       }
       
       else if(rs485_status==0x03)       //如果接收中断程序处于3,则接收数据信息.
       {
              m_meterdatbuf[m_meterdatac]=rs485_data;  //保存接收的数据信息
              m_meterdatac++;                          //更新数据计数器
              if(m_meterdatac==8)          //判断数据段是否接收完?
              { 
                m_metersyscheck= 0xac+0xca+m_sendaddrcode+m_receiveaddrcode; //初始化和校验变量
                rs485_status=0x04;     //更新RS485接收中断程序的状态 
              }
       }
       
       else if(rs485_status==0x04)    //如果接收中断程序处于4,则接收累加和校验信息
       {
              m_metercheck=rs485_data; //保存接收到的累加和校验信息.
              for(m_meterdatac=0;m_meterdatac<8;m_meterdatac++)//累加数据段.
              {
                   m_metersyscheck+=m_meterdatbuf[m_meterdatac];
              }
              
              
             
              rs485_status=0x05;         //更新RS485接收中断程序的状态  
              
       }
       else if(rs485_status==0x05)           //如果RS485接收中断程序处于状态5,则接收结束符.
       {
            
                re_de1=0;     //设置RS485进入发送状态.设置MAX485(3)接收
                re_de2=0;     //设置MAX485(2)接收
                re_de3=1;     //设置MAX485(1)发送.
       
                m_meteraddrc=0x00;           //重新接收数据帧中的地址信息
                rs485_status=0x00;         //复位RS485接收中断程序状态标志.
                if(m_metersyscheck==m_metercheck )   //如果正确接收到数据,发出dd.
	            {  
                  
	               switch(m_meterdatbuf[0])
                   {
                         case 0x30:send_ultrasonic();break;    //如果是30H,发送超声信息。
                         
                         case 0x40:send_mapan();   break;      //如果是50H,发送码盘信息。
                         case 0x50:send_compass(); break;      //如果是60H,发送罗盘信息。
						 default : send_frameagain();          //请求重发。
                   }
				}
				else
				{
				    send_frameagain();
				}
                m_metersyscheck=0x00;
				m_metercheck=0x00;
       }        
    } 
 
     
} 

   

     
/*主程序*/
void main(void)
{  
	 TMOD=0x11;                      //16位定时器T0,16位定时器T1工作方式皆方式1.
     
    
	 TCON=0x01;     //设置TCON,INT1为低电平有效,INT0为下降沿有效.IT0=1
     d=0;
     EA=1;

     P0_7=1;             //CD4520先清零
     P0_7=0;             //让CD4520工作.
     tmp1=0;             //赋初值.
	 tmp2=0;             //赋初值.
     count1=0;           //左车轮计数是否溢出先清零。
     count2=0;           //右车轮计数是否溢出先清零。
       
     T2CON=0x30;
     RCAP2H=0xff;            //用T2做波特率发生器.9600 置初值.
     RCAP2L=0xdc; 
     PCON&=0x0f;             //波特率不加倍.
     SCON=0x70;              //设置串行口工作方式为方式1
     ES=1;                   //串行中断允许
     TR2=1;                  //定时器T1启动
     re_de1=1;                          //设置MAX485进入接收状态,设置MAX485(3)发送.
     re_de2=0; 
     re_de3=0;                          //设置MAX485(1)接收.
	          
	 while(1)
	     {
            int i;
            for(i=0;i<=7;i++)
              { 
			    select=i;
	            IE = 0x82;
		        P0_0=flag0;P0_1=flag1;P0_2=flag2;P0_3=1;   //选中第i路.分别为0.1.2.3.4.5.6.7路.
		        TH0=0xca;
		        TL0=0x00;                      
                TH1=0xFe;TL1=0x33;            //发送20个脉冲=0.5ms,用T1计时0.5ms.
		        TF1=0;                         //打开定时器T0,15ms
                TF0=0;              
		        TR1=1;TR0=1;                  //同时启动T0,T1
                do{}while(TF1==0);                    //等0.5ms时间结束.
		        P0_3=0;                        //关闭555
		        TR1=0;TH1=0xfc;TL1=0x66;       //延时1ms,盲区26cm
		        TF1=0;             
		        TR1=1;
		        do{}while(TF1==0);              //等待结束.
		        a=0;                             
                IE0=0;                           //开中断前,清中断    
                EX0=1;                         //允许外部中断int0
		        do{}while(a==0);
		        array1[i]=count;
		
           	}
            e1=1;       //对P1口的高三位置位
            e2=1;
            e3=1;
		    IE1=0;    //开中断前先清外部中断1, 
		    EX1=1;        //设置外部中断1允许.
	        delayms(1);
            
			array2[0]=z0;  //把第0路红外线信号赋入array2[0].
			array2[1]=z1;  //把第1路红外线信号赋入array2[1]
            array2[2]=z2;  //把第2路红外线信号赋入array2[2]
			array2[3]=z3;  //把第3路红外线信号赋入array2[3]
			array2[4]=z4;  //把第4路红外线信号赋入array2[4]

			for(i=0;i<8;i++)    //对超声波和红外线进行综合处理.
			{
			   if(i<3)
			   {
			      if(z[i]==1)
				  {
				     array1[i]=-1;               //说明在盲区内有障碍物的存在.
                  }
               }
			   else if(i==3)
			   {
			      if(z[2]==1)                   //说明在盲区内有障碍物的存在.
				  {
				    array1[3]=-1;   
                  }
			   }
			   else if(3<i<=5)                 //说明在盲区内有障碍物的存在.
			   {
			       if(z[3]==1)
                   {
                     array1[i]=-1; 
                   }
               }
               else if(5<i<=7)              //说明在盲区内有障碍物的存在.
               {
                     if(z[4]==1)
                     {
                        array1[6]==-1;
                        array1[7]=-1;
                     }
               }
                        
             }



			 
            dis1=tmp1;             //记录tmp1的上一次的值.
            dis2=tmp2;             //记录tmp2的上一次的值.
            tmp1=P2;
	        tmp1=tmp1&0x0f;     //左车轮取P2低4位,
	        tmp2=P2;
	        tmp2>>=4;            //取得的P2口数据右移4位,以便下一步取值。
	        tmp2=tmp2&0x0f;     //右车轮取P2高4位。
            if(tmp1<dis1)
			{ 		       
			   ++count3;			   
			}
			if(tmp2<dis2)
			{  
			   ++count4;
			}		
			array3[0]=road(count3,tmp1);
        	array3[1]=road(count4,tmp2);
            for(i=0;i<8;i++)
            {
               printf("%dm   ",array1[i]);
               
            }
            printf("\n");
            for(i=0;i<5;i++)
            {
               printf("%d   ",z[i]);
            }
            printf("\n");
            for(i=0;i<2;i++)
            {
               printf("%dm    ",array3[i]);
            }
            printf("\n");
              
               
            
      }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -