C8T6_OLED_SPI_超声波测距
超声波测距小项目
仅供互相学习使用
超声波初始化
bsp_hc04.h
#ifndef __bsp_hc04_H
#define __bsp_hc04_H
#include "sys.h"
void TIM2_CAP_Init(u16 arr,u16 psc);
void HC04_cal(void);
#endif
bsp_hc04.c
#include "bsp_hc04.h"
TIM_ICInitTypeDef TIM_ICInitStruct;
void TIM2_CAP_Init(u16 arr,u16 psc)
{
GPIO_InitTypeDef GPIO_InitStruct;
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPD;
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStruct);
GPIO_ResetBits(GPIOA,GPIO_Pin_0);//初始化PA0
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(TIM2,&TIM_TimeBaseInitStruct);//定时器2初始化
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;//映射到TI1
TIM_ICInit(TIM2,&TIM_ICInitStruct);
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级为2级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
NVIC_Init(&NVIC_InitStruct);//中断优先级初始化
TIM_ITConfig(TIM2,TIM_IT_Update|TIM_IT_CC1,ENABLE);//允许更新中断,捕获中断
TIM_Cmd(TIM2,ENABLE);//使能定时器2
}
u8 TIM2CH1_CAP_STA=0;//标志位,bit0-5溢出次数。bit6高电平捕获标志。bit7捕获完成标志
u16 TIM2CH1_CAP_VAL;//下降沿计数器最终值
int distance=0;//最终距离结果
void TIM2_IRQHandler(void)
{
if((TIM2CH1_CAP_STA&0x80)==0)//bit7捕获完成判断
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)!=RESET)//发生更新中断
{
if(TIM2CH1_CAP_STA&0x40)//bit6捕获高电平判断
{
if((TIM2CH1_CAP_STA&0x3F)==0x3F)//bit0-5计数区溢出判断
{
TIM2CH1_CAP_STA|=0x80;//溢出则强行完成
TIM2CH1_CAP_VAL=0xFFFF;
}else{
TIM2CH1_CAP_STA++;//计时周期数
}
}
}
if(TIM_GetITStatus(TIM2,TIM_IT_CC1)!=RESET)//是否发生捕获事件
{
if(TIM2CH1_CAP_STA&0x40)//bit6捕获下降沿判断
{
TIM2CH1_CAP_STA|=0x80;
TIM2CH1_CAP_VAL=TIM_GetCapture1(TIM2);//获取最后一次计数值
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Rising);//恢复为上升沿触发
}else{
TIM2CH1_CAP_STA=0;
TIM2CH1_CAP_VAL=0;
TIM_SetCounter(TIM2,0);//全部清零
TIM2CH1_CAP_STA|=0x40;//捕获标志位
TIM_OC1PolarityConfig(TIM2,TIM_ICPolarity_Falling);//捕获到高电平,改变模式,捕获低电平
}
}
}
TIM_ClearITPendingBit(TIM2,TIM_IT_CC1|TIM_IT_Update);
}
void HC04_cal(void)
{
u32 temp;
temp=TIM2CH1_CAP_STA&0x3F;
temp*=65536;
temp+=TIM2CH1_CAP_VAL;
distance=(int)temp*340*0.5*0.001;//毫米
if(distance>4000)
{
distance=4000;
}
}
main.c
//=========================================电源接线================================================//
// OLED模块 STM32单片机
// VCC 接 DC 5V/3.3V //OLED屏电源正
// GND 接 GND //OLED屏电源地
//=======================================液晶屏数据线接线==========================================//
//本模块默认数据总线类型为4线制SPI
// OLED模块 STM32单片机
// D1 接 PB15 //OLED屏SPI写信号
//=======================================液晶屏控制线接线==========================================//
// OLED模块 STM32单片机
// CS 接 PB11 //OLED屏片选控制信号
// RES 接 PB12 //OLED屏复位控制信号
// DC 接 PB10 //OLED屏数据/命令选择控制信号
// D0 接 PB13 //OLED屏SPI时钟信号
//=========================================触摸屏接线=========================================//
//本模块不带触摸功能,所以不需要触摸屏接线
#include "delay.h"
#include "sys.h"
#include "oled.h"
#include "gui.h"
#include "test.h"
#include "bsp_hc04.h"
#include "led.h"
extern int distance;
extern u8 TIM2CH1_CAP_STA; //输入捕获状态
int main(void)
{
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
TIM2_CAP_Init(0xFFFF,72-1);//65535
LED_Init();
OLED_Init(); //初始化OLED
OLED_Clear(0); //清屏(全黑)
while(1)
{
LED0=1;
delay_us(20);//发送20us高电平
LED0=0;//控制端口PC13
if(TIM2CH1_CAP_STA&0X80)
{
HC04_cal();
TIM2CH1_CAP_STA=0; //开启下一次捕获
}
GUI_ShowString(0,16,"distance:",16,1);//字母宽8格
GUI_ShowNum(48,32,distance,5,16,1);//以左上角为坐标基准点
GUI_ShowString(88,40,"mm",8,1);
delay_ms(5);
}
}
OLED例程包见厂家链接