5, ♥ ☆ smart Bracelet based on STM32 √★☆

5, ♥ ☆ smart Bracelet based on STM32 √★☆ 💙💙

Introduction

With the development of society, people's material living standards are improving day by day, and people are paying more and more attention to their health. As a measuring instrument, the pedometer can calculate the number of walking steps and the energy consumed, so people can quantitatively formulate exercise programs to exercise, and analyze the health of the human body according to the running situation, so it is becoming more and more popular. The handheld electronic pedometer is designed to meet market demand and is simple and convenient to use.

introduction

With the development of society, people's material living standards are improving day by day, and people pay more and more attention to their health. As a measuring instrument, pedometer can calculate the number of walking steps and energy consumption, so people can quantitatively formulate exercise plans to fitness, and analyze the health status of human body according to the operation, so it is more and more popular. The hand-held electronic pedometer is designed to meet the needs of the market and is simple and convenient to use.

1. System overview

1.1 design tasks

Design an intelligent bracelet with STM32.

1.2 design requirements

  • (1) Accurate step counting function;

  • (2) Can detect heart rate;

  • (3) Able to detect the temperature of environment and human body;

  • (4) All data is displayed on the screen.

2. Scheme design and demonstration

2.1 chip selection scheme

stm32 is a 32-bit single chip microcomputer with low power consumption and high performance. It contains 4K bytes ISP (in system programmable) Flash read-only program memory that can be rewritten 1000 times. The main performances are: compatible with MCS-51 single chip microcomputer products, full static operation: 0Hz ~ 33Hz, three-level encryption program memory, 32 programmable I/O port lines, three 16 bit timers / counters, eight interrupt sources, full duplex UART serial channel, interrupt wake-up after power failure, watchdog timer, double data pointer, power failure identifier and easy programming.

2.2 system overview

Pedometer is a popular daily exercise progress monitor, which can inspire people to challenge themselves, enhance their physique and help them lose weight. Early designs used weighted mechanical switches to detect pace, with a simple counter. When shaking these devices, you can hear a metal ball sliding back and forth, or a pendulum swinging left and right to hit the stop. The main components of electronic pedometer are vibration sensor and electronic counter. When walking, people's center of gravity will move up and down. The up and down displacement of the waist is the most obvious, so it is most suitable for the walker to hang on the belt. The so-called vibration sensor is actually a balance weight whose balance is damaged when it vibrates up and down, so that a contact can have on / off action. The electronic counter completes the main recording and display functions, others belong to heat consumption, and the distance conversion is completed by the circuit. An accelerometer is generally used in pedometer to feel the vibration of the outside world. The principle of common accelerometers is as follows: a small piece of magnet is sealed in a section of plastic pipe, and the coil is wound outside the pipe. When the plastic pipe moves, the magnet moves reversely in the pipe due to inertia and cuts the coil. Due to electromagnetic induction, the current is generated in the coil. When the human body moves, the up and down acceleration is approximately sinusoidal, and the output current of the coil is also sinusoidal, Measuring the frequency of sine wave can get the number of steps of motion, and then calculate the distance.

Heart Rate is a professional term used to describe the cardiac cycle heart The number of beats per minute shall be subject to the first sound. Heart rate, which is interpreted in modern Chinese as“ heart Beat frequency ". Frequency is the number of times something happens in unit time. The combination of the two explanations is, heart The number of beats in a certain period of time, that is, how fast the heart beats in a certain period of time.

The heart rate of healthy adults is 60 ~ 100 beats / min, most of them are 60 ~ 80 beats / min, which is slightly faster in women; Children under 3 years old are often more than 100 times / minute; The elderly are slow. Adult heart rate exceeds 100 beats per minute (generally not more than 160 beats / min) or baby More than 150 times / minute is called Sinus tachycardia . It is common in normal people after exercise, excitement, excitement, smoking, drinking and drinking strong tea. It can also be seen in fever shock , anemia, hyperthyroidism heart failure And Application atropine,adrenaline,ephedrine Wait. If the heart rate is 160 ~ 220 beats / min, it is often called Paroxysmal tachycardia . Those whose heart rate is lower than 60 beats / min (generally more than 40 beats / min) are called Sinus bradycardia . It can be seen that they have been engaged in heavy physical labor and labor for a long time Athletes ; Pathological thyroid Low function Intracranial hypertension,Obstructive jaundice , digitalis Quinidine or Propranolol Drug overdose or poisoning. If the heart rate is lower than 40 beats / min, consider Atrioventricular block.

Based on this, this design chooses to develop an intelligent Bracelet integrating steps and heart rate.

2.3 design requirements

  • (1) Accurate step counting function;

  • (2) Can detect heart rate;

  • (3) Able to detect the temperature of environment and human body;

  • (4) All data is displayed on the screen

