B50 - Children's Growth Management System Based on 51 MCU

Task

In view of the shortcomings of traditional children's height and weight measuring instruments, such as time-consuming measurement, large measurement error, and the inability to carry out historical records to facilitate viewing of children's recent height and weight to intuitively see the changes of children, further improvements have been made, and a child growth management based on a single-chip microcomputer is mainly introduced. system. It consists of two parts: Android phone APP and embedded hardware. The embedded hardware part is composed of power supply circuit, single-chip microcomputer minimum system circuit, LCD display circuit, ultrasonic module ranging circuit, weight measurement module circuit, and Bluetooth communication module circuit. Distance, weighing, saving measurement records and other functions, the Android APP part is written by QT development tools, and has functions such as graphical display of children's historical measurement data. This design integrates increasingly mature technologies such as ultrasound and sensors, and mainly realizes the collection, digital display and storage of children's height and weight data, and can easily see historical measurement data through Bluetooth and Android mobile phone connection, reaching The purpose of monitoring a child's development.

The system has a height detection module, a button acquisition module, and a weight detection module for information collection. The height detection module uses an ultrasonic sensor, which can avoid the influence of light intensity on height detection. The weight detection module uses a commonly used resistive bridge pressure sensor. HX711 high-precision digital-to-analog conversion chip is used to ensure the accuracy of detection. The output uses LCD1602 for visual display of information, and uses HC-05 Bluetooth module to meet the two-way communication with the mobile phone. The single-chip microcomputer of the Bluetooth module can receive the query command sent by the mobile phone, and can also send user information to the mobile phone according to the preset program after analyzing the command. Historical measurement data, complete two-way communication. The overall structure of the system is shown in Figure 2-1.
insert image description here
insert image description here

in kind

insert image description here
insert image description here

insert image description here

schematic diagram

insert image description here

hardware design

Weight detection module

The body weight data acquisition part is composed of a weighing sensor, signal amplification and A/D conversion part, and the signal amplification and A/D conversion part is mainly realized by a dedicated high-precision 24-bit AD conversion chip HX711. HX711 is a 24-bit A/D converter chip specially designed for high-precision load cells. Compared with other chips of the same type, this chip integrates the peripheral circuits required by other chips of the same type, including regulated power supply, on-chip clock oscillator, etc., and has the advantages of high integration, fast response speed, and strong anti-interference.
insert image description here

height detection module

The height detection module of this design is realized by ultrasonic ranging. The ultrasonic transmitting circuit is composed of an ultrasonic transmitting probe, and the P1.6 pin control signal of the single-chip microcomputer STC89C52RC is sent to the ultrasonic generator, and the ultrasonic wave emitted by the ultrasonic probe is directed to the obstacle. The principle of ultrasonic distance measurement is to continuously detect the echoes reflected by obstacles after encountering ultrasonic waves, so as to measure the time difference T between transmitting ultrasonic waves and receiving echoes, and then calculate the distance S=CXT/2, where C is Ultrasonic wave velocity is taken as 344m/s at room temperature. After the speed of sound is determined, as long as the round-trip time of the ultrasonic wave is measured, the distance can be obtained. STC89C52RC is used as the central processor, and a dedicated paired ultrasonic module is selected to perform mutual conversion between ultrasonic signals and electrical signals. Using the frequency selection characteristics of the ultrasonic sensor, the amplitude of the received ultrasonic signal is judged, so as to achieve the selection and matching of different distances. The purpose of the alarm.
insert image description here

Bluetooth communication module

This design uses the HC-05 Bluetooth serial communication module for wireless connection with the mobile phone. The wireless working frequency band of this module is 2.4GHz ISM performs data modulation and demodulation through GFSK. The maximum transmission power of this module is 4dBm, the receiving sensitivity is -85dBm, and the PCB antenna is mounted on the board, which can realize the wireless communication requirements at a distance of 10 meters. The module can configure the serial port baud rate, device name and other functions through AT commands, and can judge the current working status of the module through the onboard LED lights. This system uses the HC-05 Bluetooth module to connect to the corresponding pins P30 and P31 of the serial port of the STC89C52RC microcontroller to complete the serial communication. When the mobile phone is connected to the Bluetooth module, the communication function between the system and the mobile phone is completed, and the APP on the mobile phone sends corresponding The command is sent out through the Bluetooth of the mobile phone, and the HC-05 module can receive the information sent by the connected mobile phone Bluetooth and transmit the received information to the single-chip microcomputer through the serial port for the single-chip microcomputer to analyze the received command information. After the analysis is completed, according to the design of this system The status returns the corresponding feedback data to the Android phone via Bluetooth, and displays it for the user to check after being processed and analyzed by the mobile app.
insert image description here

power off memory module

AT24C02 is a 2K-bit serial CMOS E2PROM, which contains 256 8-bit bytes. CATALYST's advanced CMOS technology substantially reduces the power consumption of the device. The AT24C02 has a 16-byte page write buffer. The device operates through an IIC bus interface and has a dedicated write protection function. AT24C02 supports I2C, the bus data transmission protocol I2C, and the bus protocol stipulates that any device that transmits data to the bus is used as a transmitter. Any device that receives data from the bus is a receiver. Data transfers are controlled by the master which generates the serial clock and all start and stop signals. Both the master device and the slave device can be used as a transmitter or receiver, but the mode of transmitting data (sending or receiving) is controlled by the master device. Since A0, A1 and A2 can form eight situations of 000~111, that is, through the device address input terminal A0, A1 and A2 can connect up to 8 AT24C02 devices to the bus, and select devices through different configurations.
insert image description here

