目录
期末我们开设了感知技术实习,两人一小组,我们组分到的题目为超声波测距。从电路设计到焊板子,检测,再到写程序,收获不少。
一、STM32F103RCT6电路图
单片机电路不由我们设计,我们只需要将响应的元件焊上去就行了。但是看电路图真的很重要(
二、使用元器件
1.HC-SR04超声波测传感器初始化
传感器hc-rs04.c:(库函数是用的正点原子的)
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "led.h"
#include "key.h"
#include "lcd.h"
#include "hcsr04.h"
#define HCSR04_PORT GPIOA
#define HCSR04_CLK RCC_APB2Periph_GPIOA
#define HCSR04_TRIG GPIO_Pin_3
#define HCSR04_ECHO GPIO_Pin_2
u16 msHcCount = 0;
void Hcsr04Init(){
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(HCSR04_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin =HCSR04_TRIG;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_TRIG);
GPIO_InitStructure.GPIO_Pin = HCSR04_ECHO;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(HCSR04_PORT, &GPIO_InitStructure);
GPIO_ResetBits(HCSR04_PORT,HCSR04_ECHO);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
TIM_DeInit(TIM2);//1000*72/72000000
TIM_TimeBaseStructure.TIM_Period = (1000-1);
TIM_TimeBaseStructure.TIM_Prescaler =(72-1);
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);
hcsr04_NVIC();
TIM_Cmd(TIM4,DISABLE);
}
static void OpenTimerForHc(){
TIM_SetCounter(TIM4,0);
msHcCount = 0;
TIM_Cmd(TIM4, ENABLE);
}
static void CloseTimerForHc()
{
TIM_Cmd(TIM4, DISABLE);
}
void hcsr04_NVIC()
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void TIM4_IRQHandler(void)
{
if (TIM_GetITStatus(TIM4, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM4, TIM_IT_Update );
msHcCount++;
}
}
u32 GetEchoTimer(void)
{
u32 t = 0;
t = msHcCount*1000;
t += TIM_GetCounter(TIM4);
TIM4->CNT = 0;
delay_ms(50);
return t;
}
float Hcsr04GetLength(void)
{
u32 t = 0;
int i = 0;
float lengthTemp = 0;
float sum = 0;
while(i!=5)
{
TRIG_Send = 1;
delay_us(20);
TRIG_Send = 0;
while(ECHO_Reci == 0);
OpenTimerForHc();
i = i + 1;
while(ECHO_Reci == 1);
CloseTimerForHc();
t = GetEchoTimer();
lengthTemp = ((float)t/58.0);//cm
sum = lengthTemp + sum ;
}
lengthTemp = sum/5.0;
return lengthTemp;
}
hc-rs04.h:
#ifndef __HC_H
#define __HC_H
#include "sys.h"
void hcsr04_NVIC(void);
void Hcsr04Init(void);
static void OpenTimerForHc(void);
static void CloseTimerForHc(void);
void TIM4_IRQHandler(void);
u32 GetEchoTimer(void);
float Hcsr04GetLength(void);
#endif
2.LCD1602的初始化
这东西搞了我半天,实在是太坑了,一开始写完代码初始化后lcd只亮没有显示任何东西,我就一直以为是代码问题,最后看到电路图
这里是有个滑动变阻,用来调节lcd显示的对比度,用螺丝刀扭动R22直到有显示为止
lcd1602.c:
#include "lcd1602.h"
#include "delay.h"
#include "sys.h"
void gpio_config()
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC|RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOC, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|
GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 ;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
void lcd_write_com(u8 com){
EN_CLR;
delay_us(1);
RS_CLR;
delay_us(1);
RW_CLR;
delay_us(10);
GPIOC->ODR = (GPIOC->ODR&0xFF00)|com;;
//GPIO_Write(GPIOC,com);
delay_us(400);
EN_SET;
delay_us(400);
EN_CLR;
delay_us(300);
}
void lcd_write_ascii(u8 ascii){
EN_CLR;
delay_us(1);
RS_SET;
delay_us(1);
RW_CLR;
delay_us(10);
GPIOC->ODR = (GPIOC->ODR&0xFF00)|ascii;
//GPIO_Write(GPIOC,ascii);
delay_us(300);
EN_SET;
delay_us(400);
EN_CLR;
delay_us(300);
}
void lcd_write_char(u8 x,u8 y,u8 data){
if(y==0){
lcd_write_com(0x80+x);
}
else{
lcd_write_com(0xc0+x);
}
lcd_write_ascii(data);
delay_us(500);
}
void lcd_write_string(u8 x,u8 y,u8* str){
if(y==0)
lcd_write_com(0x80+x);
else
lcd_write_com(0xc0+x);
while(*str){
lcd_write_ascii(*str);
str++;
delay_us(500);
}
}
void lcd_clear(){
lcd_write_com(0x01);
delay_ms(5);
}
void lcd_init(){
delay_ms(100);
lcd_write_com(0x38);
delay_ms(10);
lcd_write_com(0x38);
delay_ms(10);
lcd_write_com(0x38);
delay_ms(10);
lcd_write_com(0x38);
delay_ms(10);
lcd_write_com(0x08);
delay_ms(10);
lcd_write_com(0x01);
delay_ms(10);
lcd_write_com(0x06);
delay_ms(10);
lcd_write_com(0x0c);
delay_ms(10);
}
lcd1602.h:
#ifndef __LCD1602_H
#define __LCD1602_H
#include "stm32f10x.h"
#define RS_SET GPIO_SetBits(GPIOC,GPIO_Pin_8)
#define RS_CLR GPIO_ResetBits(GPIOC,GPIO_Pin_8)
#define RW_CLR GPIO_ResetBits(GPIOC,GPIO_Pin_9)
#define RW_SET GPIO_SetBits(GPIOC,GPIO_Pin_9)
#define EN_CLR GPIO_ResetBits(GPIOB,GPIO_Pin_1)
#define EN_SET GPIO_SetBits(GPIOB,GPIO_Pin_1)
void lcd_write_char(u8 x,u8 y,u8 data);
void lcd_write_string(u8 x,u8 y,u8* str);
void lcd_init(void);
void gpio_config(void);
#endif
mian.c:
#include "delay.h"
#include "sys.h"
#include "hcsr04.h"
#include "lcd1602.h"
#include "usart.h"
u8 u1buffer[4]={0};
static void LCD_Disp(u16 u1);
static void user_init()
{
lcd_write_string(0,0,(u8*)"DIST= cm");
}
int main(){
u16 u1;
u16 distance=0.0;
user_init();
delay_init();
NVIC_Configuration();
uart_init(115200);
LCD_GPIO_Init();//lcd的引脚初始化一定要在lcd初始化之前,很重要
lcd_init();
Hcsr04Init();
while(1){
distance = Hcsr04GetLength();
u1=distance;
LCD_Disp(u1);
}
}
static void LCD_Disp(u16 u1)
{
u1buffer[0] = u1/1000;
u1buffer[1] = u1%1000/100;
u1buffer[2] = u1%100/10;
u1buffer[3] = u1%10;
lcd_write_char(6,0,u1buffer[0]+0X30);
lcd_write_char(7,0,u1buffer[1]+0X30);
lcd_write_char(8,0,u1buffer[2]+0X30);
lcd_write_char(9,0,u1buffer[3]+0X30);
}
总结
最后成果,本人水平有限,如有错误请大家批评指正 !