2.4 overall system design idea

  • (1) The state of people is detected by the gravity acceleration sensor ADXL345, and the walking steps, walking distance and average speed are calculated.

  • (2) . the heart rate is detected in real time through the heart rate sensor, and the temperature is detected through the temperature sensor.

  • (3) LCD 1602 displays the number of steps, distance, average speed, heart rate and temperature in real time.

2.5 analysis of program implementation principle of each functional module

This design consists of STM32F103C8T6 MCU core board circuit + ADXL345 sensor circuit + heart rate sensor circuit + temperature sensor + LCD 1602 circuit.

  • 1. The state of people is detected by the gravity acceleration sensor ADXL345, and the walking steps, walking distance and average speed are calculated.

  • 2. The heart rate is detected in real time by the heart rate sensor and the temperature is detected by the temperature sensor.

  • 3. LCD 1602 displays steps, distance, average speed, heart rate and temperature in real time.

    The specific block diagram of the system is shown in the figure below:

2.5. 1. Circuit design of LCD1602 LCD module

LCD display is divided into field display and character display. The field display is similar to the LED display, which can be displayed as long as the corresponding signal is sent to the corresponding pin. Character display is to display basic characters as needed. This design adopts character display. In the system, LCD1602 is used as the display device to output information. Compared with the traditional LED digital tube display device, the liquid crystal display module has the advantages of small volume, low power consumption and rich display content, and does not need additional driving circuit. Now the liquid crystal display module is the most commonly used display device in the application design of single chip microcomputer. LCD1602 can display 2 lines of 16 Chinese characters.

2.5. 2. Circuit design of ADXL345 inclination sensor module

This design selects ADXL345 module of inclination sensor to detect relevant state information in real time. ADXL345 is a small and thin ultra-low power 3-axis accelerometer with high resolution (13 bits) and a measurement range of ± 16g. The digital output data is in 16 bit binary complement format and can be accessed through SPI(3-wire or 4-wire) or I2C digital interface. ADXL345 is ideal for mobile device applications. It can measure static gravity acceleration in tilt detection applications, as well as dynamic acceleration caused by motion or impact. Its high resolution (3.9mg/LSB) can measure tilt angle changes of less than 1.0 °. The device provides a variety of special detection functions. The active and inactive detection functions detect the occurrence of motion by comparing the acceleration on any axis with the threshold set by the user. The knock detection function can detect single vibration and double vibration in any direction. The free fall detection function can detect whether the device is falling. These functions can be independently mapped to one of the two interrupt output pins. The patent pending integrated memory management system adopts a 32 level first in first out (FIFO) buffer, which can be used to store data, so as to minimize the host processor load and reduce the overall system power consumption. Low power mode supports motion based intelligent power management, so as to carry out threshold sensing and motion acceleration measurement with very low power consumption.

2.5. 3. Circuit design of Pulsesensor pulse and heart rate sensor module

Pulse heart rate sensor is a sensor used to test heart rate. In essence, it is an optical heart rate sensor integrating amplification circuit and noise elimination circuit. This sensor can be used to develop interactive works related to heart rate. Sensors can be worn on fingers or earlobes. The photoelectric sensor converts the pulse signal into an electrical signal. The device needs to place the finger on the sensor dial. The photoelectric sensor is an optical heart rate sensor integrating an amplification circuit and a noise elimination circuit. The light-emitting diode on one side of the photoelectric sensor emits light. When the pulse beats, the arterial blood volume of the fingertip or earlobe changes periodically, The light intensity through the fingertips changes simultaneously. The photoelectric triode on the other side converts the received infrared light signal into an electrical signal.

2.5. 4. Circuit design of DS18B20 temperature sensor module

DS18B20 is a commonly used digital temperature sensor. Its output is digital signal. It has the characteristics of small volume, low hardware overhead, strong anti-interference ability and high precision. DS18B20 digital temperature sensor has convenient wiring and can be applied to a variety of occasions after packaging, such as pipeline type, threaded type, magnet adsorption type, stainless steel packaging type. There are a variety of models, including LTM8877, LTM8874 and so on. The appearance is mainly changed according to different applications. The packaged DS18B20 can be used for various non limit temperature occasions, such as cable trench temperature measurement, blast furnace water circulation temperature measurement, boiler temperature measurement, machine room temperature measurement, agricultural greenhouse temperature measurement, clean room temperature measurement, ammunition depot temperature measurement and so on. The utility model has the advantages of wear resistance, collision resistance, small volume, convenient use and various packaging forms, and is suitable for the field of digital temperature measurement and control of various narrow space equipment.

3. STM32 performance introduction and hardware design

3.1 performance introduction of STM32 single chip microcomputer

STM32 has resources including 48KB SRAM, 256KB FLASH, 2 basic timers, 4 general timers, 2 advanced timers, 2 DMA controllers (12 channels in total), 3 SPI s, 2 IIC S, 5 serial ports, 1 USB, 1 CAN, 3 12 bit ADC s, 1 12 bit DAC, 1 SDIO interface and 51 general IO ports. The chip has high cost performance.