source program

main program flow

The main program of this design begins with the power-on initialization stage. The LCD1602 peripherals are configured as a normal display mode, and the corresponding power-on prompts are displayed, and then the serial port peripherals are initialized. STC89C52RC has only one serial port. Compared with the C51 model, the newly added timer 2 of STC89C52RC is used as the baud rate generator of the serial port for the first time, and is configured to generate a serial port baud rate of 9600bps, 8 data bits, and no parity bit mode. Then initialize the AT24C02 peripherals. After the power-off storage module is powered on, it will be detected whether the set value is stored in the set position. If not, the set value will be stored, and the data in other positions will be cleared to prevent data disorder. Case. The advantage of LCD is that it can give corresponding display prompts in time, and here it will display a prompt to determine whether it is a new or old single-chip microcomputer. After that, the HX711 weight detection and HC-SR04 height detection peripherals are initialized. After the initialization of various peripherals is completed, it enters the loop, and continues to collect information and display in the loop. In the normal detection interface, this design will determine whether the serial port has received an instruction. The instruction is the data sent to the design through the Bluetooth of the mobile phone. After receiving the data, the Bluetooth module on the design transmits the data to the microcontroller through the serial port. Corresponding analysis, to determine the mode of view command sent by the user on the mobile APP, to view the data of the user ID, whether to view the weight or height data, the microcontroller will read the corresponding data and send the data through the Bluetooth module. In normal mode, the height and weight data are detected and displayed on the LCD1602 display.
insert image description here

Data storage process

The storage program in this design is realized by pressing the button. When the user presses the button 1 after measuring the height and weight, the MCU enters the storage interface, and the LCD displays the user ID and height and weight data in this interface. The user can change the user ID by pressing the button 2 in this interface. After the change is completed, press Press key 3 to perform data storage. When storing data in this design, first read the data stored in the memory of the corresponding user ID in AT24C02. Each user ID is allocated 40 bytes, and the height and weight each occupy 20 bytes. Every two bytes form a data , because the memory is 8 bits and cannot store a value greater than 255, so two bytes are used to store a height or weight data. When the user reads the data corresponding to the ID, it is judged whether there is 0 data. If it exists, it means that the historical measurement record has not reached the full historical record, so the current measured height and weight data are stored in the position corresponding to the 0 data. If the full history record is reached, and there is no internal data of 0, discard the first data measured by the user ID, move the latest data back by one position, and free the last position to store the latest measurement data. After the data is stored, the write program that drives the AT24C02 writes the data into the memory space of the corresponding user ID.
insert image description here

Bluetooth communication process

The Bluetooth module communicates through the serial port. When the serial port is configured, it can communicate with the Bluetooth module through the serial port. This time, the communication command is designed as a custom one, starting with @ as the frame, ending with @ as the frame, when received as the beginning of the frame, @ as the end of the frame, when receivedAs the beginning of the frame and @ as the end of the frame, when receiving IDX,1@, where X represents the user ID, the range is 1-5, the MCU reads the height data stored in the AT24C02 corresponding to the ID, and sends it out through the serial port , Bluetooth converts the data into a wireless signal and sends it to the mobile phone. When $IDX,2@ is received, where X represents the user ID, the range is 1-5, the MCU reads the weight data stored in the AT24C02 corresponding to the ID, and sends it out through the serial port, and the Bluetooth converts the data into a wireless signal Send to mobile.
insert image description here

source code

Main program (including data processing of Bluetooth communication)

#include "config.h"
#include "lcd1602.h"
#include "24c02.h"
#include "Ultrasonic.h"
#include "HX711.h"
#include "Key_Duli.h"
#include "UART.H"  

void Send(uchar num);
extern bit is_uartRec;
extern uchar xdata Uart_Buff[20];

uchar xdata menu = 0;
uchar xdata userID = 1;
uint xdata userHeight[10];
uint xdata userWeight[10];

