51系列--人体身高体重BMI指数检测健康秤

本文主要介绍基于51单片机实现的人体身高体重BMI指数检测健康秤称设计(程序、电路图、PCB以及文档说明书见文末链接)

一、简介

本系统由STC89C52单片机、LCD1602液晶显示、按键、超声波测距、HX711称重传感器模块(0-1000KG)以及模块电源组成。

主要功能介绍如下:

(1)称重传感器进行人体称重,测量范围0-1000kg,实时显示在液晶上。

(2)超声波测量的距离,测量范围0-5m,显示在液晶上。

(3)按键按下,进行BMI值进行计算。BMI值等于重量除以身高的平方。

如果BMI低于18.5,则显示"过轻"字样、如果BMI在18.5-23.9之间,则显示"正常"字样、如果BMI高于24,则显示"过重"字样。

注意:称重/压力传感器上电时,保持没有重物,去皮功能。

二、详细设计方案

(1)电路图设计

单片机最小系统选用STC89C52单片机;称重传感器选用YZC-516C-1T称重传感器模块,并通过HX711专用的24位精度AD转换模块转换后传给单片机系统;身高测量选用的是HC-SR04超声传感器,基于超声波测距功能实现身高测量;

此外还包括LCD1602液晶显示电路、电源供电电路等,具体如下图所示

(2)PCB设计

PCB设计方案如下图所示,使用的是Altium designer软件

(3)源程序代码

c 复制代码
void main(void)
{
    TMOD|=0x01;		   //设T0为方式1,GATE=1;
    TH0=0;
    TL0=0;
    TIM2Inital();        //定时器初始化
    UART_Init(); //初始化串口

//    led_gl = 0;DelayMs(100);led_gl = 1;
    
    LCD_Init();//初始化液晶显示
    LCD_Clear();
    LCD_Write_String(0,0,"Init.. ");
    
    i = 5;startCheckWireLess=1;//启动检测无线
    while(i-- && wirelessFlag == 0) //此时判断是无线类型
    {UartSendString("ATE0\r\n");  DelayMs(100);}   
    startCheckWireLess=0;
    if(wirelessFlag == 1)
    {
        i = 50;while(i--){DelayMs(100);}//wifi启动 必须延时一定时间        
    //    UartSendString("AT+CWMODE_CUR=3\r\n");// 设置模式
    //    DelayMs(50); 
    //    UartSendString("AT+CWSAP=\"AUAISOUT000\",\"\",1,0\r\n");//设置网络名字及密码
    //    DelayMs(50);
    //    UartSendString("AT+CIPAP_CUR=\"10.10.10.11\"\r\n");//设置本机ip
    //    DelayMs(50);
    //    UartSendString("AT+CIPMODE=0\r\n");//设置ip模式
    //    DelayMs(50);
        UartSendString("AT+CIPMUX=1\r\n");//打开多连接
        DelayMs(50);
        UartSendString("AT+CIPSERVER=1,8080\r\n");//启动端口号
        DelayMs(50);   //以上作为服务端 局域网    
    }
	Weight_Maopi = HX711_Read();  	//读取去皮重量
	DelayMs(10);
	Weight_Maopi = HX711_Read();    

    while(1)
    {
        if(disFlag == 1)  //更新显示
        {
            disFlag = 0;

            csbDelater++;  //声音处理计数
            if(csbDelater>=4) //声音处理
            {
                csbDelater = 0;
                Trip=1;			   //启动一次模块		//不可以使用其他终端 容易造成死循环
                DelayUs2x(4);
                Trip=0;
                while(!Echo);		//当RX为零时等待
                TR0=1;			    //开启计数
                while(Echo);			//当RX为1计数并等待
                TR0=0;
                JlCoun=(long)(TH0*256+TL0);	 //计算数据
                JuLi=(float)(JlCoun*17)/100.0*1.08/1000;     //算出来是m 因为是11.0592M的晶振 11.0592/12
                if(JuLi > 9.99) JuLi = 8.88;//数据超出测量范围
            }

            readWeightFlag++;//计数
            if(readWeightFlag > 3)//达到一定时间 读取重量
            {
                readWeightFlag = 0;//清空标志

                Weight_Shiwu = HX711_Read();	 		//读取实物重量
                Weight_Shiwu = Weight_Maopi - Weight_Shiwu;// Weight_Shiwu - Weight_Maopi;		//获取净重

                if(Weight_Shiwu > 10)	//过滤错误		
                {	
                    Weight_Shiwu = (unsigned int)((float)Weight_Shiwu/430);	//kg计算实物的实际重量		该称重值 针对0-1000kg的传感器												
                }
                else
                {	Weight_Shiwu = 0;}
                if(Weight_Shiwu < 50 ) Weight_Shiwu = 0;	//体重过低清空               
            }
            
			if(key == 0 || getBMIFlag ==1)   //按键按下或者接收到获取命令
			{
                getBMIFlag =0;//清空标志
				if(JuLi > 0)BMI = Weight_Shiwu/10/JuLi/JuLi;	//防止出现除数为0//计算BMI
				else {BMI = 0;}			
			}

			sprintf(dis0,"H:%3.2fm G:%04.1fKg" ,JuLi,(float)Weight_Shiwu/10);//打印	显示	  
			LCD_Write_String(0,0,dis0);//打印显	
			if(BMI <= 18.5)//体重过轻
			{
				sprintf(dis1,"BMI:%4.1f  GQ   " ,BMI);//打印			
			}
			else if(BMI <= 23.9)  //体重合适
			{
				sprintf(dis1,"BMI:%4.1f  ZC   " ,BMI);//打印			
			}
			else	 //体重过重
			{
				sprintf(dis1,"BMI:%4.1f  GZ   " ,BMI);//打印				
			}	
			LCD_Write_String(0,1,dis1);//打印显           
            
            sendDataFlag++;
            if(sendDataFlag >= 8)//发送数据计数	发送蓝牙数据
            {
                sendDataFlag =	0;		//定时发送数据清空
                
                sprintf(dis0,"身高:%3.2fm 体重:%04.1fKg \r\n" ,JuLi,(float)Weight_Shiwu/10);         
                sprintf(dis0,"%sBMI值:%4.1f\r\n" , dis0 , BMI); 
                if(BMI <= 18.5)//体重过轻
                {
                    sprintf(dis0,"%s参考分析:体重过轻\r\n\r\n" , dis0 ); 		
                }
                else if(BMI <= 23.9)  //体重合适
                {
                    sprintf(dis0,"%s参考分析:体重正常\r\n\r\n" , dis0 ); 		
                }
                else	 //体重过重
                {
                    sprintf(dis0,"%s参考分析:体重过重\r\n\r\n" , dis0 ); 		
                }	                
                if(wirelessFlag == 0)UartSendString(dis0);			 //发送	 对应的 数据
                else My_ESP8266_SendStrStr(dis0);			 //发送	 对应的 数据                
            }            
        }
        if(uartTest == 1 && sendDataFlag >= 2)//接收到 测试命令
        {
            uartTest = 0;//取消标志
            if(wirelessFlag == 0)UartSendString("Test Ok!\r\n\r\n");			 //发送	 对应的 数据
            else My_ESP8266_SendStrStr("Test Ok!\r\n\r\n");			 //发送	 对应的 数据    
        }  
    }
}

