OpenEdv-开源电子网

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

超声测距程序出问题了

[复制链接]

25

主题

87

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2013-1-12
在线时间
3 小时
发表于 2013-8-25 21:12:31 | 显示全部楼层 |阅读模式

 
u8  overflow=0;
void Timerx_Init(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
 NVIC_InitTypeDef NVIC_InitStructure;

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能

 TIM_DeInit(TIM3);
 TIM_TimeBaseStructure.TIM_Period = 5000; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值  计数到5000为500ms
 TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); //设置用来作为TIMx时钟频率除数的预分频值  10Khz的计数频率 
 TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
 
 TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_Trigger, ENABLE );

 NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //先占优先级0级
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;  //从优先级3级
 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
 NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
      
}
void TIM3_IRQHandler(void)   //TIM3中断
{
 if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查指定的TIM中断发生与否:TIM 中断源
  {
     TIM_ClearITPendingBit(TIM3, TIM_IT_Update  );  //清除TIMx的中断待处理位:TIM 中断源
        overflow++;
     LED0=!LED0;
  }
}

void Temp_Init(void)
{
  GPIO_InitTypeDef  GPIO_InitStructure;
   
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //使能PB端口时钟
  //温度传感器   触发端口 PB.1
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;     //
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    //推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_SetBits(GPIOB,GPIO_Pin_1);       //
  //温度传感器   返回端口 PB.2
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;     //
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;   //浮空输入
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GPIOB, &GPIO_InitStructure);
  GPIO_SetBits(GPIOB,GPIO_Pin_2);       //
}


u16  Distance(void)
{
   u16 time,dis;
   GPIO_SetBits(GPIOB,GPIO_Pin_1);
   delay_us(50);
   GPIO_ResetBits(GPIOB,GPIO_Pin_1);

   TIM_Cmd(TIM3, ENABLE); //使能TIM3
   while(!GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)&&overflow==0)  //低电平等待 
   TIM_SetCounter(TIM3,0x00);
   while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_2)&&overflow==0)  //等待回应结束
   TIM_Cmd(TIM3, DISABLE); //禁止TIM3
   if(overflow!=0)
   {
      overflow=0;
   printf("fali!");
   return 0;
   }
   time=TIM_GetCounter(TIM3);
   dis=time*100/58;
   return  dis;
}


 

为什么定时器总是溢出,用示波器测了一下两个端口,都有信号,并且信号持续时间远小于定时时间,但不知道为什么还是溢出

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-25 23:15:57 | 显示全部楼层
LED0的翻转频率是多少?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

25

主题

87

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2013-1-12
在线时间
3 小时
 楼主| 发表于 2013-8-26 10:44:02 | 显示全部楼层
回复【2楼】正点原子:
大约0.5s的样子,正好是每次溢出的时间
回复 支持 反对

使用道具 举报

5

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2013-6-8
在线时间
2 小时
发表于 2013-8-26 11:40:27 | 显示全部楼层
为什么不用定时器的捕获啊
即使爬到最高的山上,一次也只能脚踏实地地迈一步。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-26 15:01:16 | 显示全部楼层
回复【3楼】海滨:
---------------------------------
那你一楼又说远小于定时器溢出时间?
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

25

主题

87

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2013-1-12
在线时间
3 小时
 楼主| 发表于 2013-8-26 15:29:58 | 显示全部楼层
回复【5楼】正点原子:
---------------------------------
因为我是检测传感器回应的高电平信号持续的时间的,这个时间远小于定时器溢出时间,本来应该是在定时器溢出之前就检测结束,关闭定时器的,但不知道为什么定时器总是溢出
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-26 18:21:38 | 显示全部楼层
回复【6楼】海滨:
---------------------------------
估计你的是没有进入中断。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

25

主题

87

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2013-1-12
在线时间
3 小时
 楼主| 发表于 2013-8-27 09:39:59 | 显示全部楼层
回复【4楼】倒拔萝卜:
---------------------------------
//定时器3通道3输入捕获配置

TIM_ICInitTypeDef  TIM3_ICInitStructure;