void main()
{
    
    
	uchar  i=0,j=0;
	int HC_SR04Value = 0;
	int HX711_Weight = 0;
	uchar KeyNum = 0xff;
	Init_1602();
  delay_ms(100);
	
	UART_Init();
	
	memset(userHeight,0,10);
	memset(userWeight,0,10);
	
	Inint_24c02();
	if(read24c02AddDat(ID_ADDR) == ID_VALUE)
	{
    
    
		write_string(1,0,"Welcome  To  Use");
		write_string(2,0,"OLD  EPROM      ");
//		for(i=1;i<245;i++) // 新内存,清空数据
//		{
    
    
//			write24c02AddDat(i,0);
//			delay_ms(10);
//		}
	}
	else
	{
    
    
		write24c02AddDat(ID_ADDR,ID_VALUE);
		write_string(1,0,"Welcome  To  Use");
		write_string(2,0,"NEW  EPROM      ");
		for(i=1;i<245;i++) // 新内存,清空数据
		{
    
    
			write24c02AddDat(i,0);
			delay_ms(10);
		}
	}
	delay_ms(1000);
	
	Init_Ultrasonic();
	write_string(1,0,"Height:    000CM");
	write_string(2,0,"Weight:    5000g");
	
	HX711_Init();
	
	printf("Welcome  To  Use,Made By Lei ZhenKun\r\n");
	while(1)
	{
    
    
		if(menu == 0)
		{
    
    
			if(is_uartRec)
			{
    
    
				is_uartRec = 0;
				if(Uart_Buff[1]=='I')
				{
    
    
					write_string(1,0,"Extracting  data");
					write_string(2,0,"Please wait.....");
					
					userID = Uart_Buff[3]-0x30;
								
					memset(userHeight,0,10);
					memset(userWeight,0,10);
					
					if(Uart_Buff[5] == '1')
					{
    
    
						j=0;
						for(i=0;i<20;i+=2)
						{
    
    
							userHeight[j] = read24c02AddDat(1+(userID-1)*40+i)*256 + read24c02AddDat(1+(userID-1)*40+i+1);//1,2; 3,4;5,6
							delay_ms(10);									
							j++;
						}		
						printf("$%01bu,9,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,@",
						userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000,userHeight[5]%1000,userHeight[6]%1000,userHeight[7]%1000,userHeight[8]%1000);
					}
					else if(Uart_Buff[5] == '2')
					{
    
    
						j=0;
						for(i=0;i<20;i+=2)
						{
    
    
							userWeight[j] = read24c02AddDat(21+(userID-1)*40+i)*256 + read24c02AddDat(21+(userID-1)*40+i+1);//21,22;3,4;5,6;
							delay_ms(10);									
							j++;
						}	
						printf("$%01bu,19,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,@",
							userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000,userWeight[5]%10000,userWeight[6]%10000,userWeight[7]%10000,userWeight[8]%10000);				
					}									
					write_string(1,0,"Extracting  data");
					write_string(2,0,"Send Data succes");
												
					delay_ms(2000);
					write_string(1,0,"Height:    000CM");
					write_string(2,0,"Weight:    5000g");
					write_sfm(1,11,3,HC_SR04Value);
					write_sfm(2,11,4,HX711_Weight);
				}
			}
			HC_SR04Value=Count();
			if(HC_SR04Value == -1)  //超出量程
			{
    
    
				write_string(1,11,"---");
			}
			else
			{
    
    
				write_sfm(1,11,3,HC_SR04Value);
			}
			HX711_Weight = Get_Weight();
			if(HX711_Weight == -1)  //超出量程
			{
    
    
//				write_string(2,11,"----");
			}
			else
			{
    
    
				write_sfm(2,11,4,HX711_Weight);
			}
			delay_ms(100);
		}
		KeyNum = KEY_Scan();
		if(KeyNum!=0xff)
		{
    
    
			switch(KeyNum)
			{
    
    
				case 1:
					if(menu == 0)
					{
    
    
						menu = 1;
						write_string(1,0,"Storage ID:   00");
						write_string(2,0,"H:000CM  W:5000g");
						write_sfm(1,14,2,userID);
						write_sfm(2,2,3,HC_SR04Value);
						write_sfm(2,11,4,HX711_Weight);
					}
					else
					{
    
    
						write_string(1,0,"Height:    000CM");
						write_string(2,0,"Weight:    5000g");
						write_sfm(1,11,3,HC_SR04Value);
						write_sfm(2,11,4,HX711_Weight);
						menu = 0;
					}
					break;
				case 2:
					if(menu == 1)
					{
    
    
						userID ++;
						if(userID > 5)
							userID = 1;
						write_sfm(1,14,2,userID);
					}
					break;
				case 3:
					if(menu == 1)  //存储
					{
    
    
						write_string(1,0,"Storage ID:     ");
						write_string(2,0,"Info saved  N:  ");
						
						memset(userHeight,0,10);
						memset(userWeight,0,10);
	
						j=0;
						for(i=0;i<20;i+=2)
						{
    
    
							userHeight[j] = read24c02AddDat(1+(userID-1)*40+i)*256 + read24c02AddDat(1+(userID-1)*40+i+1);//1,2; 3,4;5,6
							delay_ms(10);
							userWeight[j] = read24c02AddDat(21+(userID-1)*40+i)*256 + read24c02AddDat(21+(userID-1)*40+i+1);//21,22;3,4;5,6;
							delay_ms(10);						
							if(userHeight[j]==0 || userWeight[j] == 0)  //说明此位置没存到数据,那就存入当前要存的数据
							{
    
    
								break;
							}			
							j++;
						}						
						if(j >= 9) // 数据是满的,代表已经有了10次历史数据.清空最初的0位置数据,整体移动
						{
    
    
							for(i=0;i<8;i++)  // !!!!!!!!!!!!!! 没办法,10次不行导致程序输出错误,改动到9次
							{
    
    
								userHeight[i] = userHeight[i+1];
								userWeight[i] = userWeight[i+1];
							}
							userHeight[i] = HC_SR04Value; // 最后一位,数组8位置寸新数据
							userWeight[i] = HX711_Weight;
							
							write_sfm(1,14,2,userID);
							write_sfm(2,14,2,i+1);
						}
						else
						{
    
    
							userHeight[j] = HC_SR04Value;
							userWeight[j] = HX711_Weight;

							write_sfm(1,14,2,userID);
							write_sfm(2,14,2,j+1);
						}						
						j=0;
						for(i=0;i<20;i+=2)
						{
    
    
							write24c02AddDat(1+(userID-1)*40+i,userHeight[j]/256);
							write24c02AddDat(1+(userID-1)*40+i+1,userHeight[j]%256);
							delay_ms(10);
							write24c02AddDat(21+(userID-1)*40+i,userWeight[j]/256);
							write24c02AddDat(21+(userID-1)*40+i+1,userWeight[j]%256);
							delay_ms(10);
							j ++;
						}
						
//						printf("$%01bu,10,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,@",
//							userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000,userHeight[5]%1000,userHeight[6]%1000,userHeight[7]%1000,userHeight[8]%1000,userHeight[9]%1000);
//						printf("$%01bu,20,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,@",
//							userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000,userWeight[5]%10000,userWeight[6]%10000,userWeight[7]%10000,userWeight[8]%10000,userWeight[9]%10000);					
						
						delay_ms(2000);
						
						menu = 0;
						write_string(1,0,"Height:    000CM");
						write_string(2,0,"Weight:    5000g");
						write_sfm(1,11,3,HC_SR04Value);
						write_sfm(2,11,4,HX711_Weight);						
					}
					break;
				default:break;
			}
		}
	}
}
//void Send(uchar num)
//{
    
    
//	switch(num)
//	{
    
    
//		case 1:
//			printf("$%01bu,01,%03u,@",userID,userHeight[0]%1000);
//			printf("$%01bu,11,%04u,@",userID,userWeight[0]%10000);
//			break;
//		case 2:
//			printf("$%01bu,02,%03u,%03u,@",userID,userHeight[0]%1000,userHeight[1]%1000);
//			printf("$%01bu,12,%04u,%04u,@",userID,userWeight[0]%10000,userWeight[1]%10000);
//			break;
//		case 3:
//			printf("$%01bu,03,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000);
//			printf("$%01bu,13,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000);
//			break;
//		case 4:
//			printf("$%01bu,04,%03u,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000);
//			printf("$%01bu,14,%04u,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000);
//			break;
//		case 5:
//			printf("$%01bu,05,%03u,%03u,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000);
//			printf("$%01bu,15,%04u,%04u,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000);
//			break;
//		case 6:
//			printf("$%01bu,06,%03u,%03u,%03u,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000,userHeight[5]%1000);
//			printf("$%01bu,16,%04u,%04u,%04u,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000,userWeight[5]%10000);
//			break;
//		case 7:
//			printf("$%01bu,07,%03u,%03u,%03u,%03u,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000,userHeight[5]%1000,userHeight[6]%1000);
//			printf("$%01bu,17,%04u,%04u,%04u,%04u,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000,userWeight[5]%10000,userWeight[6]%10000);
//			break;
//		case 8:
//			printf("$%01bu,08,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000,userHeight[5]%1000,userHeight[6]%1000,userHeight[7]%1000);
//			printf("$%01bu,18,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000,userWeight[5]%10000,userWeight[6]%10000,userWeight[7]%10000);
//			break;
//		case 9:
//			printf("$%01bu,09,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000,userHeight[5]%1000,userHeight[6]%1000,userHeight[7]%1000,userHeight[8]%1000);
//			printf("$%01bu,19,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000,userWeight[5]%10000,userWeight[6]%10000,userWeight[7]%10000,userWeight[8]%10000);
//			break;
//		case 10:
//			printf("$%01bu,10,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,%03u,@",
//				userID,userHeight[0]%1000,userHeight[1]%1000,userHeight[2]%1000,userHeight[3]%1000,userHeight[4]%1000,userHeight[5]%1000,userHeight[6]%1000,userHeight[7]%1000,userHeight[8]%1000,userHeight[9]%1000);
//			printf("$%01bu,20,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,%04u,@",
//				userID,userWeight[0]%10000,userWeight[1]%10000,userWeight[2]%10000,userWeight[3]%10000,userWeight[4]%10000,userWeight[5]%10000,userWeight[6]%10000,userWeight[7]%10000,userWeight[8]%10000,userWeight[9]%10000);
//			break;
//		default:break;
//	}
//}

