#include "RCWL.h"
#define RCWL1601_PORT GPIOB
#define RCWL16014_CLK RCC_APB2Periph_GPIOB
#define RCWL1601_TRIG GPIO_Pin_5
#define RCWL1601_ECHO GPIO_Pin_6
#define RCC_APB1Periph_TIM RCC_APB1Periph_TIM2
#define RCTW_TIM TIM2
#define RCTW_IRQn TIM2_IRQn
#define TRIG_Send PBout(5)
#define ECHO_Reci PBin(6)
u16 msRcCount = 0; //毫秒計數
void RCWL1601_NVIC(void);
void RCWL1601_Init()
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure_RCWL; //生成用于定時器設置的結構體
GPIO_InitTypeDef GPIO_InitStructure_RCWL;
RCC_APB2PeriphClockCmd(RCWL16014_CLK,ENABLE);
// IO初始化
GPIO_InitStructure_RCWL.GPIO_Pin = RCWL1601_TRIG; //發送電平引腳
GPIO_InitStructure_RCWL.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure_RCWL.GPIO_Mode = GPIO_Mode_Out_PP; //推挽輸出
GPIO_Init(RCWL1601_PORT,&GPIO_InitStructure_RCWL);
GPIO_ResetBits(RCWL1601_PORT,RCWL1601_TRIG);
GPIO_InitStructure_RCWL.GPIO_Pin = RCWL1601_ECHO; //返回電平引腳
GPIO_InitStructure_RCWL.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空輸入
GPIO_Init(RCWL1601_PORT,&GPIO_InitStructure_RCWL);
GPIO_ResetBits(RCWL1601_PORT,RCWL1601_ECHO);
//定時器初始化使用基本定時器TIM6
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM,ENABLE); //使能對應RCC時鐘
//配置定時器基礎結構體
TIM_DeInit(RCTW_TIM);
TIM_TimeBaseStructure_RCWL.TIM_Period =(1000-1); //設置在下一個更新事件裝入活動的自動重裝載寄存器周期的計數到1000為1ms
TIM_TimeBaseStructure_RCWL.TIM_Prescaler =(72-1); //設置用來作為TIMx時鐘頻率除數的預分頻值1M的計數頻率1US計數
TIM_TimeBaseStructure_RCWL.TIM_ClockDivision = TIM_CKD_DIV1; //不分頻
TIM_TimeBaseStructure_RCWL.TIM_CounterMode = TIM_CounterMode_Up; // TIM向上計數模式
TIM_TimeBaseInit(RCTW_TIM,&TIM_TimeBaseStructure_RCWL); //根據TIM_TimeBaseInitStruct中指定的參數初始化TIMX的時間基數單位
TIM_ClearFlag(RCTW_TIM,TIM_FLAG_Update); //清除更新中斷,免得一打開中斷立即產生中斷
TIM_ITConfig(RCTW_TIM,TIM_IT_Update,ENABLE); //打開定時器更新中斷
RCWL1601_NVIC();
TIM_Cmd(RCTW_TIM,DISABLE);
}
//提示:靜態函數的作用域僅限于定義它的源文件內,所以不需要在頭文件里聲明
static void OpenTimerForHc() //打開定時器
{
TIM_SetCounter(RCTW_TIM,0); //清除計數
msRcCount = 0;
TIM_Cmd(RCTW_TIM,ENABLE); //使能TIMX外設
}
static void CloseTimerForHc() //關閉定時器
{
TIM_Cmd(RCTW_TIM,DISABLE); //使能TIMX外設
}
// NVIC配置
void RCWL1601_NVIC()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = RCTW_IRQn; //選擇串口1個中斷
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //搶占式中斷優先級設置為1
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //響應式中斷優先級設置為1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能中斷
NVIC_Init(&NVIC_InitStructure);
}
//定時器6中斷服務程序
void TIM2_IRQHandler(void) // TIM3中斷
{
if(TIM_GetITStatus(RCTW_TIM,TIM_IT_Update)!= RESET) //檢查TIM3更新中斷發生與否
{
TIM_ClearITPendingBit(RCTW_TIM,TIM_IT_Update); //清除TIMX更新中斷標志
msRcCount++;
}
}
//獲取定時器時間
u32 GetEchoTimer(void)
{
u32 t = 0;
t= msRcCount*1000; //得到MS
t+= TIM_GetCounter(RCTW_TIM); //得到us
RCTW_TIM-> CNT = 0; //將TIM2計數寄存器的計數值清零
Delay_Ms(50);
return t;
}
//一次獲取超聲波測距數據兩次測距之間需要相隔一段時間,隔斷回響信號
//為了消除余震的影響,取五次數據的平均值進行加權濾波。
float RCWL1601GetLength(void)
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)
{
TRIG_Send = 1; //發送口高電平輸出
Delay_Us(20);
TRIG_Send = 0;
while (ECHO_Reci==0); //等待接收口高電平輸出
OpenTimerForHc(); //打開定時器
i = i + 1;
while (ECHO_Reci==1);
CloseTimerForHc(); //關閉定時器
t = GetEchoTimer(); //獲取時間,分辨率為1US
lengthTemp =((float )t /58.0); //厘米
sum = lengthTemp + sum;
}
lengthTemp = sum / 5.0;
return lengthTemp;
}
/*
函數名稱:Delay_Ms_Ms
**功能描述:延時1MS(可通過仿真來判斷他的準確度)
**參數描述:time(ms)注意時間<65535
*/
void Delay_Ms(uint16_t time) //延時函數
{
uint16_t i,j;
for (i = 0; i <time; i ++)
for (j = 0; j <10260; j ++);
}
/* :::::::::::::::::::::::::::::::::::::::::::::::: :::::::::::::
**函數名稱:Delay_Ms_Us
**功能描述:延時1us(可通過仿真來判斷他的準確度)
**參數描述:time(us)注意時間<65535
:::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::: */
void Delay_Us(uint16_t time) //延時函數
{
uint16_t i,j;
for (i = 0; i <time; i ++)
for (j = 0; j <9; j ++);
} |