使用超声波测距离并显示到STONE LCD模组上

超声波模组介绍

超声波测量距离的原理
超声波指向性强,在介质中传播的距离较远,因而超声波经常用于距离的测量,如测距仪和物 位测量仪等都可以通过超声波来实现。利用超声波检测往往比较迅速、方便、计算简单、易于做到实时控制,并且在测量精度方面能达到工业实用的要求,因此在移 动机器人的研制上也得到了广泛的应用。
超声波测距原理是在超声波发射装置发出超声波,它的根据是接收器接到超声波时的时间差,与雷达测距原理相似。 超声波发射器向某一方向发射超声波,在发射时刻的同时开始计时,超声波在空气中传播,途中碰到障碍物就立即返回来,超声波接收器收到反射波就立即停止计时。
(超声波在空气中的传播速度为340m/s,根据计时器记录的时间t(秒),就可以计算出发射点距障碍物的距离(s),即:s=340t/2)
HC-SR04介绍
HC-SR04是一款超声波发射接收模组,电子爱好者常用这款模组来做自己的试验。
本模块性能稳定,测度距离精确,模块高精度,盲区小。
主要技术参数:
使用电压:DC—5V
静态电流:小于2mA
电平输出:高5V
电平输出:底0V
感应角度:不大于15度
探测距离:2cm-450cm
高精度 :可达0.2cm

使用超声波测距离并显示到STONE LCD模组上_第1张图片
使用超声波测距离并显示到STONE LCD模组上_第2张图片
HC-SR04模组原理图

使用超声波测距离并显示到STONE LCD模组上_第3张图片
这张图片是HC-SR04超声波模组的原理图,对硬件原理感兴趣的朋友可以到网络上查找。
接线方式:VCC、trig(控制端)、echo(接收端)、GND

基本工作原理:

(1)采用IO口TRIG触发测距,给至少10us的高电平信号;
(2)模块自动发送8个40khz的方波,自动检测是否有信号返回;
(3)有信号返回,通过IO口ECHO输出一个高电平,高电平持续的时间就是超声波从发射到返回的时间。测试距离=(高电平时间*声速(340M/S))/2;
本模块使用方法简单,一个控制口发一个10US以上的高电平,就可以在接收口等待高电平输出.一有输出就可以开定时器计时,当此口变为低电平时就可以读定时器的值,此时就为此次测距的时间,方可算出距离.如此不断的周期测,即可以达到你测量的值。

应用场景

机器人避障
物体测距
液位检测
公共安防
停车场检测

使用MCU测试HC-SR04

STM32F103RCT6
STM32F103RCT6这款MCU功能很强大,下面是这个MCU的基本参数介绍:
系列:STM32F10X
内核:ARM-COTEX32
速度:72MHz
通讯接口:CAN,I2C,IrDA,LIN,SPI,UART/USART,USB
外围设备:DMA,电机控制PWM,PDR,POR,PVD,PWM,温度传感器,WDT
程序存储器容量:256KB
程序存储器类型:FLASH
RAM容量:48K
电压-电源(Vcc/Vdd):2 V ~ 3.6 V
振荡器:内部
工作温度:-40°C ~ 85°C
封装/外壳:64-LQFP

在这个项目中,我会用到STM32F103RCT6的UART,GPIO,Watch Dog, Timer.

下面的内容是这个项目的代码开发记录。

STM32使用的是Keil MDK软件开发,关于这个软件大家一定很熟悉,所以我就不介绍这个软件的安装方法了。
STM32可以通过J-LINK或者ST-LINK等仿真工具进行在线仿真调试,下面这张图片是我使用的STM32开发板:
使用超声波测距离并显示到STONE LCD模组上_第4张图片

通过串口助手显示测试结果

初始化时将trig和echo端口都置低,首先向给 trig发送至少10 us的高电平脉冲(模块自动向外发送8个40K的方波),然后等待,捕捉 echo 端输出上升沿,捕捉到上升沿的同时,打开定时器开始计时,再次等待捕捉echo的下降沿,当捕捉到下降沿,读出计时器的时间,这就是超声波在空气中运行的时间,按照S=(高电平时间*(340M/S))/2 就可以算出超声波到障碍物的距离。
根据这个思路,我们就可以写出简单的测试代码了。
使用超声波测距离并显示到STONE LCD模组上_第5张图片
使用超声波测距离并显示到STONE LCD模组上_第6张图片
我们可以看到串口返回的测量结果。