AT24C02 power-off storage module

#ifndef __24C02_H__
#define __24C02_H__

#include "config.h"


#define add24c02 0									//定义24C02管脚输入地址比如:A2,A1,A0 = 0 0 0 = 0.(方便修改)

sbit SCL=P2^6;									//定义SCL时钟输出IO口.
sbit SDA=P2^5;									//定义SDA数据传输IO口.

#define ID_ADDR  250
#define ID_VALUE 250

void Inint_24c02(void);

unsigned char read24c02AddDat(unsigned char readAdd);//从指定的地址读取一个数据.
void write24c02AddDat(unsigned char writeAdd,unsigned char writeDat);//写入一个数据到指定地址.




#endif




#include "24c02.h"

void Delay5us()		//@12.000MHz
{
    
    
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
}
//24C02部分
/*===========================================================================================
函数名	:	单片机上电,24C02初始化通迅IO.
调  用	:	无调用函数.
参  数	:	无参数.
返回值	:	无返回值.
备  注	:	24C02芯片在上电前,保持IO为空闲状态.
===========================================================================================*/
void Inint_24c02(void)					//上电保护空闲状态
{
    
    
	SCL = 1;
	SDA = 1;
}

/*===========================================================================================
函数名	:	24C02起始条件.
调  用	:	无调用函数.
参  数	:	无参数.
返回值	:	无返回值.
备  注	:	当SCL为高,SDA的下降沿叫做起始条件.(5V时:高大于0.6us,低大于0.6us)
===========================================================================================*/
void start24c02(void)				//24c02起始条件
{
    
    
	SDA = 1;						//SDA输出高电平(注意的是:SCL需在SDA后面拉高,如果外部已拉低SCL,SDA的拉高将被看着是停止条件)
	Delay5us();						//延时
	SCL = 1;						//SCL输出高电平
	Delay5us();						//延时
	SDA = 0;						//SDA下降沿.
	Delay5us();						//延时
	SCL = 0;						//SCL输出高电平
	Delay5us();						//延时
}