The description of each pin is as follows:

  • PA0 function 1, press KEY_UP 2 can be used as standby wake-up pin (WKUP) 3, and can be connected to DS18B20 sensor interface (P2 setting)

  • PA1 function 1, NRF24L01 interface IRQ signal 2, connected to HS0038 infrared receiver (P2 setting)

  • PA2 acts as the chip selection signal of W25Q64

  • PA3 acts as the chip selection pin of SD card interface

  • PA4 acts as CE signal of NRF24L01 interface

  • PA5 acts as SCK signal of W25Q64, SD card and NRF24L01 interface

  • PA6 acts as MISO signal of W25Q64, SD card and NRF24L01 interface

  • PA7 acts as MOSI signal of W25Q64, SD card and NRF24L01 interface

  • PA8 is used to connect DS0 LED lamp (red)

  • PA9 acts as TX pin of serial port 1, and is connected to RX of CH340 by default (P4 setting)

  • PA10 acts as RX pin of serial port 1, and is connected to TX(P4 setting) of CH340 by default

  • PA11 acts as a USB D-pin

  • PA12 acts as a USB D + pin

  • PA13 acts as JTAG/SWD simulation interface without any peripherals

  • PA14 acts as JTAG/SWD simulation interface without any peripherals

  • PA15 acts as 1, JTAG simulation port (JTDI) 2, CLK signal 3 of PS/2 interface, and connected to key 1

3.2 hardware design of intelligent Bracelet system

The main circuit diagram, temperature detection module circuit diagram, step counting module circuit diagram, heart rate sensor module circuit diagram and LCD external wiring diagram required by the program are shown in the following figure in turn:

4. System program

4.1 main program design flow chart

4.2 main program content

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include <stdio.h>
#include "timer.h"
#include "key.h"
#include "exti.h"
#include "adxl345.h"
#include "lcd1602.h"
#include "ds18b20.h" 

unsigned char ReadAdxl345;	   //Read adxl345 data regularly
unsigned char ErrorNum=0;   //Record the number of errors
unsigned char CheckNum=0;   //Detection times
	  
char dis0[16];//LCD array display temporary storage
char dis1[35];

unsigned int xlTab[5];//Heart rate array
unsigned char count=0;	//Heart rate filter count
unsigned int xinLater=0;//	Heart rate delay processing
unsigned int xinLv =0;    //Heart rate value

unsigned int BuShu=0;//Number of steps
unsigned int Normal_num=0;			//Normal times
unsigned int Error_num=0;			//Tilt times

unsigned int disBuShu = 0;  //Show steps
float disJuLi = 0;//Display distance
float temperature;  //temperature
unsigned char readTemp = 0;	//Read temperature flag

int main(void)
{ 
    delay_init();	    	 //Delay function initialization	  
    uart_init(9600);	 	//The serial port is initialized to 9600
    TIM3_Int_Init(49,7199);//50ms  	
    EXTIX_Init();		// Initialize external interrupt
    LED_Init();		  		//Initialize the hardware interface to the LED
    KEY_Init();			//Initialization key
    Lcd_GPIO_init();  //Initialize lcd pin
    Lcd_Init();		  //Initialize lcd screen
    delay_ms(200);

    Init_ADXL345();
    if(Single_Read_ADXL345(0X00)==0xe5)	
    {
        delay_ms(5);
    }
    else
    {
        delay_ms(3);
    }
    while(1)
    {
        if(ReadAdxl345== 1)   //Read adxl345 data regularly
        {
            ReadAdxl345= 0;
            ReadData_x();  						//Triaxial detection function
            CheckNum++;
            if((temp_Y>450)||(temp_Y<-450)) //View normal times     
            {
                Normal_num++;  //Normal times++
            }
            else
            {
                Error_num++;//Tilt times
            }
            if((Error_num!=0)&&(Normal_num!=0))//Steps detected
            {
                BuShu++;   //Step pulse++
                Error_num=0;    //Clear one cycle detection
                Normal_num=0;
            }
        }
        if(disFlag==1)	   //Display flag
        {
            disFlag = 0;
            readTemp++;  //Timing count
            if(readTemp >= 8)//Primary data processing temperature of about 800ms
            {
                readTemp =0;//Re count
                temperature=(float)DS18B20_Get_Temp()/10;	//Reduce 10 times to actual value			
            }
            disBuShu = BuShu/2;  //Show steps
            disJuLi = disBuShu*0.45;//Display distance
            sprintf(dis0,"X:%03d/min %4.1f C",xinLv,temperature);//Print
            Lcd_Puts(0,0,(unsigned char *)dis0);	//display
            Lcd_1Put(14,0,0xdf);//display symbols
            sprintf(dis1,"BS:%03d JL:%4.1fm  ",disBuShu,disJuLi);//Print
            Lcd_Puts(0,1,(unsigned char *)dis1);	//display

        }	
    }											    
}	

4.3 ADXL345 inclination sensor

#include "stm32f10x.h"
#include "delay.h"
#include "adxl345.h"

