51有很多现有可以使用的例程,但是随着对单片机处理性能的提高,需要使用32位的单片机,把程序移植过来,需要考虑的东西比较多。
超声波测距原理:
通过ECHO(外部中断1)引脚被超声波传感器拉高时自动启动和关闭定时器得到计时时间,由传播时间和速度计算出距离。
移植过程:
需要使用到STM32的定时器,选用基本定时器即可。
遇到的问题:
在从51转换到STM32的问题主要是:
定时器类型多,无从选择;
定时器设置方法不同。
如果把STM32上的定时器结构搞清楚了,问题迎刃而解。
STM32F103系统一共包含8个定时器和1个系统滴答定时器(SysTick),另外还有1和实时时钟、2个看门狗定时器。
此处我们使用基本定时器,基本定时器TIM6和TIM7各包含一个16位自动装载计数器,由各自的可编程预分频器驱动,在更新事件(计数器溢出)时产生中断/DMA请求。
时基单元:
计数器TIMx_CNT
预分频器TIMx_PSC
自动装载寄存器TIMx_ARR
三者可由软件进行读写操作,计数器运行期间也可以读写。
计时时间计算:(TIM_Prescaler+1) x (TIM_Period+1) /TIMxCLK
u32 SonarRange(void) { //测距准备 float fDist;//测距值 u32 T1; //T1运行时间(单位:机器周期个数) //使用基本定时器TIM6 Timer_Config(); //配置中断优先级 NVIC_Config(); //触发超声测距(高电平持续10us以上,下降沿触发超声测距) sonar_TRIG_PORT->ODR = 1;//触发信号拉高 delay_us(20);//保持10us以上 sonar_TRIG_PORT->ODR = 0; //触发信号拉低 while(!sonar_ECHO_PORT->IDR);//等待ECHO=1,开始计时 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); while(sonar_ECHO_PORT->IDR);//等待ECHO==0,结束计时 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); T1=TIM6->CNT; //超声测距值换算及有效性校验 fDist = (float)T1 * T * 0.17;//先换算成以us为单位的T1运行时间,再换算成以mm为单位的超声测距值 if(fDist < RANGE_MIN || fDist > 1000)//无效或不稳定的测距值 return 0; else//有效的测距值 return (u32)fDist;//测距值取整 } void Timer_Config() { TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; //RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);//开启TIM6 TIM_DeInit(TIM6);//复位,使其初始化 //赋初值 TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);//结构赋默认值 TIM_TimeBaseStructure.TIM_Period=0;//自动装载寄存器赋值0 TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); TIM_ClearFlag(TIM6, TIM_FLAG_Update);//清除中断标志 TIM_ITConfig(TIM6, TIM_IT_Update, ENABLE); TIM_Cmd(TIM6, ENABLE);//使能计时器,并未开始计时 }