/*===========================================================================================
函数名	:	24C02停止条件.
调  用	:	无调用函数.
参  数	:	无参数.
返回值	:	无返回值.
备  注	:	当SCL为高,SDA的上升沿叫做停止条件.
			写此函数思想:1.要产生停止条件,必须要让SDA产生1个上升沿.在产生上升沿之前,SDA须为低.
						 2.正常停止信号在ACK应答后产生,考虑到应答和非应答,所以要先拉低SCL,允许
						 SDA确保为低,再拉高SCL来满足这1条件 
===========================================================================================*/
void stop24c02(void)				//24c02停止条件
{
    
    
	SCL = 0;						//允许SDA为低.
	Delay5us();						//延时
	SDA = 0;						//SDA输出低电平.
	Delay5us();						//延时
	SCL = 1;						//SCL输出高电平
	Delay5us();						//延时
	SDA = 1;						//SDA上升沿.
	Delay5us();						//延时
}


/*===========================================================================================
函数名	:	检测应答信号.
调  用	:	无调用函数.
参  数	:	无参数.
返回值	:	返回值应答,0表示应答,1表示非应答.
备  注	:	当发送完8个数据位后,再发送1个SCL用来检测24C02是否应答.
===========================================================================================*/
bit ACK24c02(void)					//检测应答信号
{
    
    
	SCL = 0;						//拉低SCL,允许SDA改变.
	Delay5us();						//延时
	SDA = 1;						//因为是要接收低电平,所以要先拉高SDA的电平.
	Delay5us();						//延时
	SCL = 1;						//发送1个SCL高.准备检测SDA数据.
	delay_ms(30);						//延时
	if(SDA == 1)					//检测SDA数据.
	{
    
    
		SCL = 0;					//拉低SCL,准备退出,允许外部改变SDA.
		Delay5us();					//延时
		return 1;					//如果读到应答对应位为1说明24c02没有应答.
	}
	else
	{
    
    
		SCL = 0;					//拉低SCL,准备退出,允许外部改变SDA.
		Delay5us();					//延时
		return 0;					//如果读到应答对应位为0说明24c02回复了应答.
	}
}

/*===========================================================================================
函数名	:	等待应答信号.
调  用	:	无调用函数.
参  数	:	无参数.
返回值	:	无返回值.
备  注	:
===========================================================================================*/
void ACKtime24c02(void)				//等待应答信号
{
    
    
	unsigned char i;				//定义1个变量用来循环延时.

	SCL = 0;						//允许数据改变
	Delay5us();						//延时.
	SDA = 1;						//因为是要接收低电平,所以要释放SDA数据线.
	Delay5us();						//延时.
	SCL = 1;						//发送一个时钟信号,等待SDA的应答信号.
	Delay5us();						//延时.
	while(SDA == 1 && i < 200)		//等待24c02应答信号
		i++;
	SCL = 0;						//接低SCL,允许外部改变SDA.
	Delay5us();						//延时.
}

/*===========================================================================================
函数名	:	回复应答或者非应答信号.
调  用	:	无调用函数.
参  数	:	ACKsw为:应答开关,为0时表示应答,1表示非应答.
返回值	:	无返回值.
备  注	:
===========================================================================================*/
void ACKSw24c02(bit ACKsw)	//回复应答或者非应答信号.为0时表示应答,1表示非应答.
{
    
    
	SCL = 0;						//拉抵SCL,允许SDA变化.
	Delay5us();						//延时
	SDA = ACKsw;					//把应答信号传输SDA.
	Delay5us();						//延时
	SCL = 1;						//拉高SCL,让24C来读取.
	Delay5us();						//延时
	SCL = 0;						//拉低SCL,允许外部改变SDA.
	Delay5us();						//延时
}

/*===========================================================================================
函数名	:	24C02位发送.
调  用	:	无调用函数.
参  数	:	dat为:要发送的8位数据.
返回值	:	无返回值.
备  注	:	传输1个字节数据的8个位.
===========================================================================================*/
void write8BitTO24c02(unsigned char dat)//24C02位发送
{
    
    
	unsigned char i;				//定义1个变量用来循环发送数据位用.
	
	SCL = 0;						//SCL输出低电平,允许数据改变
	Delay5us();						//延时
	for(i = 0;i < 8;i++)			//循环8次,发送1个数据的8个位
	{
    
    
		if(dat & 0x80)				//如果要发送的数据最高位为1
			SDA = 1;				//传输位1.
		else
			SDA = 0;				//否则传输0.
		dat <<= 1;					//把要传输的数据移到高位,方便下次发送.
		Delay5us();					//延时
		SCL = 1;					//SCL输出高电平24C02来读数
		Delay5us();					//延时
		SCL = 0;					//SCL输出低电平允许改变数据
		Delay5us();					//延时
	}
}