#define SDA_RCC			RCC_APB2Periph_GPIOA
#define SDA_GPIO		GPIOA
#define SDA_GPIO_PIN	GPIO_Pin_5

#define SCL_RCC			RCC_APB2Periph_GPIOA
#define SCL_GPIO		GPIOA
#define SCL_GPIO_PIN	GPIO_Pin_4

#define SCL_OUT() SCL_Set_Output() / / set scl
#define SET_SCL() GPIO_SetBits(SCL_GPIO, SCL_GPIO_PIN) / / set SCL
#define CLE_SCL() GPIO_ResetBits(SCL_GPIO, SCL_GPIO_PIN) / / clear SCL
                    
#define SDA_OUT() SDA_Set_Output()
#define SDA_INT() SDA_Set_Input()
#define SET_SDA() GPIO_SetBits(SDA_GPIO, SDA_GPIO_PIN) / / set SDA
#define CLE_SDA() GPIO_ResetBits(SDA_GPIO, SDA_GPIO_PIN) / / clear SDA
#define SDA_VAL() GPIO_ReadInputDataBit(SDA_GPIO, SDA_GPIO_PIN)

#define 	 Slaveaddress 0xA6 / / defines the slave address of the device in the IIC bus. It is modified according to the ALT address pin / / the address of the ALT address pin is 0xA6 when it is grounded and 0x3A when it is connected to the power supply

unsigned char BUF[8];                         //Receive data buffer      	
unsigned char ge,shi,bai,qian,wan;           //Display variables
unsigned char err;
float temp_X,temp_Y,temp_Z;

void SCL_Set_Output(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = SCL_GPIO_PIN;				 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 
	GPIO_Init(SCL_GPIO, &GPIO_InitStructure);					 					
}	

void SDA_Set_Output(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN;				 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 
	GPIO_Init(SDA_GPIO, &GPIO_InitStructure);					 					
}	

void SDA_Set_Input(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = SDA_GPIO_PIN;				 
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; 		 
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 
	GPIO_Init(SDA_GPIO, &GPIO_InitStructure);					 
}

/**************************************
Start signal
**************************************/
void ADXL345_Start(void)
{
    SCL_OUT();
    SDA_OUT();
    SET_SDA();//SDA = 1;                    // Pull up the data cable
    SET_SCL();//SCL = 1;                    // Pull up the clock line
    delay_us(2);//Delay5us();                 // delayed
    CLE_SDA();//SDA = 0;                    // Produce falling edge
    delay_us(2);//Delay5us();                 // delayed
    CLE_SCL();//SCL = 0;                    // Pull down the clock line
}

/**************************************
Stop signal
**************************************/
void ADXL345_Stop(void)
{
    SCL_OUT();
    SDA_OUT();
    CLE_SDA();//SDA = 0;                    // Pull down the data cable
    SET_SCL();//SCL = 1;                    // Pull up the clock line
    delay_us(2);//Delay5us();                 // delayed
    SET_SDA();//SDA = 1;                    // Produce rising edge
    delay_us(2);//Delay5us();                 // delayed
    CLE_SCL();
}

/**************************************
Send response signal
 Entry parameter: ack (0:ACK 1:NAK)
**************************************/
void ADXL345_SendACK(uchar ack)
{   
    SCL_OUT();
    SDA_OUT();
    if(ack==0)//SDA = ack;                  // Write reply signal
    {
      CLE_SDA();
    }
    else
    {
      SET_SDA();
    }
    SET_SCL();//SCL = 1;                    // Pull up the clock line
    delay_us(2);//Delay5us();                 // delayed
    CLE_SCL();//SCL = 0;                    // Pull down the clock line
    delay_us(5);//Delay5us();                 // delayed
}
/**************************************
Receive response signal
**************************************/
uchar ADXL345_RecvACK(void)
{
    SDA_INT();
    SCL_OUT();
    SET_SCL();//SCL = 1;                    // Pull up the clock line
    delay_us(2);//    Delay5us();                 // delayed
    SET_SCL();
    if(SDA_VAL()== Bit_SET)   //CY = SDA;                   // Read response signal
    {
        err = 1;
    }
    else
    {
        err = 0;
    }
    CLE_SCL() ;//SCL = 0;                    // Pull down the clock line
    delay_us(5);//    Delay5us();                 // delayed
    SDA_OUT();
    return err;
}

