5

STM32F103C8T6芯片写的三路超声波读距离数据跳变问题

大家好,请大家帮我看看这个问题,我使用STM32F103C8T6这款芯片,参考网上的程序改写了一个使用定时器TIM4的三个通道分别读三个超声波距离的代码,但是三个超声波的数据均不准确,显示的数据完全超出正常范围(使用单个通道测试单个超声波的数据获取基本上正确可用)。相关程序如下:
    一    定时器配置
    void Ultrasonic_TIM4_Init(u16 arr, u16 psc)

{
TIM_ICInitTypeDef TIM_ICInitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
//
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);

    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = arr;
    TIM_TimeBaseInitStruct.TIM_Prescaler = psc;
    TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStruct);
    //TIM4 CH1 INIT
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
    TIM_ICInitStruct.TIM_ICFilter = 0x00;
    TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;  //³õʌ׎̬ÉèÖÃΪÉÏÉýÑز¶»ñ
    TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInit(TIM4, &TIM_ICInitStruct);
            //TIM4 CH2 INIT
      TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
    TIM_ICInitStruct.TIM_ICFilter = 0x00;
    TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInit(TIM4, &TIM_ICInitStruct);
            //TIM4 CH3 INIT
      TIM_ICInitStruct.TIM_Channel = TIM_Channel_3;
    TIM_ICInitStruct.TIM_ICFilter = 0x00;
    TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
    TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
    TIM_ICInit(TIM4, &TIM_ICInitStruct);
    //CH1---PB6 CH2---PB7  CH3---PB8
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6; 
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
            GPIO_ResetBits(GPIOB,GPIO_Pin_6);
    //TRIG PIN INIT  PB0 PB1 PB2
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStruct);
    GPIO_ResetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2);
    //
    NVIC_InitStruct.NVIC_IRQChannel = TIM4_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
    NVIC_Init(&NVIC_InitStruct);
    //
    TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_CC1, ENABLE);
            TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_CC2, ENABLE);
            TIM_ITConfig(TIM4, TIM_IT_Update | TIM_IT_CC3, ENABLE);
    TIM_Cmd(TIM4, ENABLE);

// Working_Light = 1; //code debug
}

二   定时器中断函数

