Project 4: Serial port printing ultrasonic distance measurement

Notice! ! ! ! Be sure to RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

Turn on the multiplexing function clock, although the multiplexing function is not used.

1. Basic knowledge of serial communication

1. Serial communication interface of STM32.

        UART: Universal Asynchronous Transceiver.

       USART: Universal Synchronous Asynchronous Transceiver.

       Large-capacity STM32F10x series chips, including 3 USARTs and 2 UARTs.

2. Connection mode of communication pin RXD and TXD

3. Communication data flow process 

 

4. Serial port parameters that need to be configured 

 

5. Library functions related to serial ports 

 

 6. Library function initialization serial port steps

 6. Code

void uart_init1(u32 bound)
	{
    //GPIO define
    GPIO_InitTypeDef GPIO_InitStructure;
	  USART_InitTypeDef USART_InitStructure;
	  NVIC_InitTypeDef NVIC_InitStructure;
	 
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//open USART1,GPIOA clk
 	  USART_DeInit(USART1);  //release uart1
	 //USART1_TX   PA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//output mode
    GPIO_Init(GPIOA, &GPIO_InitStructure); // Set PA9
   
    //USART1_RX	  PA.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;//
    GPIO_Init(GPIOA, &GPIO_InitStructure);  //Set PA10

   //Usart1 NVIC

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=4 ;//
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//
	NVIC_Init(&NVIC_InitStructure);	//
  
   //USART1

	USART_InitStructure.USART_BaudRate = bound;//9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//
	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); //
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//
    USART_Cmd(USART1, ENABLE);                    //

}

2. Basic knowledge of ultrasound

Preface: SR04 is a sensor that uses ultrasonic characteristics to detect distance. It has two ultrasonic probes, which are used to transmit and receive ultrasonic waves respectively. Its measuring range is 3-500cm.

1. Basic principles

(1) First use the digital pin 13 of the STM32 to input a high-level signal of at least 10us to the TRIG pin to trigger the ranging function of the module.

(2) After the ranging function is triggered, the module will automatically send out 8 40kHz ultrasonic pulses, and automatically detect whether there is a signal return. This step is automatically completed inside the module.

(3) Once an echo signal is detected, the ECHO pin will output a high level. The duration of the high level is the time from the emission to the return of the ultrasonic wave. At this time, the timer can be used to obtain the high level time, and calculate the actual distance from the measured object. Formula: distance = high level time * speed of sound (340M/S)/2.

2. Circuit diagram

 

 3. Library function writing process

(1) Initialize the ultrasonic pin and turn on the corresponding pin clock.

(2) Since the timer needs to be used to measure the time of the returned high level, the timer (period is 1ms) needs to be initialized.

(3) From the formula: distance = high level time * speed of sound (340M/S)/2, so it is necessary to write a function to convert the measured time into distance, and measure five times to get the average value.

3. Overall programming process

1. Serial port initialization (interrupted), open the serial port.

2. Ultrasonic pin initialization.

3. Timer initialization (with interrupt).

4. Writing the ranging function

4. Main function output

Fourth, the code (detailed comments)

main.c

#include "motor.h"
#include "stdio.h"
#include "delay.h"
#include "stm32f10x.h"
#include "followline.h"
#include "sys.h"
#include "ultrasonic.h"

u8 UART3_data,UART1_data;
u8 UART3_rcv[20],UART3_rcv_count;
u8 UART1_rcv[50],UART1_rcv_count,Uart1_finish;

int main(void)
{
	float length;
	delay_init();//延迟初始化
	uart_init1(9600);//串口初始化
	ultrasonic_gpio_init();//超声波管脚初始化
	ultrasonic_time2_init();//超声波定时器初始化
	
	while(1)
	{
		
    printf("start  work!!\n");
		length=transfer_ditigal();
		printf("distance:%fcm\n",length);
		delay_s(1);
		
	}
}

ultrasonic.c 

#include "ultrasonic.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"

int overcount;//计数变量

/************************超声波管脚初始化***************************************/
	
