#include "stm32f10x.h"
#include "stdio.h"
static GPIO_InitTypeDef GPIO_InitStructure;
static USART_InitTypeDef USART_InitStructure;
#define PB5OUT(n) *(volatile uint32_t *)(0x42000000+((uint32_t)&GPIOB->ODR-0x40000000)*32+n*4)
#define PE0OUT(n) *(volatile uint32_t *)(0x42000000+((uint32_t)&GPIOE->ODR-0x40000000)*32+n*4)
#define PE2IN(n) *(volatile uint32_t *)(0x42000000+((uint32_t)&GPIOE->IDR-0x40000000)*32+n*4)
int fputc(int c, FILE * stream){
USART_SendData(USART1, c);
//判断有没有发送完毕
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
return c;
}
void led0(void){
//led0-->PB5
//使能端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
//初始化GPIO引脚
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;//高速响应
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_5);
}
void delay_ms(uint32_t n){
while(n--){
SysTick->CTRL=0; //关闭系统定时器,第0位:使能位,1为使能
SysTick->LOAD=(72000)-1;//配置计数值,因为计算机从0开始,所以减一
SysTick->VAL=0;//清空当前的值(标志位),定时器在计数时,标志位为0,当计数完毕时,标志位为1
SysTick->CTRL=5;//5=101 使能系统计时器,并且使用系统时钟
//第二位:时钟选择位,0=系统时钟/8,1=系统时钟
while((SysTick->CTRL&0x10000)==0);//等待计数到0
//第16位:计数到0则为1
}
SysTick->CTRL=0;
}
void delay_us(uint32_t n){
//us就不用循环了,会增加误差
SysTick->CTRL=0; //关闭系统定时器,第0位:使能位,1为使能
SysTick->LOAD=(72*n)-1;//配置计数值,因为计算机从0开始,所以减一
SysTick->VAL=0;//清空当前的值(标志位),定时器在计数时,标志位为0,当计数完毕时,标志位为1
SysTick->CTRL=5;//5=101 使能系统计时器,并且使用系统时钟
//第二位:时钟选择位,0=系统时钟/8,1=系统时钟
while((SysTick->CTRL&0x10000)==0);//等待计数到0
//第16位:计数到0则为1
SysTick->CTRL=0;
}
void supertrandsinit(void){
//外设排针选择PE0(trig输出)和PE2(echo输入)
//使能端口
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE, ENABLE);
//初始化GPIO引脚
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;//高速响应
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD;//下拉输入
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;//高速响应
GPIO_Init(GPIOE, &GPIO_InitStructure);
//PE0初始化状态为0(看时序图)
PE0OUT(0)=0;
}
//看时序图编程
int32_t sr04_get_distance(void){
int32_t t=0,d=0;
//先发出触发信号
PE0OUT(0)=1;
//持续10us以上才触发,所以进行延时
delay_us(20);
PE0OUT(0)=0;
//等待PE2出现高电平
while(PE2IN(2)==0){//0==0就进行循环,1==0说明等待的高电平来了,退出循环
/*为了防止出现高电平一直不出现(可能是因为硬件等等的原因)即为了防止一直卡在
这个循环里,所以加一个超时处理
*/
t++;
delay_us(1);
if(t>10000){
return -1;
}
}
//测量高电平的时间
t=0;
while(PE2IN(2)){
t++;
delay_us(9);//9us的距离,相当于3mm,3mm是超声波的精度
if(t>10000){
return -2;
}
}
//测量距离:由于测量的时间就是超声波从发射到返回的时间
d=(t/2)*3;
return d;
}
void usart1_init(uint32_t baud){
//串口PA9 ,PA10
//硬件时钟时钟打开
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
//使能串口1的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
//tx配置引脚的工作模式
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_9;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP; //设置成复用功能
GPIO_InitStructure.GPIO_Speed= GPIO_Speed_50MHz;//高速响应
GPIO_Init(GPIOA, &GPIO_InitStructure);
//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 = baud;//设置波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//8位数据位
USART_InitStructure.USART_StopBits = USART_StopBits_1;//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
USART_Cmd(USART1, ENABLE);
}
int main(){
int32_t d=0;
supertrandsinit();
usart1_init(115200);
led0();
while(1){
d=sr04_get_distance();
if(d>0){
//距离的合法性
if(d>=20&&d<=4000){
printf("distance=%u\r\n",d);
if(d<60){
PB5OUT(5)=0;
}else{
PB5OUT(5)=1;
}
}
}
delay_ms(3000);
}
}
微信扫码关注
更新实时通知