void TIM4_IRQHandler(void)
{
//CH1
if((TIM4CH1_CAPTURE_STA & 0x80) == 0)
{
if(TIM_GetITStatus(TIM4, TIM_IT_Update) == 1)
{

if(TIM4CH1_CAPTURE_STA & 0x40)
{
if((TIM4CH1_CAPTURE_STA & 0x3F) == 0x3F)
{
TIM4CH1_CAPTURE_STA |= 0x80;
TIM4CH1_CAPTURE_VAL = 0xFFFF;
// Working_Light = 0; //code debug
}
else
{
TIM4CH1_CAPTURE_STA++;
// Indicator_Light_TIM2 = 0; //code debug
}
}
}
if(TIM_GetITStatus(TIM4, TIM_IT_CC1) == 1)
{
if(TIM4CH1_CAPTURE_STA & 0x40)
{
TIM4CH1_CAPTURE_STA |= 0x80;
TIM4CH1_CAPTURE_VAL = TIM_GetCapture1(TIM4);
TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Rising);
// Indicator_Light_TIM2 = 1; //code debug
}
else
{
TIM4CH1_CAPTURE_STA = 0;
TIM4CH1_CAPTURE_VAL = 0;
TIM4CH1_CAPTURE_STA |= 0x40;
TIM_SetCounter(TIM4, 0);
TIM_OC1PolarityConfig(TIM4, TIM_ICPolarity_Falling);
// Working_Light = 1; //code debug
}

            }
    }
            //CH2 
            if((TIM4CH2_CAPTURE_STA & 0x80) == 0)//»¹ÎŽ³É¹Š²¶»ñ
    {
            if(TIM_GetITStatus(TIM4, TIM_IT_Update) == 1)  //žüÐÂÖжÏÔŽ ÖжϷ¢Éú£š¶šÊ±Æ÷ÖжϷ¢Éú£©
            {                               
                                            //CH2
                                            if(TIM4CH2_CAPTURE_STA & 0x40)  //ÒÑŸ­²¶»ñµœžßµçÆœÁË
                    {
                            if((TIM4CH2_CAPTURE_STA & 0x3F) == 0x3F)   //žßµçƜ׎̬
                            {
                                    TIM4CH2_CAPTURE_STA |= 0x80; //±êŒÇ³É¹Š²¶»ñÁËÒ»ŽÎ
                                    TIM4CH2_CAPTURE_VAL = 0xFFFF;

// Working_Light = 0; //code debug
}
else
{
TIM4CH2_CAPTURE_STA++;
Indicator_Light_TIM2 = 0; //code debug
}
}
}

                            if(TIM_GetITStatus(TIM4, TIM_IT_CC2) == 1){  //ÍšµÀ2·¢Éú²¶»ñÊÂŒþ
                    if(TIM4CH2_CAPTURE_STA & 0x40)  // ²¶»ñµœÏÂœµÑØ
                    {
                            TIM4CH2_CAPTURE_STA |= 0x80;    //±êŒÇ³É¹Š²¶»ñµœÒ»ŽÎÉÏÉýÑØ
                            TIM4CH2_CAPTURE_VAL = TIM_GetCapture2(TIM4);
                            TIM_OC2PolarityConfig(TIM4, TIM_ICPolarity_Rising);//ÉèÖÃΪÉÏÉýÑز¶»ñ
                                                            Indicator_Light_TIM2 = 1;   //code debug
                    }
                    else
                    {
                            TIM4CH2_CAPTURE_STA = 0;  //Çå¿Õ
                            TIM4CH2_CAPTURE_VAL = 0;
                            TIM4CH2_CAPTURE_STA |= 0x40;  //±êŒÇ²¶»ñµœÁËÉÏÉýÑØ
                            TIM_SetCounter(TIM4, 0);
                            TIM_OC2PolarityConfig(TIM4, TIM_ICPolarity_Falling); //ÉèÖÃΪÏÂœµÑز¶»ñ

// Working_Light = 1; //code debug
}
}
}
//CH3
if((TIM4CH3_CAPTURE_STA & 0x80) == 0)
{
if(TIM_GetITStatus(TIM4, TIM_IT_Update) == 1)
{
if(TIM4CH3_CAPTURE_STA & 0x40)
{
if((TIM4CH3_CAPTURE_STA & 0x3F) == 0x3F)
{
TIM4CH3_CAPTURE_STA |= 0x80;
TIM4CH3_CAPTURE_VAL = 0xFFFF;
// Working_Light = 0; //code debug
}
else
{
TIM4CH3_CAPTURE_STA++;
// Indicator_Light_TIM2 = 0; //code debug
}
}
}
if(TIM_GetITStatus(TIM4, TIM_IT_CC3) == 1)
{
if(TIM4CH3_CAPTURE_STA & 0x40)
{
TIM4CH3_CAPTURE_STA |= 0x80;
TIM4CH3_CAPTURE_VAL = TIM_GetCapture3(TIM4);
TIM_OC3PolarityConfig(TIM4, TIM_ICPolarity_Rising);
// Indicator_Light_TIM2 = 1; //code debug
}
else
{
TIM4CH3_CAPTURE_STA = 0;
TIM4CH3_CAPTURE_VAL = 0;
TIM4CH3_CAPTURE_STA |= 0x40;
TIM_SetCounter(TIM4, 0);
TIM_OC3PolarityConfig(TIM4, TIM_ICPolarity_Falling);
// Working_Light = 1; //code debug
}

            }
    }

// TIM_SetCounter(TIM4, 0);
TIM_ClearITPendingBit(TIM4, TIM_IT_Update | TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3); //Çå³ýÖжÏ
}

