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

相关推荐
可待电子单片机设计定制(论文)8 小时前
【51单片机】基于单片机的智能门禁系统设计
单片机·mongodb·51单片机
长安——归故李1 天前
51单片机彩灯控制与数码管结合
汇编·单片机·嵌入式硬件·青少年编程·c#·51单片机·硬件工程
二年级程序员1 天前
51单片机的五类指令(五)——位操作类指令
单片机·嵌入式硬件·51单片机
猫猫的小茶馆2 天前
【PCB工艺】软件是如何控制硬件的发展过程
开发语言·stm32·单片机·嵌入式硬件·mcu·51单片机·pcb工艺
电子艾号哲2 天前
51单片机总结
单片机·嵌入式硬件·51单片机
二年级程序员3 天前
51单片机的五类指令(一)——数据传送类指令
汇编·单片机·嵌入式硬件·51单片机
二年级程序员3 天前
51单片机的五类指令(三)——逻辑操作类指令
单片机·嵌入式硬件·51单片机
二年级程序员3 天前
51单片机的五类指令(二)——算术运算类指令
单片机·嵌入式硬件·51单片机
F133168929574 天前
WD8001打奶棒芯片
stm32·单片机·嵌入式硬件·51单片机
猫猫的小茶馆5 天前
【PCB工艺】时序图(Timing Diagram)
stm32·单片机·嵌入式硬件·mcu·51单片机·pcb工艺