/*===========================================================================================
函数名	:	24C02读取8位.
调  用	:	无调用函数.
参  数	:	无参数.
返回值	:	返回读取到的8位数据.
备  注	:	读取1个字节数据的8个位.
===========================================================================================*/
unsigned char read8BitTO24c02(void)	//24C02读取8位
{
    
    
	unsigned char i;		//定义1个变量用来循环接收数据位用.
	unsigned char readDat;	//定义1个变量用来暂存接收到的数据
	
	readDat = 0;			//暂存初值为0.
	SCL = 0;				//SCL输出低电平,允许数据改变(任何时序函数结束时都应保持SCL低电平)
	SDA = 1;				//如果要接收数据,必须释放数据总线SDA.
	Delay5us();				//延时
	for(i = 0;i < 8;i++)	//循环8次,接收1个数据的8个位
	{
    
    
		SCL = 1;			//SCL拉高电平,24C输出数据位.
		delay_ms(30);			//延时
		readDat <<= 1;		//因为24C传输数据是高位在前,所以必须左移1位才有空位接收新的数据位.
		if(SDA == 1)		//如果读到的数据为1.
			readDat++;		//暂存最低位置1.
		SCL = 0;			//SCL输出低电平允许改变数据
		Delay5us();			//延时
	}
	return readDat;			//返回读取到的字节
}

/*===========================================================================================
函数名	:	写入一个数据到指定地址.
调  用	:	调用了起始条件函数,发送8位数据函数,检测应答函数,停止条件函数.
参  数	:	writeAdd为:指定数据存储的地址0-255
			writeDat为:要写入的数据.
返回值	:	无返回值.
备  注	:	使用此函数,只需指定数据存储的位置和要写入的数据.
			如果需要连续写,也可以用for循环指定开始位置和结束地址一次写入.
===========================================================================================*/
void write24c02AddDat(unsigned char writeAdd,unsigned char writeDat)//写入一个数据到指定地址.
{
    
    
	unsigned char addWrite;				//定义1个变量用来暂存器件地址.
	unsigned char i;					//定义1个变量i,用来循环检测24C是否应答.
	EA=0;
	addWrite = add24c02;				//把器件地址给暂存.
	addWrite <<= 1;						//器件地址向高位移1位.
	addWrite += 0;						//写入数据时,最低为应为0.
	addWrite |= 0xa0;					//把24C02高4位固定地址放在器件地址高4位.

	for(i = 0;i < 5;i++)				//最多检测5次应答信号,
	{
    
    
		start24c02();					//24c02起始条件.
		write8BitTO24c02(addWrite);		//写入7位器件地址,最低位为0.
		if(!ACK24c02())					//如果没有应答,继续发送起始条件和器件地址.
			break;						//如果应答了,就跳出for循环,准备写入地址.
	}
	write8BitTO24c02(writeAdd);			//写入数据要存储地址.
	ACKtime24c02();						//等待应答信号.
	write8BitTO24c02(writeDat);			//写数据.
	ACKtime24c02();						//等待应答信号.
	stop24c02();						//发送停止条件.
	EA=1;
}

/*===========================================================================================
函数名	:	从指定的地址读取一个数据.
调  用	:	调用了起始条件函数,发送8位数据函数,接收8位数据函数,等待应答函数,停止条件函数.
参  数	:	readAdd为:读出数据的地址0-255(要从哪个地址读出数据)
返回值	:	返回读出的数据.其类型为char.
备  注	:	此函数会返回该地址对应的数据.
===========================================================================================*/
unsigned char read24c02AddDat(unsigned char readAdd)//从指定的地址读取一个数据.
{
    
    
	unsigned char readDat;			//定义1个变量用来暂存读取数据.
	unsigned char addRead;			//定义1个变量用来暂存器件地址.
	unsigned char i;				//定义1个变量i,用来循环检测24C是否应答.
	EA=0;
	addRead = add24c02;				//把器件地址给暂存.
	addRead <<= 1;					//器件地址向高位移1位.
	addRead |= 0xa0;				//把24C02高4位固定地址放在器件地址高4位.
	readDat = 0;					//初始化暂存为0.

	for(i = 0;i < 5;i++)			//最多检测5次应答信号,
	{
    
    
		start24c02();				//24c02起始条件.
		write8BitTO24c02(addRead);	//写入7位器件地址,最低位为0.
		if(!ACK24c02())				//如果没有应答,继续发送起始条件和器件地址.
			break;					//如果应答了,就跳出for循环,准备写入地址.
	}
		write8BitTO24c02(readAdd);	//写入指定地址.
		ACKtime24c02();				//等待应答信号.
		start24c02();				//24c02起始条件.
		write8BitTO24c02(addRead+1);//写入7位器件地址,最低位为1(读).
		ACKtime24c02();				//等待应答信号
		readDat = read8BitTO24c02();//24C02位接收
		ACKSw24c02(1);				//非应答
		stop24c02();				//24c02停止条件
		EA=1;
		return readDat;				//返回读到的数据.
}
//24C02结束