三    计算距离的函数
通道1 
    u16 Ultrasonic_Value()

{
u32 temp;
GPIO_SetBits(GPIOB, GPIO_Pin_0);
delay_us(20);
GPIO_ResetBits(GPIOB, GPIO_Pin_0);
// Ultrasonic_TIM4_Init(arr, psc);
delay_ms(1);
while(TIM4CH1_CAPTURE_STA&0x80)
{
temp=TIM4CH1_CAPTURE_STA&0X3F;
temp*=65536;//Òç³öʱŒä×ܺÍ
temp+=TIM4CH1_CAPTURE_VAL;//µÃµœ×ܵĞߵçƜʱŒä
//value = ~~ (cm)
value = 340*temp/2/10000;
TIM4CH1_CAPTURE_STA = 0;
}
return value;
}

通道2
u16 Ultrasonic_Value2()
{
u32 temp;
GPIO_SetBits(GPIOB, GPIO_Pin_1);
delay_us(20);
GPIO_ResetBits(GPIOB, GPIO_Pin_1);

// delay_ms(1);
while(TIM4CH2_CAPTURE_STA&0x80)
{
temp=TIM4CH2_CAPTURE_STA&0X3F;
temp*=65536;//Òç³öʱŒä×ܺÍ
temp+=TIM4CH2_CAPTURE_VAL;//µÃµœ×ܵĞߵçƜʱŒä
TIM4CH2_CAPTURE_STA &= 0x3f;//Çå3y±ê֟λ
//value = ~~ (cm)
value2 = 340*temp/2/10000;
TIM4CH2_CAPTURE_STA = 0;
}
return value2;
}

通道3

u16 Ultrasonic_Value3()
{
u32 temp;
GPIO_SetBits(GPIOB, GPIO_Pin_2);
delay_us(20);
GPIO_ResetBits(GPIOB, GPIO_Pin_2);

// delay_ms(1);
while(TIM4CH3_CAPTURE_STA&0x80)
{
temp=TIM4CH3_CAPTURE_STA&0X3F;
temp*=65536;//Òç³öʱŒä×ܺÍ
temp+=TIM4CH3_CAPTURE_VAL;//µÃµœ×ܵĞߵçƜʱŒä
TIM4CH3_CAPTURE_STA &= 0x3f;//Çå3y±ê֟λ
//value = ~~ (cm)
value3 = 340*temp/2/10000;
TIM4CH3_CAPTURE_STA = 0;
}
return value3;
}

四 主函数 (主函数里我就把主要相关的代码贴出了)

NVIC_Configuration();
Ultrasonic_TIM4_Init(0XFFFF,72-1);

while(1){           
    switch (count){
        case 0:
                Ultrasonic_Value();
                count = 1;
        break;
        case 1:
                Ultrasonic_Value2();
                count = 2;
        break;
        case 2:
            Ultrasonic_Value3();
            count = 0;
        break;
    }

最后,我是通过Nokia5110来显示三个距离数据的,上面的代码已经确认定时器配置等没有问题(部分代码是在写帖子的时候改回来的,我现在将代码改为一个定时器负责一个超声波数据读取都不能达到要求,我想一个通道获取一路数据应该是正常的解决方式),因为已经能够通过各个通道读取到数据,但就是数据跳变的很厉害,完全不是正确数据。网络上面参考了很多方法,有的说是因为两个通道以上读取数据的时候,定时器就不能够清零,有的说定时器预装值不对等等。我能够使用stm32但是并不精通,所以这个问题困扰了我好久,本来要解决的demo也脱了很久了。在这里请各位帮我看看到底是什么原因导致了三个通道获取三个超声波数据会出现数据乱窜的问题。谢谢。

查看全部
zhaoqi2617
BlackSmith-2617
2017/04/08 02:26
  • stm32
  • 数据
  • 芯片
  • 超声波测距离c
  • 点赞
  • 收藏
  • 回答
    私信
满意答案
查看全部

1个回复