完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
本帖最后由 mhx321 于 2016-1-10 18:10 编辑
为什么我的超声波模块,测出的距离大10倍了,实测过,刚好是大了10倍,程序哪里出问题了,贴来,各位帮忙分析一下 /********************************************************/ /*项目名称:单片机避障小车 */ /*单片机:STC89C52RC */ /*晶振频率:12MHz */ /********************************************************/ #include #include #include #define uchar unsigned char #define uint unsigned int #define ulong unsigned long /************STC单片机特殊功能寄存器定义*****************/ sfr T2CON=0xC8; //定时器2控制寄存器 ***it TF2=T2CON^7; ***it TR2=T2CON^2; ***it 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 /*************端口定义**********************************/ ***it Sevro_moto_pwm=P3^5; //接舵机信号端输入PWM信号调节速度 ***it Trig=P3^1; //超声波控制端 ***it Echo=P3^2; //超声波接收端 ***it IN1=P1^0; //左边电机驱动口 ***it IN2=P1^1; //左边电机驱动口 ***it IN3=P1^2; //右边电机驱动口 ***it IN4=P1^3; //右边电机驱动口 ***it INA=P1^4; //左边电机使能端 ***it INB=P1^5; //右边电机使能端 ***it IR1=P3^6; //左边红外距离检测 ***it 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 } /********************************************************/ 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个回答
|
|
我是加了舵机驱动程序后变成这样的,测量距离比实际大了10倍
|
|
|
|
会不会是pwm的中断导致的?
|
|
|
|
|
|
|
|
屏蔽掉这个中断看一下是不是正常,先确定问题
|
|
|
|
把舵机的PWM程序屏蔽掉,是正常的,问题就是舵机程序和超声波的中断有冲突,你能帮我看看,怎么修改吗,江湖救急! |
|
|
|
我也是菜鸟,我提供一下我的思路,遇到这种问题的话,一般我的话先看一下是否可以避免中断的影响,如果是超声脉冲计时有问题的是否可以在进行pwm控制中断程序是进去暂停结束后在开始超声脉冲的计时,还有一种的话测量需要,pwm也一直需要,是否可以将处理放到中断里(处理的周期比较长,造成的影响应该就小多了),主函数跑pwm;
|
|
|
|
零tot 发表于 2016-1-10 22:59 调了很久,现在终于发现问题了,是自己程序的问题,过程一言难尽了,也谢谢你的意见! |
|
|
|
|
|
|
|
|
|
|
|
这种问题很复杂,要根据现象分析才行
|
|
|
|
你正在撰写答案
如果你是对答案或其他答案精选点评或询问,请使用“评论”功能。
644 浏览 0 评论
求助一下关于51系列单片机的Timer0的计时问题,TH0、TL0+1的时间是怎么算的?
1819 浏览 1 评论
【RA-Eco-RA4E2-64PIN-V1.0开发板试用】开箱+Keil环境搭建+点灯+点亮OLED
1262 浏览 0 评论
【敏矽微ME32G070开发板免费体验】使用coremark测试敏矽微ME32G070 跑分
1136 浏览 0 评论
【敏矽微ME32G070开发板免费体验】开箱+点灯+点亮OLED
1357 浏览 2 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
12028 浏览 31 评论
浏览过的版块 |
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-24 11:49 , Processed in 0.884237 second(s), Total 57, Slave 50 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号