/**************************************
Sends a byte of data to the IIC bus
**************************************/
void ADXL345_SendByte(unsigned char dat)
{
    unsigned char i;
    SCL_OUT();
    SDA_OUT();
    for (i=0; i<8; i++)         //8-bit counter
    {
        delay_us(5);             //delayed
        if(dat&0x80)  //SDA = CY;               // Data transmission port
        {SET_SDA();}
        else
        {CLE_SDA();}       
        delay_us(5);             //delayed
        SET_SCL();//SCL = 1;                // Pull up the clock line
        delay_us(5);             //delayed
        CLE_SCL();//SCL = 0;                // Pull down the clock line
        dat <<= 1;              //Remove the highest bit of data
    }
    ADXL345_RecvACK();
}
/**************************************
Receives a byte of data from the IIC bus
**************************************/
unsigned char ADXL345_RecvByte(void)
{
    unsigned char i;
    unsigned char Mid;
    unsigned char dat = 0;
    SDA_INT();
    SCL_OUT();

    for (i=0; i<8; i++)         //8-bit counter
    {
        dat <<= 1;
        delay_us(5);            //delayed
        SET_SCL();

        if(SDA_VAL()== Bit_SET)   //CY = SDA;                   // Read response signal
        {
            Mid = 1;
        }
        else
        {
            Mid = 0;
        }
        if(Mid) dat++;
        delay_us(5);     
        CLE_SCL();//SCL = 0;                // Pull down the clock line
    }
    return dat;
}

//******Single byte write*******************************************

void Single_Write_ADXL345(uchar REG_Address,uchar REG_data)
{
    ADXL345_Start();                  //Start signal
    ADXL345_SendByte(SlaveAddress);   //Sending device address + write signal
    ADXL345_SendByte(REG_Address);    //Internal register address
    ADXL345_SendByte(REG_data);       //Internal register data
    ADXL345_Stop();                   //Send stop signal
}

//********Single byte read*****************************************
uchar Single_Read_ADXL345(uchar REG_Address)
{  
    uchar REG_data;
    ADXL345_Start();                          //Start signal
    ADXL345_SendByte(SlaveAddress);           //Sending device address + write signal
    ADXL345_SendByte(REG_Address);            //Send storage unit address, starting from 0	
    ADXL345_Start();                          //Start signal
    ADXL345_SendByte(SlaveAddress+1);         //Sending device address + read signal
    REG_data=ADXL345_RecvByte();              //Read register data
    ADXL345_SendACK(1);   
    ADXL345_Stop();                           //Stop signal
    return REG_data; 
}
//Continuously read ADXL345 internal acceleration data, address range 0x32~0x37
void Multiple_Read_ADXL345(void)
{   
    uchar i;
    ADXL345_Start();                          //Start signal
    ADXL345_SendByte(SlaveAddress);           //Sending device address + write signal
    ADXL345_SendByte(0x32);                   //Send storage unit address, starting from 0x32	
    ADXL345_Start();                          //Start signal
    ADXL345_SendByte(SlaveAddress+1);         //Sending device address + read signal
    for (i=0; i<6; i++)                      //Continuously read 6 address data and store BUF in
    {
        BUF[i] = ADXL345_RecvByte();          //BUF[0] stores data in 0x32 address
        if (i == 5)
        {
            ADXL345_SendACK(1);                //The last data needs to be returned to NOACK
        }
        else
        {
            ADXL345_SendACK(0);                //Respond to ACK
        }
    }
    ADXL345_Stop();                          //Stop signal
    delay_ms(5);
}
//Initialize ADXL345
void Init_ADXL345(void)
{
    Single_Write_ADXL345(0x31,0x0B);   //Measurement range, plus or minus 16g, 13 bit mode
    Single_Write_ADXL345(0x2C,0x08);   //The rate is set to 12.5 
    Single_Write_ADXL345(0x2D,0x08);   //Select power mode   
    Single_Write_ADXL345(0x2E,0x80);   //Enable DATA_READY interrupt
    Single_Write_ADXL345(0x1E,0x00);   //The X offset is written according to the status of the test sensor
    Single_Write_ADXL345(0x1F,0x00);   //The Y offset is written according to the status of the test sensor
    Single_Write_ADXL345(0x20,0x05);   //The Z offset is written according to the status of the test sensor
}
//Show x axis
void ReadData_x(void)
{   
    int  dis_data;                       //variable
    Multiple_Read_ADXL345();       	//Data is read out continuously and stored in BUF
    dis_data=(BUF[1]<<8)+BUF[0];  //Synthetic data   
    temp_X=(float)dis_data*3.9;  //Calculation data and display 
    dis_data=(BUF[3]<<8)+BUF[2];  //Synthetic data   
    temp_Y=(float)dis_data*3.9;  //Calculation data and display
    dis_data=(BUF[5]<<8)+BUF[4];    //Synthetic data   
    temp_Z=(float)dis_data*3.9;  //Calculation data and display 
}

4.4 LCD1602 display screen

#include "lcd1602.h"