void TIM2Inital(void)
{
    RCAP2H = (65536-50000)/256;//晶振12M 60ms 16bit 自动重载
    RCAP2L = (65536-50000)%256;
    ET2=1;                     //打开定时器中断
    EA=1;                      //打开总中断
    TR2=1;                     //打开定时器开关
}
void TIM2(void) interrupt 5 using 1//定时器2中断
{
    TF2=0;
    time_50ms++;
    if(time_50ms%2==0)		 //定时更新显示
    {
        disFlag = 1;//标志位置位
    }
    if(uartbusy>0)	   //串口数据采集处理
    {
        uartbusy--;   //说明刚刚接收到数据
    }
    else//长时间没有接受数据 情况接收参数重新接收
    {
        firstin =0;//接收启示标志
        Count=0;//接收计数
    }
}


void UART_Init(void)
{
    SCON  = 0x05;                // SCON: 模式 1, 8-bit UART, 使能接收
    TMOD = 0x02;               // TMOD: timer 1, mode 2, 8-bit 重装
    TH1   = 0xFD;               // TH1:  重装值 9600 波特率 晶振 11.0592MHz
    TL1 = TH1;
    TR1   = 1;                  // TR1:  timer 1 打开
    EA    = 1;                  //打开总中断
    ES    = 1;                  //打开串口中断
}