TFT-LCD显示模组

LCD模组选用的是STONE STVC050WT,这款显示模组使用起来非常方便,前面我们是通过串口来显示超声波测量的距离,而STONE的LCD模组也是通过UART来接收数据并显示到模组中的。这个过程只需要在MCU中做一个简单的协议封装就可以了。

STONE STVC050WT-01

使用超声波测距离并显示到STONE LCD模组上_第7张图片
使用超声波测距离并显示到STONE LCD模组上_第8张图片

简介

STVC050WT-01是TFT显示器和触摸控制器。它包括处理器,控制程序,驱动程序,闪存,RS232/RS485/TTL端口,触摸屏、电源等,是一个功能强大的显示系统
操作系统简单,可由任意单片机控制。STVC050WT-01可用于执行所有基本功能,如文本显示、图像显示、曲线显示、触摸功能、视音频功能等。的用户界面可以更加丰富和多样。闪存可以存储你的数据,配置文件和图片等。
-内置Cortex CPU和驱动
-可用任何单片机来控制
-显示图片/文字/曲线

  • 65536彩色TFT显示
    -有/没有触摸屏
  • RS232/ RS485/ TTL UART接口和USB端口
    -宽电压范围
    -易于使用!强大的功能!节省成本和时间!
    **

工作原理

**
智能TFT-LCD模块通过命令与客户的MCU通信(十六进制代码),然后MCU将控制其连接的设备按照接收到的命令工作。
使用超声波测距离并显示到STONE LCD模组上_第9张图片

开发步骤
使用STONE的TFT-LCD模块只需3个步骤:

  1. 设计一组漂亮的“图形用户界面”。
  2. 通过RS232, RS485或TTL直接连接客户的MCU。即插即用。
    3.编写一个简单的程序,由单片机通过命令控制TFT-LCD模块。(十六进制代码)。
    TFT液晶模块串口命令帧由5个数据块组成,所有的串口命令或数据都用十六进制格式表示。数据传输
    在MSB的方式。例如,对于0x1234,首先发送0x12,然后发送0x34。

STONE显示屏广泛应用于各种工业领域

医疗美容设备
工程机械及车辆设备
电子仪器
工业控制系统
电力行业
民用电子设备
自动化设备
交通

TOOL软件的使用

目前STONE提供的TOOL软件最新版本是TOOL2019,打开这个软件新建项目,然后导入之前设计好的UI显示图片,再添加自己的按键、文本显示框等。关于这个软件的使用,STONE官网有非常完善的教程,感兴趣的朋友可以点击下面的网页链接:
https://www.stoneitech.com/support/download/video

LCD模组的UI图片设计
可以使用Photoshop软件或者其他图片设计软件来设置UI界面,我设计的界面如下:
使用超声波测距离并显示到STONE LCD模组上_第10张图片

利用TOOL2019软件设生成LCD模组配置文件

使用超声波测距离并显示到STONE LCD模组上_第11张图片
点击箭头所指的按钮就可以生成配置文件,然后把配置文件下载到显示模组中就可以显示出我们设计的UI界面了。
这部分的内容和教程我就不详细介绍了,大家可以到STONE官网去下载到很详细的教程。

项目实施过程

这个demo的功能比较简单,主要有以下两点:
1、显示超声波模组测试到的距离
2、通过显示屏的“+”和“-”按钮修改刷新时间

硬件连接的可靠性
硬件接线比较简单,可以参考下面这张图片的连接方式:
使用超声波测距离并显示到STONE LCD模组上_第12张图片

STM32单片机程序

STM32单片机驱动HC-SR04的程序可以在网络上下载到,这里我也是使用了网友提供的demo例程去修改的。

外设资源使用情况