/************************Port initialization*******************************/
void Lcd_GPIO_init(void)
{
     GPIO_InitTypeDef GPIO_InitStructure;   //Declaration structure

    /********Data Port settings*************/
	 RCC_APB2PeriphClockCmd(RCC_GPIO_DATA, ENABLE);  //Open port B clock 
     GPIO_InitStructure.GPIO_Pin  = GPIO_DATA_0_PIN|GPIO_DATA_1_PIN|GPIO_DATA_2_PIN|GPIO_DATA_3_PIN|GPIO_DATA_4_PIN|GPIO_DATA_5_PIN|GPIO_DATA_6_PIN|GPIO_DATA_7_PIN; //  DB8~DB15
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //Standard output mode
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M clock speed
     GPIO_Init(GPIO_DATA_0, &GPIO_InitStructure);      //Initialize port

	 /********Enable port settings**********/
	 RCC_APB2PeriphClockCmd(RCC_GPIO_EN, ENABLE);    	//Open port clock 
     GPIO_InitStructure.GPIO_Pin =  GPIO_EN_PIN;     	// Enable port
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //Standard output mode
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M clock speed
     GPIO_Init(GPIO_EN, &GPIO_InitStructure);

	 /********Read / write port settings**********/
	 RCC_APB2PeriphClockCmd(RCC_GPIO_RW, ENABLE);    //Open port clock 
     GPIO_InitStructure.GPIO_Pin =  GPIO_RW_PIN;     // Enable port
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  //Standard output mode
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M clock speed
     GPIO_Init(GPIO_RW, &GPIO_InitStructure);

	 /********Command / data port settings**********/
	 RCC_APB2PeriphClockCmd(RCC_GPIO_RS, ENABLE);    //Open port clock 
     GPIO_InitStructure.GPIO_Pin =  GPIO_RS_PIN;     // Enable port
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Push pull multiplex output
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M clock speed
     GPIO_Init(GPIO_RS, &GPIO_InitStructure);


}
/******************************************************************/



void Lcd_Init( void )  //initialization
{  
    Lcd_GPIO_init();
    delay_us(1500);                     //Delay 15ms
    Lcd_Write_Command( 0x38,0);       // The write instruction 38H does not detect the busy signal
    delay_us(500);				      //Delay 5ms
    Lcd_Write_Command( 0x38,0);       // The write instruction 38H does not detect the busy signal
    delay_us(500);					  //Delay 5ms
    Lcd_Write_Command( 0x38,0);       // The write instruction 38H does not detect the busy signal
    //After that, the busy signal shall be detected before each write instruction and read / write data operation
    Lcd_Write_Command( 0x38,1);       //Display mode settings 
    Lcd_Write_Command( 0x08,1);		  //Display off
    Lcd_Write_Command( 0x01,1);       //Display clear screen
    Lcd_Write_Command( 0x06,1);       //Display cursor movement settings 
    Lcd_Write_Command( 0x0C,1); 	  //Display on, cursor not displayed
} 
/******************************************************/

void Lcd_En_Toggle(void) //Enable pulse
{
	SET_EN;        //Enable 1
	delay_us(5);   //Delay 160us
	CLE_EN;
}


void Lcd_Busy(void)//Judgment busy
{
    unsigned int later0=0;
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_GPIO_DATA, ENABLE);    //Open DATA port clock 

    GPIO_InitStructure.GPIO_Pin  = 	GPIO_DATA_0_PIN|GPIO_DATA_1_PIN|GPIO_DATA_2_PIN|GPIO_DATA_3_PIN|GPIO_DATA_4_PIN|GPIO_DATA_5_PIN|GPIO_DATA_6_PIN|GPIO_DATA_7_PIN; //  DB8~DB15
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //Input mode = pull up input
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M clock speed
    GPIO_Init(GPIO_DATA_7, &GPIO_InitStructure);      //Open busy detection port

    CLE_RS; //RS = 0
    //delay_us(1);   // Delay 10us
    SET_RW; //RW = 1
    //delay_us(1);   // Delay 10us
    SET_EN; //EN = 1
    //delay_us(2);   // Delay 20us
    while ((GPIO_ReadInputDataBit(GPIO_DATA_7,GPIO_DATA_7_PIN))&&(later0<20000)) //Circular waiting busy detection port = 0
    {
        delay_us(5);
        later0++;	
    }
    CLE_EN; //EN = 0

    //Restore port to output state 
    RCC_APB2PeriphClockCmd(RCC_GPIO_DATA, ENABLE);    //Open DATA port clock 
    GPIO_InitStructure.GPIO_Pin  = GPIO_DATA_0_PIN|GPIO_DATA_1_PIN|GPIO_DATA_2_PIN|GPIO_DATA_3_PIN|GPIO_DATA_4_PIN|GPIO_DATA_5_PIN|GPIO_DATA_6_PIN|GPIO_DATA_7_PIN; //  DB8~DB15
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //Push pull output
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //50M clock speed
    GPIO_Init(GPIO_DATA_7, &GPIO_InitStructure);

} 

