超声波测距

#include "stm32f4xx.h"  
#include 

#define  TRIG_SET  	  GPIO_SetBits(GPIOB,GPIO_Pin_6)
#define  TRIG_RESET   GPIO_ResetBits(GPIOB,GPIO_Pin_6)
#define  ECHO_READ    GPIO_ReadInputDataBit(GPIOE,GPIO_Pin_6)

int fputc(int ch, FILE *f) 
{
	USART_SendData(USART1, ch);
	while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET ); //等待数据发送完成
	
	return ch;
}


void LED_Init(void)
{
	GPIO_InitTypeDef   GPIO_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);
	
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_OUT;			//输出模式
	GPIO_InitStructure.GPIO_OType	= GPIO_OType_PP;			//推挽输出
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_100MHz;		//输出速率
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;			//无上下拉
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_9;				//引脚编号
	GPIO_Init(GPIOF, &GPIO_InitStructure);
	
	GPIO_SetBits(GPIOF,GPIO_Pin_9); //默认不亮
}


void EXTI0_Init(void)
{
	EXTI_InitTypeDef   EXTI_InitStructure;
	GPIO_InitTypeDef   GPIO_InitStructure;
	NVIC_InitTypeDef   NVIC_InitStructure;

	/* Enable GPIOA clock  打开GPIOA外设时钟*/
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	/* Enable SYSCFG clock 打开SYSCFG外设时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);

	/* Configure PA0 pin as input floating 配置PA0引脚*/
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_IN;				//输入模式
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;			//无上下拉
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_0;				//引脚编号
	GPIO_Init(GPIOA, &GPIO_InitStructure);

	/* Connect EXTI Line0 to PA0 pin GPIO引脚和外部中断线建立映射关系*/
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);

	/* Configure EXTI Line0 配置外部中断线*/
	EXTI_InitStructure.EXTI_Line 	= EXTI_Line0;				//外部中断线0
	EXTI_InitStructure.EXTI_Mode 	= EXTI_Mode_Interrupt;		//中断模式
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  	//下降沿触发
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;					//使能外部中断线0
	EXTI_Init(&EXTI_InitStructure);

	/* Enable and set EXTI Line0 Interrupt 配置中断优先级*/
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;			//中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F;		//响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//使能通道
	NVIC_Init(&NVIC_InitStructure);	

}

//串口1的初始化
void USART1_Init(uint16_t  baud)
{
	GPIO_InitTypeDef   GPIO_InitStructure;
	NVIC_InitTypeDef   NVIC_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	//1.打开USRAT1外设时钟 + GPIOA外设时钟  PA9-U1_TX  PA10-U1_RX
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
	
	//2.配置GPIO引脚 PA9 PA10  引脚模式需要设置为复用模式
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_AF;				//复用模式
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;			//无上下拉
	GPIO_InitStructure.GPIO_OType 	= GPIO_OType_PP;			//推挽输出
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_100MHz;		//引脚速率	
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_9|GPIO_Pin_10;	//引脚编号
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	//3.把GPIO引脚的功能进行复用  复用为USART1  需要调用两次
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1);
	
	//4.配置USART1  波特率  停止位  数据位  校验位
	USART_InitStructure.USART_BaudRate = baud;						//波特率  9600bps
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;		//数据位  8bit
	USART_InitStructure.USART_StopBits = USART_StopBits_1;			//停止位  1bit
	USART_InitStructure.USART_Parity = USART_Parity_No;				//校验位  无
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; //无硬件流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
	USART_Init(USART1,&USART_InitStructure);
	
	//5.指定USART1的中断源  接收到数据就发生中断
	USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);
	
	//6.配置NVIC 指定中断通道+中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;			//中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;		//响应优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;				//使能通道
	NVIC_Init(&NVIC_InitStructure);	
	
	//7.打开串口
	USART_Cmd(USART1,ENABLE);
}