/***************24C02的调用*****************

//记录数据:
if((flag_jishu)&&(m==0))
	{
		flag_jishu=0;
		password[0]=ch2o/10000%10;      //先将测的CH20值取位
		password[1]=ch2o/1000%10;
		password[2]=ch2o/100%10;
		password[3]=ch2o/10%10;
		password[4]=ch2o%10;
		for(i = 0;i < 5;i++)				//循环5次.,从24C02的0地址开始写入
			write24c02AddDat(i,password[i]);		//往24C02写入.
		m=1;
	}
//这样算来,每写入一个数据,就占了24C02的5个地址;
//即第二次数据的写入地址就从24C02的地址5开始了:
	if((m==1)&&(flag_jishu))
	{
		m=0;
		flag_jishu=0;
		password[5]=ch2o/10000%10;
		password[6]=ch2o/1000%10;
		password[7]=ch2o/100%10;
		password[8]=ch2o/10%10;
		password[9]=ch2o%10;
		for(i = 5;i < 10;i++)						//从地址5开始;循环5次.
			write24c02AddDat(i,password[i]);		//24C02写入.
	}
******************************************************/

HX711 weight detection module

#ifndef __HX711_H__
#define __HX711_H__


#include "config.h"

//IO设置
sbit HX711_DOUT=P2^3; 
sbit HX711_SCK=P2^4; 


//函数或者变量声明
extern uint GapValue;
void HX711_Init(void);
long Get_Weight(void);

#endif

#include "HX711.h"


//****************************************************
//延时函数
//****************************************************
void Delay__hx711_us(void)
{
    
    
	_nop_();
	_nop_();
	_nop_();
	_nop_();
	_nop_();
}

//****************************************************
//读取HX711
//****************************************************
unsigned long HX711_Read(void)	//增益128
{
    
    
	unsigned long count; 
	unsigned char i; 
  	HX711_DOUT=1; 
	Delay__hx711_us();
  	HX711_SCK=0; 
  	count=0; 
  	while(HX711_DOUT); 
  	for(i=0;i<24;i++)
	{
    
     
	  	HX711_SCK=1; 
	  	count=count<<1; 
		HX711_SCK=0; 
	  	if(HX711_DOUT)
			count++; 
	} 
 	HX711_SCK=1; 
    count=count^0x800000;//第25个脉冲下降沿来时,转换数据
	Delay__hx711_us();
	HX711_SCK=0;  
	return(count);
}

//****************************************************
//获取毛皮重量 -- 上称时上面的物体重量
//****************************************************
unsigned long idata Weight_Maopi = 0;
unsigned long idata Weight_Maopi_0 = 0;
uint GapValue  = 483;	//校准初值
void Get_Maopi()
{
    
    
	unsigned char clear;
mm:	Weight_Maopi_0 = HX711_Read();
	for(clear=0;clear<2;clear++)
	{
    
    
		delay_ms(500);	
	}
	Weight_Maopi = HX711_Read();
	if(Weight_Maopi/GapValue != Weight_Maopi_0/GapValue)
		goto mm;
} 
//****************************************************
//称重
//****************************************************
long Get_Weight(void)
{
    
    
	long Weight_Shiwu = 0;
	
	Weight_Shiwu = HX711_Read();
	Weight_Shiwu = Weight_Shiwu - Weight_Maopi;		//获取净重
	if(Weight_Shiwu < 0)
		Weight_Shiwu = 0;
	
	Weight_Shiwu = (unsigned int)((float)Weight_Shiwu/(float)GapValue + 0.5); 	//计算实物的实际重量																
	if(Weight_Shiwu > 5000)		//超重报警
	{
    
    
		return -1;
	}
	else
	{
    
    
		return 	(long)Weight_Shiwu;	
	}
}
void HX711_Init(void)
{
    
    
	Get_Maopi();
}






Ultrasonic ranging module

#ifndef __ULTRASONIC_H__
#define __ULTRASONIC_H__

#include "config.h"

sbit Trig_1=P1^6; //产生脉冲引脚
sbit Echo_1=P1^7; //回波引脚


void Init_Ultrasonic(void);		 //   T设置为0,E设置成1    10101010   

int Count(void);

#endif
#include "Ultrasonic.h"
bit Flag_Ultrasonic=0;
/*--------------------------------------------------------
函数名称:StartModule
函数功能://启动模块
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
void  StartModule(void) 		         //启动模块
{
    
    
	TR0=0;
	TH0=0;
	TL0=0;
	Trig_1=1;		                     //启动一次模块
	_nop_();_nop_();_nop_();_nop_();_nop_(); //空操作5次
	_nop_();_nop_();_nop_();_nop_();_nop_(); //空操作5次
	_nop_();_nop_();_nop_();_nop_();_nop_(); //空操作5次
	_nop_();_nop_();_nop_();_nop_();_nop_(); //空操作5次
	Trig_1=0; 
}
/*--------------------------------------------------------
函数名称:Waiting_Ultrasonic
函数功能://等待超声波返回信号模块
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
void Waiting_Ultrasonic(void)
{
    
    
	while(!Echo_1);TR0=1;		   
	while(Echo_1); TR0=0;
}

int Count(void)
{
    
    
	static int Time=0,S=0;
	
	StartModule();
	Waiting_Ultrasonic();
	
	Time=TH0*256+TL0;
	TH0=0;
	TL0=0;
  S=(int)((Time*1.7)/100.0);     //算出来是CM 	  //340
	if((S>=600)||Flag_Ultrasonic==1) //超出测量范围显示“-”
	{
    
    
		Flag_Ultrasonic = 0;
		return -1;
	}
	return S;
}
/*--------------------------------------------------------
函数名称:Timer0()
函数功能:定时器0中断子函数,计算距离溢出处理
注意事项:
提示说明:
输    入:
返    回:
---------------------------------------------------------*/
void Init_Timer0()
{
    
    
	TMOD&=0xf0;		   
	TMOD|=0x01;		//设T0为方式1
	TH0=0;		
	TL0=0;          //定时器0初始化装载0
	ET0=1;             //允许T0中断	
	EA=1;			   //开启总中断	
}
static void Timer0() interrupt 1 		 //T0中断用来计数器溢出,超过测距范围
{
    
    
	Flag_Ultrasonic=1;							 //中断溢出标志
}