void Gpio_data(unsigned char x)  //Port placement data
{  
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_0_PIN);  //DB0
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_1_PIN);  //DB1
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_2_PIN);  //DB2
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_3_PIN);  //DB3
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_4_PIN);  //DB4
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_5_PIN);  //DB5
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_6_PIN);  //DB6
    GPIO_ResetBits(GPIO_DATA_0, GPIO_DATA_7_PIN);  //DB7
    if(x&0X01)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_0_PIN);//DB0
    if(x&0X02)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_1_PIN);//DB1
    if(x&0X04)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_2_PIN);//DB2
    if(x&0X08)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_3_PIN);//DB3
    if(x&0X10)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_4_PIN);//DB4
    if(x&0X20)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_5_PIN);//DB5
    if(x&0X40)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_6_PIN);//DB6
    if(x&0X80)GPIO_SetBits(GPIO_DATA_0, GPIO_DATA_7_PIN);//DB7
}

//Write instruction sequence to LCD: RS=L,RW=L,Data0-Data7 = instruction code, E = high pulse
void Lcd_Write_Command(unsigned char x,char Busy) 
{ 
    if(Busy) Lcd_Busy();
    //delay_us(1);   // Delay 10us
	CLE_RS;  //RS = 0 
    //delay_us(1);   // Delay 10us
	CLE_RW;  //RW = 0 
    //delay_us(4);   // Delay 40us
    Gpio_data(x);  //Port placement data
    //delay_us(4);   // Delay 40us
	Lcd_En_Toggle();  //Enable pulse
    //delay_us(1);   // Delay 100us
	Lcd_Busy(); //Busy measurement

}
//Time sequence for writing data into LCD: RS=H,RW=L,Data0-Data7 = instruction code, E = high pulse
void Lcd_Write_Data( unsigned char x) //Write data to the LCD 
{ 
	Lcd_Busy(); //Busy measurement
    //delay_us(1);   // Delay 10us
	SET_RS;   //RS = 1 
    //delay_us(1);   // Delay 10us
    CLE_RW;   //RW = 0
    //delay_us(4);   // Delay 40us
    Gpio_data(x);
    //delay_us(4);   // Delay 40us
	Lcd_En_Toggle();  //Enable pulse
    //delay_us(1);   // Delay 100us
	Lcd_Busy(); //Busy measurement

} 
void Lcd_SetXY(unsigned char x,unsigned char y)   //Character initial position setting, x represents column and y represents row 
{ 
    unsigned char addr; 
    if(y==0) 
        addr=0x80+x; 
    else if(y==1)
        addr=0xC0+x; 
    Lcd_Write_Command(addr,1) ; 
} 
void Lcd_Puts(unsigned char x,unsigned char y, unsigned char *string) //Write a string to 1602 
{ 
    Lcd_SetXY(x,y); 
    while(*string) 
    { 
        Lcd_Write_Data(*string); 
        string++; 
    } 
}
void Lcd_1Put(unsigned char x,unsigned char y, unsigned char Data0)
{
   	Lcd_SetXY(x,y); 
	Lcd_Write_Data(Data0); 
}

4.5. DS18B20 temperature sensor

#include "ds18b20.h"
#include "delay.h"	
  
	//IO direction setting
//#define DS18B20_IO_IN()  {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;}
//#define DS18B20_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;}

void DS18B20_IO_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

 	RCC_APB2PeriphClockCmd(RCC_GPIO_DQ,ENABLE);//Enable PORTA,PORTC clock
	
	GPIO_InitStructure.GPIO_Pin  = GPIO_DQ_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //Set as pull-up input
 	GPIO_Init(GPIO_DQ, &GPIO_InitStructure);//initialization
}

void DS18B20_IO_OUT(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;
 	
 RCC_APB2PeriphClockCmd(RCC_GPIO_DQ, ENABLE);	 //Enable
	
 GPIO_InitStructure.GPIO_Pin = GPIO_DQ_PIN;				 
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //Push pull output
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;		 //The speed of IO port is 50MHz
 GPIO_Init(GPIO_DQ, &GPIO_InitStructure);					 //Initialize according to the set parameters
}
//Initialize the IO port DQ of DS18B20 and detect the existence of DS at the same time
//Return 1: does not exist
//Return 0: exists    	 
u8 DS18B20_Init(void)
{
 	GPIO_InitTypeDef  GPIO_InitStructure;
 	
 	RCC_APB2PeriphClockCmd(RCC_GPIO_DQ, ENABLE);	 //Enable PORTA port clock 
	
 	GPIO_InitStructure.GPIO_Pin = GPIO_DQ_PIN;				//PORTA0 push pull output
 	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		  
 	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIO_DQ, &GPIO_InitStructure);

 	GPIO_SetBits(GPIO_DQ,GPIO_DQ_PIN);    //Output 1

	DS18B20_Rst();

	return DS18B20_Check();
}  


