特别注意!
单独t-link只能提供3.3v电压!模块接5v电压只能收到3.3V。供电的时候请接上micro口!
模块介绍
HC-SR04超声波模块可提供2cm~400cm的距离感测功能,测量精度可以达到3mm。
通过声音340m/s * t / 2可以算出距离.
接线图
A9、A10串口可以选择ttl转usb淘宝十几块一个。B8、B9、5V、GND接在HC-SR04超声波模块
结合时序图
我们按照时序图从上到下从左到右进行查看,主要分成3块,按照我们的代码,第一块PB8默认低电平随后PB8发起高电平,接着模块内部会工作发送脉冲,同时检测PB9返回的高电平时间。
主要代码
这里有用到SYSTICK作为全局延时功能,USART1串口通信模块.
#include "stm32f10x.h"
#include "GPIOLIKE51.h"
#include "stdio.h"
static u8 fac_us=0; //us延时倍乘数
static u16 fac_ms=0; //ms延时倍乘数
int fputc( int ch, FILE *f ){
USART_SendData(USART1,(u8) ch );
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return ch;
}
//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init(){
SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); //选择外部时钟 HCLK/8
fac_us=SystemCoreClock/8000000; //为系统时钟的1/8
fac_ms=(u16)fac_us*1000; //非OS下,代表每个ms需要的systick时钟数
}
//SysTick 微秒计时器
void delay_us(uint32_t nus){
u32 temp;
SysTick->LOAD=nus*fac_us; //时间加载
SysTick->VAL=0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00; //清空计数器
}
//SysTick 毫秒计时器
void delay_ms(uint32_t nms){
u32 temp;
SysTick->LOAD=(u32)nms*fac_ms; //时间加载(SysTick->LOAD为24bit)
SysTick->VAL =0x00; //清空计数器
SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ; //开始倒数
do{
temp=SysTick->CTRL;
}while((temp&0x01)&&!(temp&(1<<16))); //等待时间到达
SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk; //关闭计数器
SysTick->VAL =0X00;
}
void USART1_init(){
GPIO_InitTypeDef GPIO_InitStructure;
//配置串口结构体
USART_InitTypeDef USART_InitStructure;
//NVIC结构体
NVIC_InitTypeDef NVIC_InitStructure;
// 打开功能复用IO时钟,用于串口通信
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//使能GPIO硬件时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//使能串口1硬件时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
/* 配置PA9和PA10为复用功能模式 */
//USART1_TX GPIOA.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; //复用推挽输出
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化GPIOA.10
USART_InitStructure.USART_BaudRate = 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); //初始化串口1
/* Configure the NVIC Preemption Priority Bits */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the USARTy Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure);
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //配置为接收中断
USART_Cmd(USART1, ENABLE); //使能串口1
}
/**
* 配置Gpio PB8为发送 PB9为返回
*/
void GPIOB_init(void){
GPIO_InitTypeDef GPIO_InitStruct;
/* GPIOB时钟初始化 */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_8; //发送电平引脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_Out_PP; //GPIO_Mode_Out_PP 推挽输出
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9; //返回电平引脚
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
int32_t sr04_get_destace(){
int32_t t = 0; //时间 us微秒
int32_t d = 0; //距离 mm毫米
PBout(8)=0;
//向PB8发送高电平
PBout(8) = 1;
//持续运行至少大于10_us
delay_us(20);
//向PB8发送低电平
PBout(8) = 0;
//循环等待PB9返回的高电平
while(PBin(9) == 0){
t++; //累计1微秒
delay_us(1);
if(t >= 1000000){
//超时返回-1
return -1;
}
}
//测量高电平时长
while(PBin(9)){
t++; //累计9微秒
delay_us(9); //声音速度340m/s 9us == 3mm
if(t >= 1000000){
//未检测高电平超时返回-2
return -2;
}
}
//计算距离 距离3mm乘以时间us除以2得出距离
d=3*t/2;
return d;
}
int main(void){
//距离mm
int32_t d = 0;
delay_init();
//串口初始化 TXD->PA9,RXD->PA10 接在ttl转usb记得反接
USART1_init();
//HC-SR04传感器相关初始化,使用的基础IO->输出PB8,接收PB9
GPIOB_init();
printf("distance:%dmm\r\n", d);
while(1)
{
d = sr04_get_destace();
if(d > 0){
//距离大于20mm且小于等于4m才会打印输出
if(d>=20 && d<=4000){
printf("distance:%dmm\r\n", d);
}
}
//延迟一秒
delay_ms(1000);
}
}
// "GPIOLIKE51.h"
#ifndef __GPIOLIKE51_H
#define __GPIOLIKE51_H
///#include <stm32f10x_lib.h>
//位带操作,实现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) //输入
#endif
串口打印配置: STM32重写fputc.