新定义51单片机(RD8G37)实现测距测速仪

时间:2024-01-26 09:06:15

本文描述用新定义51单片机(RD8G37)+超声波一体测距传感器实现简单的测距测速仪。

 9278bb850bb44edab90cb36a83ce4264.jpg

测距仪演示效果

 

新定义RD8G37Q48RJ开发板

051393b63f7b4bf0a258e947fbe23cc8.jpeg

超声波测距模块: 

8e5c3abfe06f4a7d80e23122651b14c5.png

8位并口屏

fa276aa0bc324c54bf022c22d4c27aaf.jpg

 

1、main.c


unsigned short timeConsuming=0;	
unsigned int oldDistance;

void rectClearScreen(void);

void updateDisplay(void)
{
    unsigned int d[2];
	float v,dis;
    char buf[8]={0};
    memset(buf, '0', 8);

    Measure_Distance(d);
	dis=((float)d[0])/1000;
    sprintf(buf,"%0.f2d",dis); // 获取当前秒 
    buf[4]='\0';		
		if(d[0]<500){
			//rectClearScreen();
			 GUI_WriteASCII_BIG(6,60,buf,VGA_YELLOW,VGA_RED);
		}
		else GUI_WriteASCII_BIG(6,60,buf,VGA_WHITE,VGA_BLACK);
		
		if(oldDistance>d[0])
			v=((float)(oldDistance-d[0]))/d[1];
		else v=(d[0]-oldDistance)/d[1];
		
	sprintf(buf,"%0.2f",v); // 获取当前秒 
	buf[4]='\0';
    GUI_WriteASCII(150,60,buf,VGA_Mint,VGA_BLACK);
    		
	oldDistance=d[0];
    
}

void rectClearScreen(void)
{
	uint8_t i;
	setColor(VGA_RED);
	for(i=0;i<30;i+=3)
	{
		drawRect(i+6,i*176/220+60,214-i,110-i*176/220);
	}
}
void draw_interface(void)
{
    setColor(VGA_BLACK);
    clrScr(VGA_BLACK);
    setColor(VGA_Orange_Red);
    fillRect(5,5,105,83);
    setColor(VGA_Golden);
    fillRect(115,5,215,83);
    setColor(VGA_Medium_Blue);
    fillRect(5,93,105,171);
    setColor(VGA_Mint);
    fillRect(115,93,215,171);
    GUI_Write32CnChar(10,10,"测距测速仪",VGA_Orange_Red,VGA_BLACK);
    GUI_Write32CnChar(118,113,"新定义",VGA_WHITE,VGA_Dark_Green);
    GUI_WriteASCII(20,145,"RD8G37Q48RJ",VGA_Dark_Mineral_Blue,VGA_BLACK);
    setColor(VGA_BLACK);
    fillRect(5,53,215,111);

    GUI_Write32CnChar(102,72,"米",VGA_WHITE,VGA_BLACK);
    GUI_WriteASCII(150,60,"1.1",VGA_Mint,VGA_BLACK);
    GUI_WriteASCII(165,82,"m/s",VGA_WHITE,VGA_BLACK);

    setColor(0XC618);
    drawRoundRect(0,0,219,175);
}
void main(void)
{	
    /*<Generated by EasyCodeCube begin>*/
    /*<UserCodeStart>*//*<SinOne-Tag><36>*/
    IcResourceInit();
    InitLCD();
    setColor(VGA_BLACK);
	draw_interface();
    /*<UserCodeEnd>*//*<SinOne-Tag><36>*/
    /*<UserCodeStart>*//*<SinOne-Tag><4>*/
    /*****MainLoop*****/
    while(1)
    {
        /*<UserCodeStart>*//*<SinOne-Tag><14>*/
        /***User program***/
        updateDisplay();
        Delay(50000);
	
        /*<UserCodeEnd>*//*<SinOne-Tag><14>*/
        /*<Begin-Inserted by EasyCodeCube for Condition>*/
    }
    /*<UserCodeEnd>*//*<SinOne-Tag><4>*/
    /*<Generated by EasyCodeCube end>*/
}

2、传感器驱动

HC_SR04.c

#include "SC_Init.h"
#include "HC_SR04.h"

extern unsigned int time;

void Delay_us(unsigned short time)
{
	do
	{
		_nop_();_nop_();_nop_();_nop_();
		_nop_();_nop_();_nop_();_nop_();
		_nop_();_nop_();_nop_();_nop_();
	}while(--time);

}

void HC_GPIO_Init(void)  
{

	ResetTrig();   //Trig拉低,为输出脉冲触发信号做准备
}