//系统定时器的初始化
void  SysTick_Init(void)
{
	//把168MHZ经过8分频 得到21MHZ  1000000us振荡21000000次  ---  1us振荡21次
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);
}


//延时微秒  不能超过798900us
void Delay_us(uint16_t nus)
{
	SysTick->CTRL &= ~(1<<0); 			// 关闭定时器
	SysTick->LOAD = (21*nus) - 1; 		// 设置重装载值 value-1
	SysTick->VAL  = 0; 					// 清空当前计数值
	SysTick->CTRL |= (1<<0); 			// 开启定时器  开始倒数
	while ( (SysTick->CTRL & 0x00010000)== 0 );// 等待倒数完成
	SysTick->CTRL = 0;					// 关闭定时器
	SysTick->VAL  = 0; 					// 清空当前计数值
}

//延时毫秒  不能超过798.9ms
void Delay_ms(uint16_t nms)
{
	SysTick->CTRL &= ~(1<<0); 			// 关闭定时器
	SysTick->LOAD = (21*1000*nms) - 1; 	// 设置重装载值 value-1
	SysTick->VAL  = 0; 					// 清空当前计数值
	SysTick->CTRL |= (1<<0); 			// 开启定时器  开始倒数
	while ( (SysTick->CTRL & 0x00010000)== 0 );// 等待倒数完成
	SysTick->CTRL = 0;					// 关闭定时器
	SysTick->VAL  = 0; 					// 清空当前计数值
}


//超声波初始化 TRIG-PB6  ECHO-PE6
void  SR04_Init(void)
{
	GPIO_InitTypeDef   GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB|RCC_AHB1Periph_GPIOE, ENABLE);
	
	GPIO_InitStructure.GPIO_Pin 	= GPIO_Pin_6;				//引脚编号
	
	//TRIG输出模式
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_OUT;			//输出模式
	GPIO_InitStructure.GPIO_OType	= GPIO_OType_PP;			//推挽输出
	GPIO_InitStructure.GPIO_Speed	= GPIO_Speed_100MHz;		//输出速率
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;			//无上下拉
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	//ECHO输入模式
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_IN;				//输入模式
	GPIO_InitStructure.GPIO_PuPd 	= GPIO_PuPd_NOPULL;			//无上下拉
	GPIO_Init(GPIOE, &GPIO_InitStructure);
	
	TRIG_RESET;
}

//获取距离
uint32_t SR04_GetDistance(void)
{
	uint32_t cnt=0;
	
	//1.TRIG输出至少10us的高电平
	TRIG_SET;
	Delay_us(15);
	TRIG_RESET;
	
	//2.等待ECHO引脚出现高电平
	while( ECHO_READ == 0 );
	
	//3.计算高电平持续的时间
	while( ECHO_READ == 1 )
	{
		Delay_us(9);
		cnt++;
	}
	
	cnt = cnt/2;
	
	return	cnt*3; //单位是mm

}	



int main()
{
	uint32_t distance=0;
	//1.硬件初始化
	USART1_Init(9600);
	SR04_Init();
	SysTick_Init();
	
	//2.进入死循环
	while(1)
	{
		distance = SR04_GetDistance(); //获得距离
		printf("distance is %d mm \n",distance);
		Delay_ms(500);
		
	}
}

//中断服务函数  不需要手动调用   尽量精简(尽量不要添加很长的延时)
void USART1_IRQHandler(void)
{
	uint16_t recv_data = 0;
	//检测中断是否发生
	if( USART_GetITStatus(USART1,USART_IT_RXNE) != RESET )
	{
		USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清除中断标志
		
		recv_data = USART_ReceiveData(USART1); //把接收到的数据保存到变量中
		
		USART_SendData(USART1,recv_data); //把收到的数据发送
		while( USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET ); //等待数据发送完成	
	}
}

你可能感兴趣的:(单片机,stm32,嵌入式硬件)