摘要:通信引脚与连接方式通信数据流动过程需要配置的串口参数与串口相关的的库函数库函数初始化串口步骤代码二超声波基础知识前言是利用超声波特性检测距离的传感器。其带有两个超声波探头,分别用作发射和接收超声波。
注意!!!!一定要 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
打开复用功能时钟,虽然没用复用功能。
一、串口通信基础知识
1、STM32的串口通信接口 。
UART:通用异步收发器 。
USART:通用同步异步收发器 。
大容量STM32F10x系列芯片,包含3个USART和2个UART。
2、通信引脚RXD与TXD连接方式
3、通信数据流动过程
4、需要配置的串口参数
5、与串口相关的的库函数
6、库函数初始化串口步骤
6、代码
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); //}
二、超声波基础知识
前言:SR04是利用超声波特性检测距离的传感器。其带有两个超声波探头,分别用作发射和接收超声波。其测量的范围是3-500cm。
1、基本原理
(1)先使用STM32的数字引脚13向TRIG脚输入至少10us的高电平信号,触发模块的测距功能。
(2)测距功能触发后,模块将自动发出 8 个 40kHz 的超声波脉冲,并自动检测是否有信号返回,这一步由模块内部自动完成。
(3)一旦检测到有回波信号则ECHO引脚会输出高电平。高电平持续的时间就是超声波从发射到返回的时间。此时可以使用定时器获取高电平的时间, 并计算出距被测物体的实际距离。公式: 距离=高电平时间*声速(340M/S)/2。
2、电路图
3、库函数编写流程
(1)初始化超声波引脚,打开相应管脚时钟。
(2)由于需要运用定时器测量返回的高电平的时间,所以需要对定时器(周期为1ms)进行初始化。
(3)由公式: 距离=高电平时间*声速(340M/S)/2,所以还需要编写一个函数把测量的时间转换为距离,测量五次取平均值。
三、总体编程流程
1、串口初始化(有中断),打开串口。
2、超声波管脚初始化。
3、定时器初始化(有中断)。
4、测距函数编写
4、主函数输出
四、代码(注释详细)
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:9600void 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控制功能//具体实现思想,参考<>第五章(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
五、运行结果:
最后,小白的学习笔记,欢迎大佬指教。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/119150.html
摘要:设计简介本设计是基于蓝牙的超声波无线测距的设计,主要实现以下功能实现通过测量当前温度值实现通过温差补偿法公式修改超声波在当前空气中的传播速度实现通过超声波传感器测量距离值。 设计简介: 本设计是基于蓝牙的超声波无线测距的设计,主要实现以下功能: ① 实现通过DS18B20测量当前温度值 ② ...
摘要:中央对齐模式向上计数时当时通道为无效电平,否则为有效电平向下计数时一旦通道为有效电平,否则为无效电平。一般来说,舵机接收的信号频率为,即周期为。 STM32——P...
摘要:超声波传感器,英文,既可以发射超声波,也可以接收超声波,它有一个重要作用,可以提前探测到附近的物体,而且通过声波速度,能够推算出附近物体离传感器的大概距离。 超声波...
摘要:由于担心会对主干网造成影响人们开始转向可以严格控制带宽要求的产品和技术比如多址发送。对网络造成的巨大负担也是多址发送发展的巨大动力因为多址发送是一种发送大量数据包的有效方法。什么是push技术? 所谓PUSH技术是一种基于客户服务器机制,由服务器主动的将信息发往客户端的技术。同传统的拉技术(PULL)相比,两者最为主要的区别在于前者的是由服务器主动发送信息,而后者则是由客户机主动请求信息。...
阅读 2544·2021-11-22 12:01
阅读 1071·2021-11-15 11:37
阅读 3657·2021-09-22 14:59
阅读 1716·2021-09-04 16:45
阅读 1365·2021-09-03 10:30
阅读 988·2021-08-11 11:18
阅读 2430·2019-08-30 10:53
阅读 1994·2019-08-29 15:13