OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4621|回复: 17

分享一个超声波测距的程序,不过实际测试中还有点问题,不知道是什么原因,大神帮看一下呗

[复制链接]

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
发表于 2017-3-25 20:20:34 | 显示全部楼层 |阅读模式
2金钱
本帖最后由 arao和xiaomi 于 2017-4-5 08:59 编辑

就是有时候能测试准确,但是有时候会有两厘米的误差,感觉不是很稳定,不知道是什么原因,大神帮看一下呗

#include "ultrasonic.h"
#include "sys.h"
#include "delay.h"

#define TRIG_PORT  GPIOB         //TRIG
#define ECHO_PORT  GPIOB         //ECHO

#define TRIG_PIN   GPIO_Pin_0    //TRIG
#define ECHO_PIN   GPIO_Pin_10    //ECHO


float Ultrasonic_Distance;       //计算出的距离
u8 check_data_state;

void Ultrasonic_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        EXTI_InitTypeDef EXTI_InitStructure;
         NVIC_InitTypeDef NVIC_InitStructure;
        
        //GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);        //关闭jtag
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_AFIO,ENABLE);
        
        
        GPIO_InitStructure.GPIO_Pin=TRIG_PIN;                  //PB0接TRIG   备注5伏供电
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;      //设置为推挽输出模式
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(TRIG_PORT,&GPIO_InitStructure);
        
        GPIO_InitStructure.GPIO_Pin=ECHO_PIN;                 //PB10接ECHO
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD;           //设置为输入
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_Init(ECHO_PORT,&GPIO_InitStructure);
        
        
         //PE8    中断线以及中断初始化配置
         GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource10);

          EXTI_InitStructure.EXTI_Line=EXTI_Line10;
          EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;               //中断触发
          EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;     //上升沿
          EXTI_InitStructure.EXTI_LineCmd = ENABLE;
          EXTI_Init(&EXTI_InitStructure);                 
               
                        
        NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;                        
          NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;         
          NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;                                         
          NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                                                                 
          NVIC_Init(&NVIC_InitStructure);            
        
        
}


float EXTI15_10_IRQHandler(void)
{
        
        delay_us(10);        
               
     if(EXTI_GetITStatus(EXTI_Line10) != RESET)
        {
                        TIM_SetCounter(TIM2,0);
                        TIM_Cmd(TIM2, ENABLE);                                             
               
                        while(GPIO_ReadInputDataBit(ECHO_PORT,ECHO_PIN));                        

                        TIM_Cmd(TIM2, DISABLE);                                                         
                        Ultrasonic_Distance=TIM_GetCounter(TIM2)*9.8*34/200.0;                                                                        
               
        if(Ultrasonic_Distance>0)
        {
                printf("distance:%f cm",Ultrasonic_Distance);
                LCD_ShowString(30,150,200,16,16,"Ultrasonic TEST is OK");
               
        }else
        LCD_ShowString(30,150,200,16,16,"Ultrasonic TEST is error");
               
        
        EXTI_ClearITPendingBit(EXTI_Line10);   
        
        }
        check_data_state=1;
        return Ultrasonic_Distance;
               
}
/*
*  初始化的时候,需要输出10us以上的TTL电平
*  
*
*  
*/





void Ultrasonic_StartMeasure(void)
{
        
  GPIO_SetBits(TRIG_PORT,TRIG_PIN);                  
  delay_us(20);                                   
  GPIO_ResetBits(TRIG_PORT,TRIG_PIN);
        
}





        



超声波测距5-V1.zip

4 MB, 下载次数: 2634

最佳答案