void Measure_Distance(unsigned int* distance) //测距
{
	//unsigned int distance[2]=0;
	
	SetTrig();     //10us的脉冲触发信号
	Delay_us(10);
	ResetTrig();
	while(HC_ECHO==0); //等待Echo输出高电平
	time=0;               //开始记录回波信号脉宽
	while(HC_ECHO==1); //等待Echo输出低电平	   
	distance[0]=time*1.7;//根据声速和时间计算距离,即distance=time*340/2/100
	distance[1]=time;
	/*
			关于分辨力(mm):
					定时器每次对time加1是10us,10us=0.01ms,340m/s=340mm/ms
					计算距离时,最小分辨力为:0.01(ms) * 340(mm/ms) / 2 = 1.7(mm)
					小于模块标准精度3mm,故测距结果十分精准
	*/
	return ; //返回距离,单位mm
}

HC_SR04.h

#ifndef _HC_SR04_H_
#define _HC_SR04_H_



#define HC_TRIG	P21
#define HC_ECHO	P20
#define SetTrig()    HC_TRIG=1
#define ResetTrig()  HC_TRIG=0
//#define ReadEcho()   GPIO_ReadPin(CW_GPIOB,GPIO_PIN_9)

void HC_GPIO_Init(void);
void Measure_Distance(unsigned int* distance);

#endif

3、初始化和中断

SC_Init.c,

初始化8位并口屏GPIO,TIMER0。

TIMER0设置为10us中断一次,做为距离传感器的测量时间最小单位。

void SC_Init(void)
{
	//Forbid editing areas before the following label !!!
	SC_GPIO_Init();
	SC_OPTION_Init();
	SC_TIM0_Init();
	/*write initial function here*/	
	EA = 1;	
}

/*****************************************************
*函数名称: SC_GPIO_Init
*函数功能: GPIO初始化函数
*入口参数:void
*出口参数:void
*****************************************************/
void SC_GPIO_Init(void)
{
	//Forbid editing areas before the following label !!!
	GPIO_Init(GPIO3, GPIO_PIN_6,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_5,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_4,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_3,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_2,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_1,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO3, GPIO_PIN_0,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO1, GPIO_PIN_0,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO2, GPIO_PIN_0,GPIO_MODE_IN_HI);
	GPIO_Init(GPIO2, GPIO_PIN_1,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO0, GPIO_PIN_4,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO0, GPIO_PIN_5,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO0, GPIO_PIN_6,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO5, GPIO_PIN_1,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO5, GPIO_PIN_5,GPIO_MODE_OUT_PP);
	GPIO_Init(GPIO4, GPIO_PIN_7,GPIO_MODE_OUT_PP);
	/*GPIO_Init write here*/		
}

/*****************************************************
*函数名称: SC_TIM0_Init
*函数功能: TIMER0初始化函数
*入口参数:void
*出口参数:void 
*****************************************************/
void SC_TIM0_Init(void)
{
	//Forbid editing areas before the following label !!!
	TIM0_TimeBaseInit(TIM0_PRESSEL_FSYS_D12,TIM0_MODE_TIMER);
	TIM0_WorkModeConfig(TIM0_WORK_MODE2,229, 0);
	TIM0_ITConfig(ENABLE,LOW);
	TIM0_Cmd(ENABLE);
	/*TIM0_Init write here*/		
}

SC_it.c

TIMER0中断,每次中断计数加1。

void Timer0Interrupt()		interrupt 1			   
{
    /*TIM0_it write here begin*/
    //Forbid editing areas between the labels !!!
    /*TIM0_it write here*/
    /*<Generated by EasyCodeCube begin>*/
    /*<UserCodeStart>*//*<SinOne-Tag><55>*/
    //Timer0Interrupt
    {
        /*<UserCodeStart>*//*<SinOne-Tag><15>*/
        /***User program***/
        time++;
        /*<UserCodeEnd>*//*<SinOne-Tag><15>*/
        /*<Begin-Inserted by EasyCodeCube for Condition>*/
    }
    /*<UserCodeEnd>*//*<SinOne-Tag><55>*/
    /*<Generated by EasyCodeCube end>*/
    /*Timer0Interrupt Flag Clear begin*/
    //Forbid editing areas between the labels !!!
    /*Timer0Interrupt Flag Clear end*/		
}

总结

1、程序中用了TIMER0,主要是TIMER0可以做到us级,可以使测距更准确。

2、HC_SR04传感器的算法是通用的。

3、RD8G37Q48是QFN封装,PCB封装引脚延长到3mm,可以用烙铁焊接。

4、HC_SR04传感器不能测太远距离,室内3米以内应该没问题。

5、所用屏幕为ST7775,220*176分辨率,8位并口屏。

6、工程的建立用的是EasyCodeCube.exe,主要实现了gpio和timer初始化。程序编写和下载用的是keil。