void ultrasonic_gpio_init(void)
{
	//超声波发送管脚
	
	//定义GPIO_A初始化的结构体
	GPIO_InitTypeDef GPIO_InitStruct_A;
	 //打开PA管脚的时钟
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	 //将管脚PB4特殊功能关掉
	 GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
  //	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);
	 //配置PA15的参数
	GPIO_InitStruct_A.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_InitStruct_A.GPIO_Pin=GPIO_Pin_15;
	GPIO_InitStruct_A.GPIO_Speed=GPIO_Speed_50MHz;
	 //初始化PA15管脚
	GPIO_Init(GPIOA, &GPIO_InitStruct_A);
	 //置PA15低位
	GPIO_ResetBits(GPIOA, GPIO_Pin_15);
	
	
	//超声波接收管脚
	
	//配置PA12的参数
  GPIO_InitStruct_A.GPIO_Mode=GPIO_Mode_IPD;
	GPIO_InitStruct_A.GPIO_Pin=GPIO_Pin_12;
	//初始化PA12管脚
	GPIO_Init(GPIOA, &GPIO_InitStruct_A);
	
}
/************************************************************************************************************/

/********************************超声使用定时器2初始化*******************************************************/
void ultrasonic_time2_init(void)
{

	//定义TIME_2初始化的结构体
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct_TIME2;
	//打开定时器2的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	//配置TIME_2的参数
	TIM_TimeBaseInitStruct_TIME2.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInitStruct_TIME2.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct_TIME2.TIM_Period=999;
	TIM_TimeBaseInitStruct_TIME2.TIM_Prescaler=71;
	//初始化TIME_2
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct_TIME2);
  //定义NVIC初始化的结构体
	NVIC_InitTypeDef NVIC_InitStruct;
	//中断分组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	//配置NVIC的参数
	NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;
	//中断NVIC的初始化
	NVIC_Init(&NVIC_InitStruct);
	//清除定时器TIME_2更新中断标志
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	//开启定时器TIME_2的中断
	TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
	 //使能定时器TIME_2
  //TIM_Cmd(TIM2,ENABLE );
	
}
/*************************************************************************************************************************/

/*********************************************距离测量函数*********************************************************************/
float transfer_ditigal(void)
{ 
 
  float length =0,sum=0;
  u16 time;
  unsigned int i=0;
/*测则5次数据计算—次平均值*/
	while(i!=5)
	{
    GPIO_SetBits(GPIOA,GPIO_Pin_15);//拉高信号,作为触发信号
		delay_us(20);//高电平信号超过10us
    GPIO_ResetBits(GPIOA,GPIO_Pin_15);
/*等待回响信号*/
   while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_12) ==RESET);
		TIM_Cmd(TIM2,ENABLE);//回响信号到来,开启定时器计数
    i+=1; //每收到一次回响信号+1收到5次就计算均值
    while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_12)== SET);//回响信号消失
		TIM_Cmd(TIM2,DISABLE) ;//关闭定时器
    time=TIM_GetCounter(TIM2);//获取计TIw2数寄存器中的计数值,一边计算回响信号时间
    length=(time+overcount*1000)/58.0;//通过回响信号计算距离
     sum=length+sum;
    TIM2->CNT = 0; //将tiem2计数寄存器的计数值清零
		overcount = 0;//中断溢出次数清零
     delay_ms(1);
	}
    length =sum/5;
	  return length;//距离作为函数返回值
}
/**********************************************************************************************************************/


void TIM2_IRQHandler()   //TIM2中断
{    
    if (TIM_GetITStatus(TIM2, TIM_IT_Update))//检查TIM2更新中断发生与否
        {
						 TIM_ClearITPendingBit(TIM2, TIM_IT_Update);//清除TIM2更新中断标志 
					   overcount++;
				}
}

ultrasonic.h

#ifndef __ULTRASONIC_H
#define __ULTRASONIC_H

#include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"
#include "delay.h"
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"

float transfer_ditigal(void);//距离展示
void ultrasonic_gpio_init(void);//超声波管脚初始化
void ultrasonic_time2_init(void);//超声波定时器初始化

#endif

usart.c

#include "sys.h"
#include "ultrasonic.h"
#include "stdio.h"
#include "sys.h"
#include "usart.h"
extern u8 UART3_data,UART1_data;
extern u8 UART3_rcv[20],UART3_rcv_count;
extern u8 UART1_rcv[50],UART1_rcv_count,Uart1_finish;
//uart1 
//bound:9600

//加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
//标准库需要的支持函数                 
struct __FILE 
{ 
	int handle; 

}; 

FILE __stdout;       
//定义_sys_exit()以避免使用半主机模式  
  
void _sys_exit (int  x) 
{ 
	x = x; 
} 
//重定义fputc函数 
int fputc(int ch, FILE *f)
{      
	  while((USART1->SR&0X40)==0)
			;                    //循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
	  return ch;
}
#endif 