查看完整内容[请看2#楼]

LCD_ShowString函数占用时间稍长,建议放到main函数里面,中断里面只做捕获工作。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5789
金钱
5789
注册时间
2013-11-22
在线时间
1214 小时
发表于 2017-3-25 20:20:35 | 显示全部楼层
LCD_ShowString函数占用时间稍长,建议放到main函数里面,中断里面只做捕获工作。
回复

使用道具 举报

15

主题

72

帖子

0

精华

初级会员

Rank: 2

积分
128
金钱
128
注册时间
2016-11-11
在线时间
20 小时
发表于 2017-3-25 20:42:58 | 显示全部楼层
不稳定应该不是程序问题吧。程序就是一个输入对应着一个输出。输入不变的话,输出也不变。
专才能精
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-3-25 20:50:09 | 显示全部楼层
chenjiabao 发表于 2017-3-25 20:42
不稳定应该不是程序问题吧。程序就是一个输入对应着一个输出。输入不变的话,输出也不变。

你好,就是测试的距离结果不是很稳定,有时候得到的数据能很准确,然后有时候会有两厘米左右的误差,不知道是什么原因,我怕会是上面的逻辑哪里有问题什么的
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-3-25 22:09:18 | 显示全部楼层
lycreturn 发表于 2017-3-25 21:15
LCD_ShowString函数占用时间稍长,建议放到main函数里面,中断里面只做捕获工作。

你好,这个终端这部分处理有问题吗?
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-3-25 22:16:11 | 显示全部楼层
lycreturn 发表于 2017-3-25 21:15
LCD_ShowString函数占用时间稍长,建议放到main函数里面,中断里面只做捕获工作。

你好,就是这部分中断处理有问题吗
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5789
金钱
5789
注册时间
2013-11-22
在线时间
1214 小时
发表于 2017-3-25 22:26:08 | 显示全部楼层
arao和xiaomi 发表于 2017-3-25 22:16
你好,就是这部分中断处理有问题吗

如果中断频率较高,而中断服务函数占用时间又比较长,有可能丢失部分中断,所以要求中断服务函数占用时间尽可能短
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-3-25 22:32:18 | 显示全部楼层
lycreturn 发表于 2017-3-25 22:26
如果中断频率较高,而中断服务函数占用时间又比较长,有可能丢失部分中断,所以要求中断服务函数占用时间 ...

你好,我按照你的建议把它改成这样,然后老出问题,不知道哪里错了

float EXTI15_10_IRQHandler(void)
{
       
               
               
     if(EXTI_GetITStatus(EXTI_Line10) != RESET)
        {
                        TIM_SetCounter(TIM2,0);
                        TIM_Cmd(TIM2, ENABLE);                                             
               
                        while(GPIO_ReadInputDataBit(ECHO_PORT,ECHO_PIN));                         

                        TIM_Cmd(TIM2, DISABLE);                                                        
                        Ultrasonic_Distance=TIM_GetCounter(TIM2)*9.8*34/200.0;                                                 
                        EXTI_ClearITPendingBit(EXTI_Line10);
                        check_data_state=1;               
       
        }
       
        return Ultrasonic_Distance;
               
}

while(1)
        {                 
                Ultrasonic_StartMeasure();
               
               
               
               
                        POINT_COLOR=BLUE;
                       
                        if(check_data_state)
                        {
                                if(Ultrasonic_Distance>0)
                                {
                                        printf("distance:%f cm",Ultrasonic_Distance);
                                        LCD_ShowString(30,150,200,16,16,"Ultrasonic TEST is OK");
                                       
                                        distance=Ultrasonic_Distance;
                                       
                                       
                                       
                                        LCD_ShowxNum(157,170,distance,3,16,0x80);//显示距离值      显示整数部分
                                        Ultrasonic_Distance-=distance;
                                        Ultrasonic_Distance*=100;                                    // 扩大10倍,显示小数 部分
                                        LCD_ShowxNum(184,170,Ultrasonic_Distance,2,16,0x80);
                                }
                                else  LCD_ShowString(30,150,200,16,16,"Ultrasonic TEST is error");
                               
                                check_data_state=0;
                               
                        }
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5789
金钱
5789
注册时间
2013-11-22
在线时间
1214 小时
发表于 2017-3-25 22:47:45 | 显示全部楼层
本帖最后由 lycreturn 于 2017-3-25 22:50 编辑
arao和xiaomi 发表于 2017-3-25 22:32
你好,我按照你的建议把它改成这样,然后老出问题,不知道哪里错了

float EXTI15_10_IRQHandler(vo ...

仔细看了下你的代码,我是不建议用这种方式(中断里面等待引脚被拉低)测量高电平的,同样用了定时器还占用一路中断,中断里还死等;当然不是说这种方式不行,只是你可以用更好的方法:那就是输出捕获,捕获高电平就可以了,例程也有现成的;
好了,说回来,你的这种方式,实际没测试过,不知是不是中断服务函数那儿出问题了,中断服务函数改成void试试吧,我自己肯定是不会 使用这种测量方式的
回复

使用道具 举报

3

主题

2170

帖子

0

精华

资深版主

Rank: 8Rank: 8

积分
5789
金钱
5789
注册时间
2013-11-22
在线时间
1214 小时
发表于 2017-3-25 23:14:04 | 显示全部楼层
arao和xiaomi 发表于 2017-3-25 22:32
你好,我按照你的建议把它改成这样,然后老出问题,不知道哪里错了

float EXTI15_10_IRQHandler(vo ...

知道你哪里出问题了,你没给我看TIM2的配置,问题就出在TIM2,你配置的定时器计数频率太低了,把它设置成1us 计数一次即可
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-3-25 23:19:03 | 显示全部楼层
lycreturn 发表于 2017-3-25 23:14
知道你哪里出问题了,你没给我看TIM2的配置,问题就出在TIM2,你配置的定时器计数频率太低了,把它设置成1 ...

我的定时器2设置的是
TIM_TimeBaseStructure.TIM_Period = 5000;  
        TIM_TimeBaseStructure.TIM_Prescaler =(7200-1);  
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-3-26 09:20:07 | 显示全部楼层
lycreturn 发表于 2017-3-25 23:14
知道你哪里出问题了,你没给我看TIM2的配置,问题就出在TIM2,你配置的定时器计数频率太低了,把它设置成1 ...

你好,我把显示的部分从中断中取出来放到主函数中去了,果然稳定效果要好一些,但是偶尔的还是会出现浮动,感觉确实可以试一下用输入捕获的方式来做,谢谢你
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-3-26 09:24:42 | 显示全部楼层
lycreturn 发表于 2017-3-25 23:14
知道你哪里出问题了,你没给我看TIM2的配置,问题就出在TIM2,你配置的定时器计数频率太低了,把它设置成1 ...

忘了说了找到原因了,就是发现电压没接对,本来是要5伏工作,我错结成3.3伏,所以计数器一直计数不对,哎,郁闷死了
回复

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2016-1-3
在线时间
32 小时
发表于 2017-4-4 21:14:30 | 显示全部楼层
你好  你发一下你的代码让我参考一下吗   我正在整超声波  谢谢
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-4-5 08:55:44 | 显示全部楼层
lewol 发表于 2017-4-4 21:14
你好  你发一下你的代码让我参考一下吗   我正在整超声波  谢谢

恩,好的,我上传一下,不过发现还是有点问题,不是很稳定
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-4-5 09:00:47 | 显示全部楼层
代码已上传,大家可以参考一下, 有什么问题欢迎讨论
回复

使用道具 举报

0

主题

5

帖子

0

精华

初级会员

Rank: 2

积分
107
金钱
107
注册时间
2016-1-3
在线时间
32 小时
发表于 2017-4-5 21:12:37 | 显示全部楼层
arao和xiaomi 发表于 2017-4-5 09:00
代码已上传,大家可以参考一下, 有什么问题欢迎讨论

谢谢分享,有一个问题,就是外部中服务函数中的返回值是如何传递到主函数的?我的MDK5主函数报错返回值的定义。
回复

使用道具 举报

33

主题

310

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
495
金钱
495
注册时间
2016-12-31
在线时间
63 小时
 楼主| 发表于 2017-4-6 08:46:36 | 显示全部楼层
lewol 发表于 2017-4-5 21:12
谢谢分享,有一个问题,就是外部中服务函数中的返回值是如何传递到主函数的?我的MDK5主函数报错返回值的 ...

你定义一个全局变量,然后在最后中断的时候返回就可以了,但是不知道这样操作合不合适
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-8-22 09:17

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表