//Reset DS18B20
void DS18B20_Rst(void)	   
{                 
	DS18B20_IO_OUT(); //SET PA0 OUTPUT
    DS18B20_DQ_OUT=0; //Pull down DQ
    delay_us(750);    //Pull down 750us
    DS18B20_DQ_OUT=1; //DQ=1 
	delay_us(15);     //15US
}
//Waiting for a response from DS18B20
//Return 1: the existence of DS18B20 is not detected
//Return 0: exists
u8 DS18B20_Check(void) 	   
{   
	u8 retry=0;
	DS18B20_IO_IN();//SET PA0 INPUT	 
    while (DS18B20_DQ_IN&&retry<200)
	{
		retry++;
		delay_us(1);
	};	 
	if(retry>=200)return 1;
	else retry=0;
    while (!DS18B20_DQ_IN&&retry<240)
	{
		retry++;
		delay_us(1);
	};
	if(retry>=240)return 1;	    
	return 0;
}
//Read a bit from DS18B20
//Return value: 1 / 0
u8 DS18B20_Read_Bit(void) 			 // read one bit
{
    u8 data;
	DS18B20_IO_OUT();//SET PA0 OUTPUT
    DS18B20_DQ_OUT=0; 
	delay_us(2);
    DS18B20_DQ_OUT=1; 
	DS18B20_IO_IN();//SET PA0 INPUT
	delay_us(12);
	if(DS18B20_DQ_IN)data=1;
    else data=0;	 
    delay_us(50);           
    return data;
}
//Read a byte from DS18B20
//Return value: read data
u8 DS18B20_Read_Byte(void)    // read one byte
{        
    u8 i,j,dat;
    dat=0;
	for (i=1;i<=8;i++) 
	{
        j=DS18B20_Read_Bit();
        dat=(j<<7)|(dat>>1);
    }						    
    return dat;
}
//Write a byte to DS18B20
//dat: bytes to write
void DS18B20_Write_Byte(u8 dat)     
 {             
    u8 j;
    u8 testb;
	DS18B20_IO_OUT();//SET PA0 OUTPUT;
    for (j=1;j<=8;j++) 
	{
        testb=dat&0x01;
        dat=dat>>1;
        if (testb) 
        {
            DS18B20_DQ_OUT=0;// Write 1
            delay_us(2);                            
            DS18B20_DQ_OUT=1;
            delay_us(60);             
        }
        else 
        {
            DS18B20_DQ_OUT=0;// Write 0
            delay_us(60);             
            DS18B20_DQ_OUT=1;
            delay_us(2);                          
        }
    }
}
//Start temperature conversion
void DS18B20_Start(void)// ds1820 start convert
{   						               
    DS18B20_Rst();	   
	DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0x44);// convert
} 

//Get the temperature value from ds18b20
//Accuracy: 0.1C
//Return value: temperature value (- 550 ~ 1250) 
short DS18B20_Get_Temp(void)
{
    u8 temp;
    u8 TL,TH;
	short tem;
    DS18B20_Start ();                    // ds1820 start convert
    DS18B20_Rst();
    DS18B20_Check();	 
    DS18B20_Write_Byte(0xcc);// skip rom
    DS18B20_Write_Byte(0xbe);// convert	    
    TL=DS18B20_Read_Byte(); // LSB   
    TH=DS18B20_Read_Byte(); // MSB  
	    	  
    if(TH>7)
    {
        TH=~TH;
        TL=~TL; 
        temp=0;//The temperature is negative  
    }else temp=1;//The temperature is positive	  	  
    tem=TH; //Get the top eight
    tem<<=8;    
    tem+=TL;//Get the bottom eight
    tem=(float)tem*0.625;//transformation     
	if(temp)return tem; //Return temperature value
	else return -tem;    
} 

5. System debugging and analysis

5.1 system commissioning

Before the power on commissioning of the overall system, observe that there are still problems in the welded system, such as obvious fracture, reverse connection of positive and negative electrodes, connection, false welding, etc., and then use a multimeter to detect whether there are serious power supply problems such as short circuit between the positive and negative electrodes of the power supply, so as to finally ensure that there is no problem in the welding of the system. After setting up the debugging platform, the software program needs to be debugged. If there is no problem with the program debugging, then start to verify whether the system function meets the requirements. If there is a problem with the function, continue to debug the program and repeat it until all functions are met.

5.2 commissioning phenomenon and analysis

After entering the debugging state, breakpoints should be set at key places, and then run step by step. At the same time, observe the changes of parameters, judge the process of program operation through changes, and then find out the chaotic parts in the program and correct them. This requires a good grasp of the software and a good understanding of the language program. After the experimental board is built successfully, We entered the stage of program design and debugging. We started to write the program smoothly, but later there were many errors in the debugging process, such as the setting of timer accuracy and the call of subroutines. The most difficult thing is the analysis of the execution sequence of the program without steps. Due to the wrong understanding of some statements in the program and the wrong judgment of the execution sequence, Let me fall into a misunderstanding and delay for a long time. Finally, with the help of my classmates, I finally found the wrong key point and corrected it successfully. It seems that I still need to strengthen the debugging ability of the program. The debugging of the program requires patience and proficiency in some functions of the software.

5.3 test results

The system functions normally and can realize the contents specified in the design requirements and purposes. The following is the result diagram:

Keywords: C Single-Chip Microcomputer stm32

Added by crackfox on Tue, 04 Jan 2022 21:47:30 +0200