为什么我的超声波模块,测出的距离大了10倍
时间:10-02
整理:3721RD
点击:
为什么我的超声波模块,测出的距离大10倍了,实测过,刚好是大了10倍,程序哪里出问题了,贴来,各位帮忙分析一下
/********************************************************/
/*项目名称:单片机避障小车 */
/*单片机:STC89C52RC */
/*晶振频率:12MHz */
/********************************************************/
#include <reg51.h>
#include <intrins.h>
#include <LCD1602.h>
#define uchar unsigned char
#define uint unsigned int
#define ulong unsigned long
/************STC单片机特殊功能寄存器定义*****************/
sfr T2CON=0xC8; //定时器2控制寄存器
sbit TF2=T2CON^7;
sbit TR2=T2CON^2;
sbit ET2=IE^5; //定时器2中断控制位
sfr T2MOD=0xC9;
sfr RCAP2L=0xCA;
sfr RCAP2H=0xCB;
sfr TL2=0xCC;
sfr TH2=0xCD;
sfr IPH=0xB7; //中断优先级控制寄存器高 定时器2优先中断IPH=0x20 IP=0x20
/*************端口定义**********************************/
sbit Sevro_moto_pwm=P3^5; //接舵机信号端输入PWM信号调节速度
sbit Trig=P3^1; //超声波控制端
sbit Echo=P3^2; //超声波接收端
sbit IN1=P1^0; //左边电机驱动口
sbit IN2=P1^1; //左边电机驱动口
sbit IN3=P1^2; //右边电机驱动口
sbit IN4=P1^3; //右边电机驱动口
sbit INA=P1^4; //左边电机使能端
sbit INB=P1^5; //右边电机使能端
sbit IR1=P3^6; //左边红外距离检测
sbit IR2=P3^7; //右边红外距离检测
/********************************************************/
/*************寄存器定义*********************************/
#define Left_moto_go {IN1=1,IN2=0;} //左边电机向前走
#define Left_moto_back {IN1=0,IN2=1;} //左边电机向后走
#define Left_moto_Stop {IN1=0,IN2=0;} //左边电机停转
#define Right_moto_go {IN3=1,IN4=0;} //右边电机向前走
#define Right_moto_back {IN3=0,IN4=1;} //右边电机向后走
#define Right_moto_Stop {IN3=0,IN4=0;} //右边电机停转
//测距相关寄存器定义
bit Time_Up; //溢出标志
uint time; //时间
ulong S=0; //距离
ulong S1=0;
ulong S2=0;
ulong S3=0;
ulong S4=0;
bit busy_flag=0; //测距中标志
bit succeed_flag=0; //测量成功标志
bit Error_flag=0; //测距出错标志
delay_flag=0; //延时标志
delay_cnt=0; //延时计数器
//舵机
uint timer=0; //延时基准变量
uchar pwm_val_left = 0;//变量定义
uchar push_val_left =14;//舵机归中,产生约,1.5MS 信号
/********************************************************/
/*********延时函数***************************************/
void Delay1ms(uint i) //1ms延时程序
{
uchar j;
while(i--)
{
for(j=0;j<125;j++)
{ ; }
}
}
void delay(unsigned int k) //延时函数
{
unsigned int x,y;
for(x=0;x<k;x++)
for(y=0;y<2000;y++);
}
/********************************************************/
void Delay20us() //@12.000MHz
{
unsigned char i;
_nop_();
i = 7;
while (--i);
}
/*****转换显示三位数*************************************/
void LCD_dis_3BIT(uchar x,uchar y,ulong dis_dat) //列,行,转换显示三位十进制数
{
GotoXY(x,y);
LCD1602_Write(LCD1602_data,dis_dat%1000/100+0x30); //百位
LCD1602_Write(LCD1602_data,dis_dat%1000%100/10+0x30); //十位
LCD1602_Write(LCD1602_data,dis_dat%1000%10%10+0x30); //个位
}
/**********测距初始化程序********************************/
void SR04_init()
{
TMOD = 0x11;//超声波就用定时器0
EA = 1; //开总中断
ET0 = 0; //如果ET0=1计数器中断可以记录中断次数,也就是扩展计数器位数,
//计数为 0-需要大(>65535用中断再计数)如果ET0=0计数器,计数为 0-65535
TR0 = 0;
TF0 = 0;
EX0 = 0;
IT0 = 0; //低电平触发
}
/************************启动测距************************/
void StartModule() //启动测距信号
{
Trig=1;
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
_nop_();
Trig=0;
while(!Echo); //当RX为零时等待
succeed_flag=0; //测量成功标志
EX0 = 1;
TR0=1; //开启计数
}
/********************************************************/
void Conut(void) //计算距离
{
time=TH0*256+TL0; //读取脉宽长度
TF0=0;
TH0=0;
TL0=0;
S=(time*1.7)/100; //算出来是CM
if(S>=400)
{
S=400;
}
LCD_dis_3BIT(6,1,S);//显示距离
}
/*************************************************/
/************外部中断0服务程序********************/
void Int0(void) interrupt 0
{
TR0 = 0;//关闭定时器
succeed_flag = 1;//至成功测量的标志
EX0 = 0;//关闭外部中断
}
/************************************************************************/
//前速前进
void run(void)
{
Left_moto_go ; //左电机往前走
Right_moto_go ; //右电机往前走
}
/************************************************************************/
//前速后退
void backrun(void)
{
Left_moto_back ; //左电机往后走
Right_moto_back ; //右电机往后走
}
/************************************************************************/
//左转
void leftrun(void)
{
Left_moto_back ; //左电机往后走
Right_moto_go ; //右电机往前走
}
/************************************************************************/
//右转
void rightrun(void)
{
Left_moto_go ; //左电机往前走
Right_moto_back ; //右电机往后走
}
/************************************************************************/
//STOP
void stoprun(void)
{
Left_moto_Stop ; //左电机停走
Right_moto_Stop ; //右电机停走
}
/************************************************************************/
/******************舵机控制**********************************************/
void COMM( void ) //方向函数
{
push_val_left=55; //舵机向左转90度 5
timer=0;
while(timer<=4000); //延时400MS让舵机转到其位置 4000
StartModule(); //启动超声波测距
Conut(); //计算距离
S2=S;
push_val_left=14; //舵机向右转90度 23
timer=0;
while(timer<=4000); //延时400MS让舵机转到其位置
StartModule(); //启动超声波测距
Conut(); //计算距离
S4=S;
push_val_left=33; //舵机归中 14
timer=0;
while(timer<=4000); //延时400MS让舵机转到其位置
StartModule(); //启动超声波测距
Conut(); //计算距离
S1=S;
if((S2<20)||(S4<20)) //只要左右各有距离小于,20CM小车后退
{
backrun(); //后退
timer=0;
while(timer<=4000);
}
if(S2>S4)
{
rightrun(); //车的左边比车的右边距离小 右转
timer=0;
while(timer<=4000);
}
else
{
leftrun(); //车的左边比车的右边距离大 左转
timer=0;
while(timer<=4000);
}
}
/***************舵机PWM初始化程序******************************************/
void Servo_PWM_init(void) //定时器2为16位自动重载模式
{
T2MOD = 0; //初始化模式寄存器
T2CON = 0; //初始化控制寄存器
TL2=RCAP2L=(65536-100)%256; //设置定时初值和定时重载值
TH2=RCAP2H=(65536-100)/256;
// IPH=0x20; //定时器2为最高优先级
// IP=0x20;
ET2=1; //定时器2中断开
TR2 = 1; //定时器2开始计时
EA=1;
}
/************************************************************************/
/* PWM调制舵机转速 */
/************************************************************************/
/*调节push_val_left的值改变舵机转速,占空比 */
void pwm_Servomoto(void)
{
if(pwm_val_left<=push_val_left)
Sevro_moto_pwm=1;
else
Sevro_moto_pwm=0;
if(pwm_val_left>=200)
pwm_val_left=0;
}
/***************************************************/
///*定时器2中断服务子函数产生PWM信号*/
void timer2() interrupt 5
{
timer++; //定时器100US为准。在这个基础上延时
pwm_val_left++;
pwm_Servomoto(); //舵机转向调整
}
/***************************************************/
/************主程序**************************************/
void main()
{
LCD1602_init(); //初始化程序
GotoXY(0,0);
Print("current distance");
GotoXY(0,1);
Print(" cm ");
Servo_PWM_init(); //舵机初始化程序
push_val_left=33; //中间为33 左边 55 右边14
while(1)
{
if(timer>=1000) //100MS检测启动检测一次 1000
{
timer=0;
if(busy_flag==0) //测距中标志
{
busy_flag=1; //测距中标志
StartModule(); //启动检测
}
if(succeed_flag==1) //测量成功标志
{
succeed_flag=0; //测量成功标志
Conut(); //计算距离
if(S<20) //距离小于20CM
{
stoprun(); //小车停止
// COMM(); //方向函数
}
else
if(S>30) //距离大于,30CM往前走
run();
busy_flag=0; //测距中标志
}
}
}
}
/********************************************************/
我是加了舵机驱动程序后变成这样的,测量距离比实际大了10倍
会不会是pwm的中断导致的?
我也是这么想,但是没找到解决办法
屏蔽掉这个中断看一下是不是正常,先确定问题
把舵机的PWM程序屏蔽掉,是正常的,问题就是舵机程序和超声波的中断有冲突,你能帮我看看,怎么修改吗,江湖救急!
我也是菜鸟,我提供一下我的思路,遇到这种问题的话,一般我的话先看一下是否可以避免中断的影响,如果是超声脉冲计时有问题的是否可以在进行pwm控制中断程序是进去暂停结束后在开始超声脉冲的计时,还有一种的话测量需要,pwm也一直需要,是否可以将处理放到中断里(处理的周期比较长,造成的影响应该就小多了),主函数跑pwm;
调了很久,现在终于发现问题了,是自己程序的问题,过程一言难尽了,也谢谢你的意见!
不客气,大家互相帮助
能告诉我大概是什么问题吗?