📄 test idata printf.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 + -