功能介绍:
0.本系统采用STC89C52作为单片机
1.导盲仗的上部和底部分别设置超声波传感器,利用超声波测距原理分别测得盲人面部和脚底离障碍物的距离,并将障碍信息通过语音播报传递给盲人
2.导盲杖设有光照传感器,利用光敏电阻测量环境光照,光照强度小于某个阈值时,自动打开导盲杖的照明LED灯带。以便引起行人及车辆注意。
3.在导盲杖的底部安装积水探测传感器,来检测积水,如果有积水则进行蜂鸣器报警,进而提醒盲人躲避积水。
4.导盲杖设有温度传感器,按键可语音播报当前温度,为盲人增添衣物提供参考。
5.采用DC002作为电源接口可直接输入5V给整个系统供电

原理图:
在这里插入图片描述

PCB:
在这里插入图片描述

主程序:

#include "main.h"

/*******************变量定义*********************/
sbit TRIG_1 = P2^4; //接口定义
sbit ECHO_1 = P2^5; //接口定义
sbit TRIG_2 = P1^1; //接口定义
sbit ECHO_2 = P1^0; //接口定义
float f_distance1 = 0; //距离1
float f_distance2 = 0; //距离2
int tempBuf = 0; //读取温度值
float temperature; //实际温度值

bit refreshFlag = 0;
bit sendFlag = 0;

unsigned int lightValue;
unsigned int waterValue;

char dis[32];

/********************************************************
函数名称:void mian()
函数作用:主函数
参数说明:
********************************************************/
void main()
{

    BUZZER = ON;
    LED = ON;
    DelayS(1);
    BUZZER = OFF;
    LED = OFF;

    TRIG_1 = 0;
    TRIG_2 = 0;

    Timer0_Init(); //初始化定时器0
    Timer1_Init(); //初始化定时器1
    UART_Init(); //初始化串口

    DS18B20_Start();
    DS18B20_GetTemp(&tempBuf);
    temperature = (float)tempBuf * 0.0625; //温度值转换

    while (1) //死循环
    {

        if (refreshFlag == 1)
        {
            refreshFlag = 0;
            Measuring();
            
            TR1 = 0;
            if (f_distance1 <= 1500) //上方探测小于1500mm
            {
                UART_SendStr("注意前方障碍物\r\n", 16); //发送数据
                DelayS(3);
            }
            
            if (f_distance2 <= 1500) //下方探测小于1500mm
            {
                UART_SendStr("注意脚下障碍物\r\n", 16); //发送数据
                DelayS(3);
            }
            
            TR1 = 1;
            
            if (lightValue < 40) //环境光低于40%
            {
                LED = ON;
            }
            else
            {
                LED = OFF;
            }

            if (waterValue > 10) //前方有积水
            {
                BUZZER = ON;
            }
            else
            {
                BUZZER = OFF;
            }

        }

        if (KEY_TEMP == 0) //语音播报温度按键按下
        {
            DelayMs(20);
            if (KEY_TEMP == 0)
            {
                TR1 = 0;
                DS18B20_Start();
                DS18B20_GetTemp(&tempBuf);
                temperature = (float)tempBuf * 0.0625; //温度值转换
                sprintf(dis, "当前温度%4.1f摄氏度\r\n", temperature); //打印温度值
                UART_SendStr(dis, 20);
                DelayS(2);
                TR1 = 1;
            }
            while (!KEY_TEMP)
                ;
        }
    }   
}

/************************* 定时器0初始化 *************************/
void Timer0_Init(void)
{
    TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
    TH0 = 0;
    TL0 = 0;
    EA = 1;  //总中断打开
    ET0 = 1; //定时器中断打开
    TR0 = 0; //定时器开关关闭
}

/************************* 定时器0中断 *************************/
void Timer0_Interrupt(void) interrupt 1
{

}