void uartSendByte(unsigned char dat)
{
    unsigned char time_out;
    time_out=0x00;
    SBUF = dat;              //将数据放入SBUF中
    while((!TI))  //检测是否发送出去
    {
        time_out++;    //未发送出去 进行短暂延时//**All notes can be deleted and modified**//
    }
}

void UartSendString(unsigned char *s)
{
    while(*s!='\0')// \0 表示字符串结束标志,
        //通过检测是否字符串末尾
    {
        uartSendByte(*s);//发送一个字节
        s++;//指向下一个
    }
}

void UART_SER (void) interrupt 4     //串行中断服务程序
{
    unsigned char midVal=0;
    unsigned char r_buf;
    static char rec01 = 0;
    if(RI)                        //判断是接收中断产生
    {
        RI=0;                      //标志位清零
        r_buf = SBUF;
        
        if(startCheckWireLess == 1 && wirelessFlag == 0)//启动检测无线
        {
            if(r_buf == 'O')rec01 = 1;
            else if (rec01 == 1 && r_buf == 'K')
            {
                wirelessFlag = 1; //1表示wifi
            }        
        }
        
        uartbusy = 20;
        if(r_buf=='*')		//接收到起始标志
        {
            firstin = 1; //接收标志成功
            Count = 0;
            tab[Count++]=r_buf;

        }
        else if(firstin == 1)	  //接收到其实标志成功
        {
            tab[Count++]=r_buf;
            if(tab[1] == '%')
            {   
                uartTest = 1;//接收到串口命令  
                firstin =0;
                Count=0;
            }            
            if(Count>=3) //*SM0# //设置值
            {
                if(tab[4] == '#')//**All notes can be deleted and modified**//
                {
                    if(tab[1] == 'B' && tab[2] == 'M')//检测到标志
                    {
                        getBMIFlag = 1;//获取BMI值
//                        setVal = (tab[3] - '0')*10 + (tab[4] - '0')*1; //提取数据     
                    }
                }
                firstin =0;
                Count=0;
            }
        }
    }
    if(TI)  TI=0; //如果是发送标志位,清零       
}

void My_ESP8266_SendStrStr( char *str)//发送数据
{
//    u8 i;
    unsigned char midLen=0;      //数据长度变量
    xdata unsigned char midTab[20]; //中间变量数组
    while(str[midLen]!='\0') midLen++;  //计算数据长度  
//    for(i=0;i<2;i++)
    {
        sprintf(midTab,"AT+CIPSEND = 0, %d \r \n",(unsigned int)midLen);	//打印
        UartSendString(midTab);//发送at命令
        DelayMs(10);//延时一下发送 等待相应
        UartSendString(str);//发送数据
//        UartSendString("\r\n");//发送数据
        DelayMs(6);//延时一下发送 等待相应
    }
}

三、实物图示

如下图所示为HC-SR04超声波传感器、YZC-516C-1T称重传感器模块以及HX711 AD转换模块

四、附完整资源链接

百度网盘链接: https://pan.baidu.com/s/1yyXPn0CIwzz8rfwZcrZDmg?pwd=usvi

提取码: usvi

相关推荐
兰_博2 小时前
51单片机驱动1602液晶显示
单片机·嵌入式硬件·51单片机
相醉为友4 小时前
在开发嵌入式系统时,尤其是处理大数时,会遇到取值范围的问题。51单片机通常没有内建大整数支持,因此我们需要采用不同的方法来解决这一问题
单片机·嵌入式硬件·51单片机
JaneZJW8 小时前
Proteus仿真——《51单片机AD和DA转换器的设计》
单片机·嵌入式硬件·51单片机·proteus
灵槐梦1 天前
【速成51单片机】2.点亮LED
c语言·开发语言·经验分享·笔记·单片机·51单片机
新晨单片机设计1 天前
【087】基于51单片机智能宠物喂食器【Proteus仿真+Keil程序+报告+原理图】
嵌入式硬件·51单片机·proteus·宠物·ad原理图
单片机学习之路1 天前
【C语言】结构
c语言·开发语言·stm32·单片机·51单片机
森旺电子2 天前
51单片机仿真摇号抽奖机源程序 12864液晶显示
单片机·嵌入式硬件·51单片机
gantengsheng2 天前
基于51单片机和OLED12864的小游戏《贪吃蛇》
单片机·嵌入式硬件·游戏·51单片机
析木不会编程3 天前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
IT_阿水5 天前
51单片机之RTC电子钟
嵌入式硬件·51单片机·数码管·rtc电子钟