单片机外设只使用到了两个GPIO引脚(trig、echo)和一个Timer。另外还需要一个UART与STONE显示屏通讯。
程序初始化时将trig和echo端口都配置成低电平输出,首先给 trig输出至少10 us的高电平脉冲(模块自动向外发送8个40K的方波),然后等待,捕捉 echo 端输出上升沿,捕捉到上升沿的同时,打开timer并且开始计时,再次等待捕捉echo的下降沿,当捕捉到下降沿,读出Timer的时间,这就是超声波在空气中运行的时间,按照S=(高电平时间*(340M/S))/2 就可以算出超声波到障碍物的距离。

HC-SR04算法源码

void EXTI9_5_IRQHandler(void)
{
	static u8 flag_Sta = 0;
	if(EXTI_GetITStatus(EXTI_Line5) != RESET)		
	{
		EXTI_ClearITPendingBit(EXTI_Line5);  
		if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==1)
		{
			 TIM_SetCounter(TIM6,0);	
			 flag_Sta=1;
			 TIM_Cmd(TIM6, ENABLE);     
		}
		else
		{
			TIM_Cmd(TIM6, DISABLE); 					
			if(flag_Sta)
			{		
				Distance = TIM_GetCounter(TIM6);
				Distance = Distance /29;
				if(Distance > 300)
					Distance = 300;
				Done = 1;
			}
			flag_Sta=0;
		}
	}
}
这是一个GPIO外部中断的Handler,最终通过获取Distance这个变量的值,就可以得到超声波模块测试出来的距离。
Main.c
#include "usart1.h"
#include "Sonic.h"
#include "SysTick.h"

#define DISPLYER_ADDR           0x05
#define CHANGE_TIME_ADDR        0x10
u8 data_send[8]=  {0xA5, 0x5A, 0x05, 0x82, 0x00, 0x00, 0x00,0x00};
extern u16  Distance;
extern u8  USART_RX_BUF[10];
extern u8 USART_RX_END;
extern u16 USART_RX_STA;
void UART1_Send_Array(u8 send_array[],unsigned char num)
{
        u8 i=0;  
        while(i=time_set)
		{
			time=0;
			data_send[5]=DISPLYER_ADDR;
			data_send[6] = Distance >> 8;//hight
			data_send[7] = Distance & 0x00ff;//low
			UART1_Send_Array(data_send,8);
		//	printf("The Distance is: %d centimetre\r\n",Distance);
		}
		if(USART_RX_END)
		{		
		 // UART1_Send_Array(USART_RX_BUF,8);
			switch (USART_RX_BUF[5])	
			{
				case CHANGE_TIME_ADDR:
					time_set=USART_RX_BUF[7]*10;
					break;
				default:
					USART_RX_END=0;
					USART_RX_STA=0;
					break;
			}
					USART_RX_END=0;
					USART_RX_STA=0;
		}
	}
}
/******************* (C) COPYRIGHT 2017 *****END OF FILE************/


Sonic.c
#include "Sonic.h"
/*******************************************************************************
*	Sonic  Init
*******************************************************************************/
u32  Distance = 0;
u8   Done;
u32 __IO time_1ms = 0;