void TIM3_Cap_Init(u16 arr,u16 psc)
{  
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //使能TIM3时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  //使能GPIOB时钟

GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_0;  //PB0 清除之前设置  
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PB0 输入  
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_ResetBits(GPIOB,GPIO_Pin_0);

//初始化定时器3 TIM3  
TIM_TimeBaseStructure.TIM_Period = arr; //设定计数器自动重装值 
TIM_TimeBaseStructure.TIM_Prescaler =psc;  //预分频器   
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割:TDTS = Tck_tim
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位
  
//初始化TIM3输入捕获参数
TIM3_ICInitStructure.TIM_Channel = TIM_Channel_3; //
   TIM3_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; //上升沿捕获
   TIM3_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; //映射到TI3上
   TIM3_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  //配置输入分频,不分频 
   TIM3_ICInitStructure.TIM_ICFilter = 0x00;//IC1F=0000 配置输入滤波器 不滤波
   TIM_ICInit(TIM3, &TIM3_ICInitStructure);

//中断分组初始化
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;  //TIM3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;  //先占优先级2级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  //从优先级0级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道被使能
NVIC_Init(&NVIC_InitStructure);  //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器 

TIM_ITConfig(TIM3,TIM_IT_CC3,ENABLE);//允许CC3IE捕获中断

   TIM_Cmd(TIM3,ENABLE );  //使能定时器3
   


}

u8  TIM3CH3_CAPTURE_STA=0; //输入捕获状态     
u16 TIM3CH3_CAPTURE_VAL; //输入捕获值
 
//定时器3中断服务程序  
void TIM3_IRQHandler(void)


if (TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET)//捕获3发生捕获事件
{
if(TIM3CH3_CAPTURE_STA==1) //捕获到一个下降沿 
{   
TIM3CH3_CAPTURE_VAL=TIM_GetCapture3(TIM3);
    TIM_OC3PolarityConfig(TIM3,TIM_ICPolarity_Rising); //CC3P=0 设置为上升沿捕获
TIM3CH3_CAPTURE_STA=0;
LED0=!LED0;
}
if(TIM3CH3_CAPTURE_STA==0) //还未开始,第一次捕获上升沿
{

  TIM_SetCounter(TIM3,0);
    TIM_OC3PolarityConfig(TIM3,TIM_ICPolarity_Falling); //CC3P=1 设置为下降沿捕获
TIM3CH3_CAPTURE_STA=1;
                LED1=!LED1;
}     
}                
 
    TIM_ClearITPendingBit(TIM3, TIM_IT_CC3); //清除中断标志位
 
}




int main(void)
 {
    u16  dis;
    SystemInit();
delay_init(72);      //延时初始化
NVIC_Configuration();
uart_init(9600);   //串口初始化
  LED_Init();    //LED端口初始化
KEY_Init();          //按键端口初始化
TIM3_Cap_Init(10000,719);//100KHZ
while(1)
{

    GPIO_SetBits(GPIOB,GPIO_Pin_1);
delay_us(20);
GPIO_ResetBits(GPIOB,GPIO_Pin_1);
delay_ms(10);
dis=TIM3CH3_CAPTURE_VAL; //输入捕获值
printf("us:%d\n",dis); //输入捕获值
delay_ms(500);
}
 }


我在捕获中断里用红绿灯指示,红绿灯都在不停翻转,说明捕获到了,但打印出来数据不对,每次复位后第一次打印的数据是432,是正确的,然后接着打印出来的数据全是1799,  不管障碍物距离多远,只有复位后的第一个数据会变,其他的依然全是1799,这是怎么回事啊?
回复 支持 反对

使用道具 举报

25

主题

87

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
216
金钱
216
注册时间
2013-1-12
在线时间
3 小时
 楼主| 发表于 2013-8-27 09:43:17 | 显示全部楼层
回复【7楼】正点原子:
---------------------------------
进入中断了啊,指示灯在不停翻转
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-8-27 10:42:01 | 显示全部楼层
那你仿真,看看问题在哪里?你说:检测传感器回应的高电平信号持续的时间,那么这个时间你肯定是通过单片机一个IO口检测是吧?那你看看检测后,所做的处理,是不是有真的关闭定时器?单步调试下。
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

5

主题

154

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
205
金钱
205
注册时间
2013-6-8
在线时间
2 小时
发表于 2013-8-27 17:31:29 | 显示全部楼层
回复【8楼】海滨:
---------------------------------
捕获的方式都不对嘛

超声波触发后,WAVE_Echo先是上升沿,之后再是下降沿,你要做的是把这两个边沿的捕获值都给记录下来(分别用两个变量存起来),然后这两个捕获值求差就可以得到时间了,然后就是算距离啦

if(产生了捕获中断)
{
     if(sta)//捕获到上升沿
     {
           xxxx//记下此时的捕获值
        xxxx//设置成下降沿捕获
           sta=0;
      }
      else
      {
           xxxx//记下此时的捕获值
        xxxx//设置成上降沿捕获,为下一次做准备
           sta=1;
           cap_ok=1;//弄个变量标记一下捕获成功了
       }
}
还有距离很远的话,还要考虑定时器计数是不是已经溢出的情况,就这样的思路了
即使爬到最高的山上,一次也只能脚踏实地地迈一步。
回复 支持 反对

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2025-7-14 12:33

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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