void Init_Ultrasonic()		 //   T设置为0,E设置成1    10101010         
{
    
    
	Trig_1=0;
	Echo_1=1;
	
	Init_Timer0();
}

Serial communication driver

#ifndef _UART_H_  
#define _UART_H_  
 
#include "config.h"
  
#define FOSC 11059200L      //System frequency
#define BAUD 9600       //UART baudrate

/*Define UART parity mode*/
#define NONE_PARITY     0   //None parity
#define ODD_PARITY      1   //Odd parity
#define EVEN_PARITY     2   //Even parity
#define MARK_PARITY     3   //Mark parity
#define SPACE_PARITY    4   //Space parity

#define PARITYBIT NONE_PARITY   //Testing even parity

void UART_SendData(BYTE dat);
void UART_SendString(char *s);
void UART_Init(void);
	

#endif  
 
 
 
#include "UART.H"  
#include <stdio.h>

bit busy=0;

void UART_Init(void)
{
    
    
		#if (PARITYBIT == NONE_PARITY)
				SCON = 0x50;            //8-bit variable UART
		#elif (PARITYBIT == ODD_PARITY) || (PARITYBIT == EVEN_PARITY) || (PARITYBIT == MARK_PARITY)
				SCON = 0xda;            //9-bit variable UART, parity bit initial to 1
		#elif (PARITYBIT == SPACE_PARITY)
				SCON = 0xd2;            //9-bit variable UART, parity bit initial to 0
		#endif
	
		TL2 = RCAP2L = (65536-(FOSC/32/BAUD)); //Set auto-reload vaule
    TH2 = RCAP2H = (65536-(FOSC/32/BAUD)) >> 8;
    T2CON = 0x34;           //Timer2 start run
    ES = 1;                 //Enable UART interrupt
    EA = 1;                 //Open master interrupt switch
}

/*----------------------------
UART interrupt service routine
----------------------------*/
uchar xdata Uart_Buff[20];
uchar Uart_ResPos=0;
bit is_uartRec = 0;
void Uart_Isr() interrupt 4
{
    
    
    if (RI)
    {
    
    
        RI = 0;             //Clear receive interrupt flag
//        P0 = SBUF;          //P0 show UART data
//		GSMA6_Receive_Byte(SBUF);
			if(SBUF == '$')
			{
    
    
				Uart_ResPos = 0;
			}
			Uart_Buff[Uart_ResPos++] = SBUF;
			if(Uart_ResPos>10 || SBUF == '@')
			{
    
    
				is_uartRec = 1;
			}
    }
    if (TI)
    {
    
    
        TI = 0;             //Clear transmit interrupt flag
        busy = 0;           //Clear transmit busy flag
    }
}

/*----------------------------
Send a byte data to UART
Input: dat (data to be sent)
Output:None
----------------------------*/
void UART_SendData(BYTE dat)
{
    
    
    while (busy);           //Wait for the completion of the previous data is sent
    ACC = dat;              //Calculate the even parity bit P (PSW.0)
    if (P)                  //Set the parity bit according to P
    {
    
    
			#if (PARITYBIT == ODD_PARITY)
							TB8 = 0;            //Set parity bit to 0
			#elif (PARITYBIT == EVEN_PARITY)
							TB8 = 1;            //Set parity bit to 1
			#endif
					}
					else
					{
    
    
			#if (PARITYBIT == ODD_PARITY)
							TB8 = 1;            //Set parity bit to 1
			#elif (PARITYBIT == EVEN_PARITY)
							TB8 = 0;            //Set parity bit to 0
			#endif
    }
    busy = 1;
    SBUF = ACC;             //Send data to UART buffer
}

/*----------------------------
Send a string to UART
Input: s (address of string)
Output:None
----------------------------*/
//void UART_SendString(char *s)
//{
    
    
//    while (*s)              //Check the end of the string
//    {
    
    
//        UART_SendData(*s++);     //Send current char and increment string ptr
//    }
//}

// printf函数在格式化输出时,向下调用了char putchar(char c);这个函数,在“stdio.h”里可以发现有这个函数
char putchar(char c)//重定向
{
    
    
	UART_SendData(c);
	return c;
}



Guess you like

Origin blog.csdn.net/qq_20467929/article/details/126142494