void TIM6_Init(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  //NVIC_InitTypeDef 		   NVIC_InitStructure;
  /* TIM6 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 0xFFFF; 
	TIM_TimeBaseStructure.TIM_Prescaler = 142;          //144£¬500K
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure);
  TIM_ITConfig(TIM6, TIM_IT_Update, DISABLE);	
	TIM_Cmd(TIM6, DISABLE);
}

void Sonic_Init(void)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC| RCC_APB2Periph_AFIO,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;       
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;						//PC4 Trig
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode= GPIO_Mode_IPD;
	GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;           		//PC5 Echo
	GPIO_Init(GPIOC,&GPIO_InitStructure);   
	
	GPIO_WriteBit(GPIOC,GPIO_Pin_4,(BitAction)0); 			//trig
	
	//EXTI_DeInit();
	EXTI_ClearITPendingBit(EXTI_Line5);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);
	EXTI_InitStructure.EXTI_Line= EXTI_Line5; 
	EXTI_InitStructure.EXTI_Mode= EXTI_Mode_Interrupt; 
	EXTI_InitStructure.EXTI_Trigger= EXTI_Trigger_Rising_Falling;
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;
  EXTI_Init(&EXTI_InitStructure);
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority= 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority= 0;        
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;   
	NVIC_Init(&NVIC_InitStructure);
	
	Distance = 0;
	Done = 1;
}

void Sonic_Trig(void)
{
	u16 i = 0;
	if((Done == 1)&&(time_1ms > 100))
	{
		time_1ms = 0;
		GPIO_WriteBit(GPIOC,GPIO_Pin_4,(BitAction)1);
		for(i=0;i<0xf0;i++);
		GPIO_WriteBit(GPIOC,GPIO_Pin_4,(BitAction)0); 
		Done = 0;
	}
}

void EXTI9_5_IRQHandler(void)
{
	static u8 flag_Sta = 0;
	if(EXTI_GetITStatus(EXTI_Line5) != RESET)		
	{
		EXTI_ClearITPendingBit(EXTI_Line5);  
		if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)==1)
		{
			 TIM_SetCounter(TIM6,0);	
			 flag_Sta=1;
			 TIM_Cmd(TIM6, ENABLE);     
		}
		else
		{
			TIM_Cmd(TIM6, DISABLE); 					
			if(flag_Sta)
			{		
				Distance = TIM_GetCounter(TIM6);
				Distance = Distance /29;
				if(Distance > 300)
					Distance = 300;
				Done = 1;
			}
			flag_Sta=0;
		}
	}
}

/*******************      (C) COPYRIGHT 2017       *END OF FILE************/

Uart
#include "usart1.h"


void USART1_Config(uint32_t uBaud)
{
	USART1_Configuration(uBaud);
	USART1_NVIC_Configuration();
}



void USART1_Configuration(uint32_t uBaud)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	/* config USART1 clock */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
	
	/* USART1 GPIO config */
	/* Configure USART1 Tx (PA.09) as alternate function push-pull */
	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);    
	/* Configure USART1 Rx (PA.10) as input floating */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	  
	/* USART1 mode config */
	USART_InitStructure.USART_BaudRate = uBaud;
	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);
}
void USART1_NVIC_Configuration(void)
{
	NVIC_InitTypeDef NVIC_InitStructure; 
	/* Configure the NVIC Preemption Priority Bits */  
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
	
	/* Enable the USARTy Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	 
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
}

int fputc(int ch, FILE *f)
{
	USART_SendData(USART1, (unsigned char) ch);
	while (!(USART1->SR & USART_FLAG_TXE));
	//while( USART_GetFlagStatus(USART1,USART_FLAG_TC)!= SET);	
	return (ch);
}
u16 USART_RX_STA=0;
u8 USART_RX_END=0;
u8 USART_RX_BUF[10]; 
void USART1_IRQHandler(void)
{  
	u8 Res;	
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
	{ 
		Res =USART_ReceiveData(USART1);
		  //printf("%x",USART_ReceiveData(USART1));
			// USART_SendData(USART1,Res);  
			if(USART_RX_END==0)
			{
				USART_RX_BUF[USART_RX_STA]=Res ;
				USART_RX_STA++;
				if(USART_RX_STA>=8)
				{
					USART_RX_END=1;
				}
			}
	}
}
Sys_tick
void SysTick_Handler(void)
{
	time_1ms++;
	time_120ms++;
	if(time_120ms>=80)
	{
		Sonic_Trig();				//50ms Trig Sonic
		time_120ms=0;
	}
	TimingDelay_Decrement();
}

整体运行效果
在硬件连接没有错误的情况下,把代码下载进STM32开发板中,就可以在STONE显示屏中看到超声波模组测量到的距离了,另外可以通过显示模组上面的“+”和“-”按钮调整距离刷新的时间。

使用超声波测距离并显示到STONE LCD模组上_第13张图片
查看原文:https://www.stoneitech.com/news/sharing/ultrasonic-module-test-with-stone-lcd-module.html

你可能感兴趣的:(工业电子,液晶面板)