/************************* 定时器1初始化 *************************/
void Timer1_Init(void)
{
    TMOD |= 0x10; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响
    TH1 = (65536 - 9216) / 256; //重新赋值 10ms
    TL1 = (65536 - 9216) % 256;
    EA = 1;  //总中断打开
    ET1 = 1; //定时器中断打开
    TR1 = 1; //定时器开关打开
}

/************************* 定时器1中断 *************************/
void Timer1_Interrupt(void) interrupt 3
{
    static unsigned int time50ms  = 0;
	TL1 = 0x00;		//设置定时初始值
	TH1 = 0x4C;		//设置定时初始值 50ms
    time50ms++;

    if (time50ms > 20)
    {
        refreshFlag = 1; //显示标志
        time50ms = 0;
    }
}

void Measuring(void)
{
    static long cnt = 0; //定时器计数
    
    TR1 = 0;
    
    TRIG_1 = 1; //启动一次模块		//不可以使用其他终端 容易造成死循环
    DelayUs10x(1);
    TRIG_1 = 0;
    while (!ECHO_1)
        ;	 //当RX为零时等待
    TR0 = 1; //开启计数
    while (ECHO_1)
        ; //当RX为1计数并等待
    TR0 = 0;
    cnt = (long)(TH0 * 256 + TL0);
    TH0 = 0;
    TL0 = 0;
    f_distance1 = (float)cnt * 17 / 100.0 * 1.102; //算出来是mm (g_cnt * 340 / 2) / 1000.0 * 1.102;系数
    cnt = 0;


    
    TRIG_2 = 1; //启动一次模块		//不可以使用其他终端 容易造成死循环
    DelayUs10x(1);
    TRIG_2 = 0;
    while (!ECHO_2)
        ;	 //当RX为零时等待
    TR0 = 1; //开启计数
    while (ECHO_2)
        ; //当RX为1计数并等待
    TR0 = 0;
    cnt = (long)(TH0 * 256 + TL0);
    TH0 = 0;
    TL0 = 0;
    f_distance2 = (float)cnt * 17 / 100.0 * 1.102; //算出来是mm (g_cnt * 340 / 2) / 1000.0 * 1.102;系数
    cnt = 0;

    TR1 = 1;

    lightValue = 100 - 100 * ReadADC(AIN0_GND) / 255; //光照强度
    waterValue = 100 - 100 * ReadADC(AIN1_GND) / 255; //水滴值

}

/************************* 串口配置 *************************/
void UART_Init(void)
{
	SCON = 0x50;
	TH2 = 0xFF;
	TL2 = 0xDB;
	RCAP2H = 0xFF;  //(65536-(FOSC/32/BAUD))   BAUD = 9600 FOSC = 11059200
	RCAP2L = 0xDB;

	/*****************/
	TCLK = 1;
	RCLK = 1;
	C_T2 = 0;
	EXEN2 = 0;

	/*****************/
	TR2 = 1;
	ES   = 1; //打开串口中断
	EA   = 1; //打开总中断

}

/************************* 串口发送字节 *************************/
void UART_SendByte(unsigned char dat) //串口发送单字节数据
{
	unsigned char time_out;
    
	time_out = 0;
	SBUF = dat;						  //将数据放入SBUF中
	while ((!TI) && (time_out < 100)) //检测是否发送出去
	{
		time_out++;
		DelayUs10x(2);
	}		//未发送出去 进行短暂延时
	TI = 0; //清除ti标志
}

/************************* 串口发送字符串 *************************/
void UART_SendStr(unsigned char *s, unsigned char length)
{
	unsigned char num;
	num = 0x00;
	while (num < length) //发送长度对比
	{
		UART_SendByte(*s); //放松单字节数据
		s++;			  //指针++
		num++;			  //下一个++
	}
}

/************************* 串口中断 *************************/
void UART_Interrupt(void) interrupt 4 //串行中断服务程序
{
    if (RI)//判断是接收中断产生
    {
        RI = 0; //标志位清零
    }
}

仿真演示视频:
https://www.bilibili.com/video/BV1EY4y1578X/

实物演示视频:
https://www.bilibili.com/video/BV1HY4y1675F/

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