输入一个数则 是他的平方 两个数则相乘 主要是输入不确定值的情况
这问的啥啊?太抽象了
你得有一个输入结束标志吧。比如只要换行就表示输入结束,判断到底输入几个数。或者判断到文件尾(即输入CTRL+Z)则算输入结束
不知道你这个问题是否已经解决, 如果还没有解决的话:首先,让我们不修改源码,直接把另一个通道的代码复制粘贴过去,再在主函数打印出其各自高低电平时间。(这里我直接用超声波做实验了,要是拿按键感觉加的代码更多而且还不够直观)
test.c
#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "led.h"
#include "timer.h"
#include "sys.h"
extern u8 TIM2CH1_CAPTURE_STA;
extern u16 TIM2CH1_CAPTURE_VAL;
extern u8 TIM2CH2_CAPTURE_STA;
extern u16 TIM2CH2_CAPTURE_VAL;
int main(void)
{
u32 temp1,temp2;
Stm32_Clock_Init(9); //系统时钟设置
uart_init(72,9600);
delay_init(72); //延时初始化
TIM2_Cap_Init(0XFFFF,72-1);
while(1)
{
printf("hello world\r\n");
PBout(6)=1; //打开TRIG
PBout(7)=1;
delay_us(20);
PBout(6)=0;
PBout(7)=0;
if(TIM2CH1_CAPTURE_STA&0X80) //成功捕获到了一次高电平
{
temp2=TIM2CH1_CAPTURE_STA&0X3F;
temp2*=65536; //溢出时间总和
temp2+=TIM2CH1_CAPTURE_VAL;
temp2*=0.017; //得到距离
printf("TIM2_CH1_LENGTH:%d cm\r\n",temp2); //打印距离
TIM2CH1_CAPTURE_STA=0; //开启下一次捕获
}
if(TIM2CH2_CAPTURE_STA&0X80) //成功捕获到了一次高电平
{
temp1=TIM2CH2_CAPTURE_STA&0X3F;
temp1*=65536; //溢出时间总和
temp1+=TIM2CH2_CAPTURE_VAL;
temp1*=0.017; //得到距离
printf("TIM2_CH2_LENGTH:%d cm\r\n",temp1); //打印距离
TIM2CH2_CAPTURE_STA=0; //开启下一次捕获
}
}
}
timer.c
#include "timer.h"
#include "led.h"
#include "sys.h"
void TIM2_Cap_Init(u16 arr,u16 psc)
{
RCC->APB1ENR|=1<<0;
RCC->APB2ENR|=1<<2;
RCC->APB2ENR|=1<<3; //使能PORTB时钟
GPIOA->CRL&=0XFFFFFF00; //定时器2通道1
GPIOA->CRL|=0X00000088; //定时器2通道2
GPIOA->ODR|=0<<0;
GPIOA->ODR|=1<<1;
GPIOB->CRL&=0X00FFFFFF;//PB7清除之前设置
GPIOB->CRL|=0X33000000;//PB7推挽输出
GPIOB->ODR|=1<<7; //PB7 输出高
GPIOB->ODR|=1<<6;
TIM2->ARR=arr;
TIM2->PSC=psc;
TIM2->CCMR1|=1<<0;
TIM2->CCMR1|=1<<4;
TIM2->CCMR1|=0<<2;
TIM2->CCMR1|=1<<8;
TIM2->CCMR1|=1<<12;
TIM2->CCMR1|=0<<10;
TIM2->CCER|=0<<1;
TIM2->CCER|=1<<0;
TIM2->CCER|=0<<5;
TIM2->CCER|=1<<4;
TIM2->DIER|=1<<1;
TIM2->DIER|=1<<2;
TIM2->DIER|=1<<0;
TIM2->CR1|=0x01;
MY_NVIC_Init(2,0,TIM2_IRQn,2);
}
u8 TIM2CH1_CAPTURE_STA=0;
u16 TIM2CH1_CAPTURE_VAL;
u8 TIM2CH2_CAPTURE_STA=0;
u16 TIM2CH2_CAPTURE_VAL;
void TIM2_IRQHandler(void)
{
u16 tsr;
tsr=TIM2->SR;
if((TIM2CH1_CAPTURE_STA&0X80)==0)
{
if(tsr&0X01)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
if((TIM2CH1_CAPTURE_STA&0X3F)==0X3F)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=0XFFFF;
}else TIM2CH1_CAPTURE_STA++;
}
}
if(tsr&0x02)
{
if(TIM2CH1_CAPTURE_STA&0X40)
{
TIM2CH1_CAPTURE_STA|=0X80;
TIM2CH1_CAPTURE_VAL=TIM2->CCR1;
TIM2->CCER&=~(1<<1);
}else
{
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_CAPTURE_STA=0X40;
TIM2->CNT=0;
TIM2->CCER|=1<<1;
}
}
}
if((TIM2CH2_CAPTURE_STA&0X80)==0)
{
if(tsr&0X01)
{
if(TIM2CH2_CAPTURE_STA&0X40)
{
if((TIM2CH2_CAPTURE_STA&0X3F)==0X3F)
{
TIM2CH2_CAPTURE_STA|=0X80;
TIM2CH2_CAPTURE_VAL=0XFFFF;
}else TIM2CH2_CAPTURE_STA++;
}
}
if(tsr&0x04)
{
if(TIM2CH2_CAPTURE_STA&0X40)
{
TIM2CH2_CAPTURE_STA|=0X80;
TIM2CH2_CAPTURE_VAL=TIM2->CCR2;
TIM2->CCER&=~(1<<5);
}else
{
TIM2CH2_CAPTURE_VAL=0;
TIM2CH2_CAPTURE_STA=0X40;
TIM2->CNT=0;
TIM2->CCER|=1<<5;
}
}
}
TIM2->SR=0;
}
上述代码基本上是在一个超声波测距的情况下加上另一个超声波(即多设置一个输入捕获),当然这种方案是不可行的,以下是实验结果。
因为录不了视频,但是大致就是我在两个超声波前均放了障碍物,距离超声波5cm左右,从图中可以看出,距离并不准确,而且跳动范围很大。
分析上述整个错误程序我发现,虽然两个通道在进行输入捕获时并没有干扰,但是他们是在同一定时器下,即他们所用的计数器是相同的。
在一个输入捕获实验中,TIM2_CH1 来捕获高电平脉宽,也就是要先设置输入捕获为上升沿检测,记
录发生上升沿的时候 TIM2_CNT 的值。然后配置捕获信号为下降沿捕获,当下降沿到来时,发
生捕获,并记录此时的 TIM2_CNT 值。这样,前后两次 TIM2_CNT 之差,就是高电平的脉宽,
同时 TIM2 的计数频率我们是知道的,从而可以计算出高电平脉宽的准确时间,从而算出距离。
而两个通道中,他们共用的是同一定时器。如果他们同时发生中断,各自进入各自的函数中,那么问题就来了,以下代码示:
else
{
TIM2CH1_CAPTURE_VAL=0;
TIM2CH1_CAPTURE_STA=0X40;
TIM2->CNT=0;
TIM2->CCER|=1<<1;
}
这是中断函数中的一段代码,最重要的是第五行TIM2->CNT=0,试想如果两个通道同时发生中断,进入各自的函数中,均会执行这行代码,这行代码就是一个清零计数器,就像你得先把你的秒表清空了,才可以计时,对吧?但是两者在执行各自代码中,都将计数器清零!这样就会导致计数的错乱,从而显示的数字就会杂乱无章,没有规律。