void uart_init1(u32 bound)
	{
    //GPIO define
    GPIO_InitTypeDef GPIO_InitStructure;
	  USART_InitTypeDef USART_InitStructure;
	  NVIC_InitTypeDef NVIC_InitStructure;
	 
	  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE);	//open USART1,GPIOA clk
 	  USART_DeInit(USART1);  //release uart1
	 //USART1_TX   PA.9
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//output mode
    GPIO_Init(GPIOA, &GPIO_InitStructure); // Set PA9
   
    //USART1_RX	  PA.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;//
    GPIO_Init(GPIOA, &GPIO_InitStructure);  //Set PA10

   //Usart1 NVIC

  NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=4 ;//
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//
	NVIC_Init(&NVIC_InitStructure);	//
  
   //USART1

	USART_InitStructure.USART_BaudRate = bound;//9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//
	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); //
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//
    USART_Cmd(USART1, ENABLE);                    //

}

//uart3 
//bound:9600
void uart_init3(u32 bound){
    //GPIO
    GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	 
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);	//open USART3 clk
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	//open GPIOB clk
 	USART_DeInit(USART3);  //release uart3
	 //USART3_TX   PB.10
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB.10
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;	//output mode
    GPIO_Init(GPIOB, &GPIO_InitStructure); //configure PB10
   
    //USART3_RX	  PB.11
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//input mode
    GPIO_Init(GPIOB, &GPIO_InitStructure);  //configure PB11

   //Usart3 NVIC 

    NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=5 ;//
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;		//
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//
	NVIC_Init(&NVIC_InitStructure);	//
  
   //USART

	USART_InitStructure.USART_BaudRate = bound;//9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//data bit
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//stop bit
	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(USART3, &USART_InitStructure); //
    USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//
    USART_Cmd(USART3, ENABLE);                    // 

} 

void USART1_SendByByter(u8 Data)
{
	//
	USART_GetFlagStatus(USART1, USART_FLAG_TC);	
	USART_SendData(USART1, Data);
	while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);	
}

void USART3_SendByByter(u8 Data)
{
	//
	USART_GetFlagStatus(USART3, USART_FLAG_TC);	
	USART_SendData(USART3, Data);
	while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);	
}

void USART1_IRQHandler(void)                	//uart1 ISR
	{
		u8 Res;
		if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  //
		{   
		  Res =USART_ReceiveData(USART1);//(USART1->DR);	//
		  UART1_data=Res;	
		if(Res==0x7E && UART1_rcv_count==0)
		{
       UART1_rcv[UART1_rcv_count++]=Res;

    }
    else if(Res!=0x7E && UART1_rcv_count>0)
    {
      UART1_rcv[UART1_rcv_count++]=Res;
			
    }
    else if(Res==0x7E && UART1_rcv_count>0)
    {
       UART1_rcv[UART1_rcv_count++]=Res;
			 Uart1_finish=2;
		 }
    else
      ;	
	 }
 }		


void USART3_IRQHandler(void)                	//uart3 ISR
	{
		if(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)  //RX set
		{
		UART3_data=USART_ReceiveData(USART3);//(USART1->DR);	//
		UART3_rcv[UART3_rcv_count]=UART3_data;
		if(UART3_rcv_count<6) UART3_rcv_count++;
		
    } 
	}
	

sys.h

#ifndef __SYS_H
#define __SYS_H	
#include "stm32f10x.h"
//	 
//本程序只供学习使用,未经作者许可,不得用于其它任何用途
//ALIENTEK STM32开发板		   
//正点原子@ALIENTEK
//技术论坛:www.openedv.com
//修改日期:2012/8/18
//版本:V1.7
//版权所有,盗版必究。
//Copyright(C) 广州市星翼电子科技有限公司 2009-2019
//All rights reserved
// 	 

//0,不支持ucos
//1,支持ucos
#define SYSTEM_SUPPORT_OS		0		//定义系统文件夹是否支持UCOS
																	    
	 
//位带操作,实现51类似的GPIO控制功能
//具体实现思想,参考<<CM3权威指南>>第五章(87页~92页).
//IO口操作宏定义
#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//IO口操作,只对单一的IO口!
//确保n的值小于16!
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

void USART1_SendByByter(u8 Data);
void uart_init1(u32 bound);

#endif

5. Running results: 

Finally, Xiaobai's study notes, welcome to give advice.

Guess you like

Origin blog.csdn.net/qq_47541315/article/details/120079648