基于32的水质监测

该代码实现了一个基于STM32的开发板系统,集成了Gizwits协议初始化、OLED显示屏管理、温湿度传感器读取、心率监测以及定时提醒等功能。系统能够显示时间、参数、气体警告和心率信息,并通过中断处理不同事件,如吃药提醒。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

例程是用正点原子的战舰STM32开发板

main.c文件

#include "main.h"
#include "bmp.h"
/************************************************  

************************************************/   
u32 Alarm_Clock_Val = 0 ;
u8 Medicine_Flag = 0; //吃药标志位

void Periph_All_Init(void);
void Set_Alarm_Clock(void);


_bool OledDisplayTimeFlag = FALSE;
_bool OledDisplayParamFlag = FALSE;
_bool OledDisplayGasFlag = FALSE;
_bool Task500MsEventFlag = TRUE;
_bool MedicineEventFlag = TRUE;
_bool HeartRateEventFlag = TRUE;
#define PHVAL_MAX  1000 //PH值报警
/* 用户区当前设备状态结构体*/
dataPoint_t currentDataPoint;

extern gizwitsProtocol_t gizwitsProtocol;
extern u8 display_status;
extern u8 Water_Temp_status;
//WIFI连接状态
//wifi_sta 0: 断开
//         1: 已连接
u8 wifi_sta=0;

//协议初始化
void Gizwits_Init(void)
{    
    TIM3_Int_Init(9,7199);//1MS系统定时
    usart3_init(9600);//WIFI初始化
    memset((uint8_t*)&currentDataPoint, 0, sizeof(dataPoint_t));//设备状态结构体初始化
    gizwitsInit();//缓冲区初始化
}
 int main(void)
 {     
    u8 able[7] = {0x50,0x34,0x20,0x19,0x04,0x05,0x19};
    u8 temp = 0;
    u8 wifi_con=0;//记录wifi连接状态 1:连接 0:断开
    u8 temperature;          
    u8 humidity;    
    Periph_All_Init();
    //gizwitsSetMode(WIFI_RESET_MODE);
    while(1)
    {
        if(Medicine_Flag == 0)
        {
            switch(display_status)
            {
                case 0:
                if(OledDisplayTimeFlag == TRUE)
                {    
                    DS1302_GetTime(able);
                    OledDisplayTimeFlag = FALSE;
                    OLED_Clear_static(1, 2, 7);
                    FuncReg(&OledDisplayTimeFlag, 10000, TRUE);
                    OLED_Show_32_32(16*2-8,2,able[2] / 10 + '0');
                    OLED_Show_32_32(16*3-8,2,able[2] % 10 + '0');
                    OLED_Show_32_32(16*4-8,2,':');
                    OLED_Show_32_32(16*5-8,2,able[1] / 10 + '0');
                    OLED_Show_32_32(16*6-8,2,able[1] % 10 + '0');
                    OLED_ShowChar(32,      6, able[6] / 10 + '0',16);
                    OLED_ShowChar(32+8*1, 6, able[6] % 10 + '0',16);
                    OLED_ShowChar(32+8*2, 6, '-',16);
                    OLED_ShowChar(32+8*3, 6, able[4] / 10 + '0',16);
                    OLED_ShowChar(32+8*4, 6, able[4] % 10 + '0',16);
                    OLED_ShowChar(32+8*5, 6, '-',16);
                    OLED_ShowChar(32+8*6, 6, able[3] / 10 + '0',16);
                    OLED_ShowChar(32+8*7, 6, able[3] % 10 + '0',16);
                    
                }
                OledDisplayGasFlag = TRUE;
                OledDisplayParamFlag = TRUE;
                break;
                case 1:
                {
                    if(OledDisplayParamFlag == TRUE)
                    {
                        OledDisplayParamFlag = FALSE;
                        OLED_Clear_static(2, 2, 7);
                        FuncReg(&OledDisplayParamFlag, 200, TRUE);
                        OLED_ShowCHinese(16 * 0, 2, 12);
                        OLED_ShowCHinese(16 * 1, 2, 13);
                        OLED_ShowChar(16 * 2, 2, ':',16);
                        OLED_ShowCHinese(16 * 6, 2, 16);
                        OLED_ShowNum(16 * 3, 2, temperature, 3, 16);
                        
                        OLED_ShowCHinese(16 * 0, 4, 14);
                        OLED_ShowCHinese(16 * 1, 4, 15);
                        OLED_ShowChar(16 * 2, 4, ':',16);
                        OLED_ShowChar(16 * 6, 4, '%',16);
                        OLED_ShowNum(16 * 3, 4, humidity, 3, 16);
                        
                        OLED_ShowChar(8 * 0, 6, 'M',16);
                        OLED_ShowChar(8 * 1, 6, 'Q',16);
                        OLED_ShowChar(8 * 2, 6, '_',16);
                        OLED_ShowChar(8 * 3, 6, '1',16);
                        OLED_ShowChar(8 * 4, 6, ':',16);
                        OLED_ShowNum(16 * 3, 6, ADC_Val[0], 4, 16);
                        
                    }
                    OledDisplayTimeFlag = TRUE;
                    OledDisplayGasFlag = TRUE;
                }
                    break;    
                
                case 2:
                    if(OledDisplayGasFlag == TRUE)
                    {
                        OledDisplayGasFlag = FALSE;
                        FuncReg(&OledDisplayGasFlag, 5000, TRUE);
                        OLED_Clear_static(3, 2, 7);
                        OLED_ShowCHinese(16 * 0, 2, 30);
                        OLED_ShowCHinese(16 * 1, 2, 31);
                        OLED_ShowCHinese(16 * 2, 2, 32);
                        OLED_ShowCHinese(16 * 3, 2, 33);
                        OLED_ShowCHinese(16 * 4, 2, 34);
                        OLED_ShowCHinese(16 * 5, 2, 35);
                        OLED_ShowCHinese(16 * 6, 2, 36);
                        OLED_ShowCHinese(16 * 0, 4, 37);
                        OLED_ShowCHinese(16 * 1, 4, 38);
                        OLED_ShowCHinese(16 * 2, 4, 39);
                        OLED_ShowCHinese(16 * 3, 4, 40);
                        OLED_ShowCHinese(16 * 4, 4, 41);
                        OLED_ShowCHinese(16 * 5, 4, 42);
                        OLED_ShowCHinese(16 * 6, 4, 43);
                        OLED_ShowString(0, 6, (u8 *)"  Any Key Exit..",16);
                        Jq_8400_Music_Num(MUSIC_GAS_WARNING);
                    }
                    break;
                
                case 3:
                {
                    OLED_Clear_static(5, 2, 7);
                    OLED_ShowCHinese(0 ,2 ,27);
                    OLED_ShowCHinese(16 ,2 ,28);
                    OLED_ShowCHinese(16 * 2 ,2 ,29);
                    OLED_ShowChar(16 * 3, 2, ':',16);
                    temp = Heart_Rate();    
                    display_status = 4;    
                }
                break;    
                case 4:
                {
                    if((temp/100) != 0)
                        OLED_Show_32_32(16 * 4 - 8,3,temp/100 + '0');
                    OLED_Show_32_32(16 * 4 +16- 8, 3,(temp % 100)/10 + '0');
                    OLED_Show_32_32(16 * 4 +32- 8, 3,temp % 10 + '0');
                    OLED_ShowString(32-8, 6, (uint8_t *)"          bpm", 16);
                    display_status = 5;
                    if(temp <= 60)
                        Jq_8400_Music_Num(MUSIC_HEART_REAT_LOW);
                    else if(temp < 110)
                        Jq_8400_Music_Num(MUSIC_HEART_REAT_NORMAL);
                    else
                        Jq_8400_Music_Num(MUSIC_HEART_REAT_HIGH);
                }
                break;
                default: break;
            }
        }
        else if(MedicineEventFlag)
        {
            MedicineEventFlag = FALSE;
            FuncReg(&MedicineEventFlag, 5000, TRUE);
            
            OLED_Clear_static(4, 2, 7);
            OLED_ShowCHinese(18 * 0, 2, 17);
            OLED_ShowCHinese(18 * 1, 2, 18);
            OLED_ShowCHinese(18 * 2, 2, 19);
            OLED_ShowCHinese(18 * 3, 2, 20);
            OLED_ShowCHinese(18 * 4, 2, 21);
            OLED_ShowCHinese(18 * 2, 4, 22);
            OLED_ShowCHinese(18 * 3, 4, 23);
            OLED_ShowCHinese(18 * 4, 4, 24);
            OLED_ShowCHinese(18 * 5, 4, 25);
            OLED_ShowCHinese(18 * 6, 4, 26);
            OLED_ShowString(0, 6, (u8 *)"  Any Key Exit..",16);
            Jq_8400_Music_Num(MUSIC_MEDICINE);
        }
        
            
        if(Task500MsEventFlag == TRUE)
        {
            Task500MsEventFlag = FALSE;
            FuncReg(&Task500MsEventFlag, 500, TRUE);
            currentDataPoint.valueHum = humidity;
            currentDataPoint.valueGas = ADC_Val[0];
            currentDataPoint.valueHeart_Rate = temp;
            if(ADC_Val[0] > PHVAL_MAX){
                BUZEER_ENABLE;
                display_status = 2;
            }
            else{
                BUZEER_DISABLE;
            }
            currentDataPoint.valueTemp = temperature;
            DHT11_Read_Data(&temperature,&humidity);    //读取温湿度值
            currentDataPoint.valuerssi = gizwitsProtocol.wifiStatusData.rssi;
        }
                                

    
        if(wifi_con!=wifi_sta)
         {
             wifi_con=wifi_sta;
             //wifi_con?printf("connect"):printf("close");
         }
        

        gizwitsHandle((dataPoint_t *)&currentDataPoint);//协议处理
        
        
        
        
        
        
//        key = KEY_Scan(0);
//        if(key==KEY1_PRES)//KEY1按键
//        {
//            printf("WIFI进入AirLink连接模式\r\n");
//            gizwitsSetMode(WIFI_AIRLINK_MODE);//Air-link模式接入
//        }            
//        if(key == KEY1_PRES)//KEY_UP按键
//        {  
//            printf("WIFI复位,请重新配置连接\r\n");
//            gizwitsSetMode(WIFI_RESET_MODE);//WIFI复位 
//            wifi_sta=0;//标志wifi已断开
//        }

    }
}
 




void Periph_All_Init(void)
{
    delay_init();             //延时函数初始化    
    //KEY_Init();     
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
    Periph_Init();                  //初始化与LED连接的硬件接口 
     Key_Io_Init();
    BUZEER_DISABLE;
    uart_init(115200);
    usart2_init(9600);
    Gizwits_Init();         //协议初始化
    OLED_Init();            //初始化OLED  
    DHT11_Init();
    Adc_Init();
    OLED_Clear(); 
    Ds1302_GpioInit();
    Jq_8400_Set_Volume(20);
    delay_ms(10);
    Jq_8400_Music_Num(MUSIC_INIT);
    //DS1302_Initial();
    //DS1302_SetTime(able);
    //DS1302_GetTime(able);
    OLED_DrawBMP(0,0,128,1,BMP1);
    OLED_ShowCHinese(18 * 1, 2, 0);
    OLED_ShowCHinese(18 * 2, 2, 1);
    OLED_ShowCHinese(18 * 3, 2, 2);
    OLED_ShowChar(18 * 4, 2, 'N',16);
    OLED_ShowChar(18 * 5 - 8, 2, 'I',16);
    OLED_ShowChar(18 * 5, 2, 'I',16);
    OLED_ShowChar(18 * 6 - 8, 2, 'T',16);
    OLED_ShowCHinese(18 * 1, 4, 3);
    OLED_ShowCHinese(18 * 2, 4, 4);
    OLED_ShowCHinese(18 * 3, 4, 5);
    OLED_ShowCHinese(18 * 4, 4, 6);
    OLED_ShowCHinese(18 * 5, 4, 7);
    OLED_ShowCHinese(18 * 6, 4, 8);
    OLED_ShowChar(18 * 3, 6, '-', 16);
    OLED_ShowCHinese(18 * 4, 6, 9);
    OLED_ShowCHinese(18 * 5, 6, 10);
    OLED_ShowCHinese(18 * 6, 6, 11);
    FuncReg(&OledDisplayTimeFlag, 5000, TRUE);
}

void Set_Alarm_Clock(void)
{
    static u8 previousvalueTime = 0;
    if(previousvalueTime != currentDataPoint.valueTime)
    {
        switch(currentDataPoint.valueTime)
        {
          case Time_VALUE0:        //未定义
            Alarm_Clock_Val = 0;
            //user handle
            break;
          case Time_VALUE1:        //10S
            Alarm_Clock_Val = 10;
            //user handle
            break;
          case Time_VALUE2:        //100S
            Alarm_Clock_Val = 100;
            //user handle
            break;
          case Time_VALUE3:        //1000S
            Alarm_Clock_Val = 1000;
            //user handle
            break;
          case Time_VALUE4:        //1分钟
            //user handle
            Alarm_Clock_Val = 60;
            break;
          case Time_VALUE5:        //10分钟
            //user handle
            Alarm_Clock_Val = 60 * 10;
            break;
          case Time_VALUE6:        //100分钟
            //user handle
            Alarm_Clock_Val = 60 * 100;
            break;
          case Time_VALUE7:        //1小时
            //user handle
            Alarm_Clock_Val = 60 * 60;
            break;
          case Time_VALUE8:        //2小时
            //user handle
            Alarm_Clock_Val = 60 * 60 * 2;
            break;
          case Time_VALUE9:        //4小时
            //user handle
            Alarm_Clock_Val = 60 * 60 * 4;
            break;
          case Time_VALUE10:    //12小时
            //user handle
            Alarm_Clock_Val = 60 * 60 * 12;
            break;
          case Time_VALUE11:    //24小时
            //user handle
            Alarm_Clock_Val = 60 * 60 * 24;
            break;
          default:
            break;
        }
    }
    previousvalueTime = currentDataPoint.valueTime;
    
}

ds1203.c文件

#include "ds1302.h"




void Ds1302_GpioInit(void)
{
    GPIO_InitTypeDef GPIO_InitTypeState;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
    GPIO_InitTypeState.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitTypeState.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_13;
    GPIO_InitTypeState.GPIO_Speed = GPIO_Speed_50MHz; 
    GPIO_Init(GPIOB, &GPIO_InitTypeState);
    
    GPIO_InitTypeState.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitTypeState.GPIO_Pin = GPIO_Pin_14;    
    GPIO_Init(GPIOB, &GPIO_InitTypeState);
}


u8 DS1302_ReadByte()
{
    u8 i;
    u8 dat = 0;
    IO_IN();
    for (i=0; i<8; i++)             //8位计数器
    {
        SCLK = 0;                   //时钟线拉低
        delay_us(2);
        dat >>= 1;                  //数据右移一位
        if (IOIN) dat |= 0x80;        //读取数据
        SCLK = 1;                   //时钟线拉高
        delay_us(2);
    }

    return dat;
}

/**************************************
向DS1302写1字节数据
**************************************/
void DS1302_WriteByte(u8 dat)
{
    char i;
    IO_OUT();
    for (i=0; i<8; i++)             //8位计数器
    {
        SCLK = 0;                   //时钟线拉低
        delay_us(2);
        IOOUT = (dat & 0X01);                    //送出到端口
        dat >>= 1;                  //移出数据
        SCLK = 1;                   //时钟线拉高
        delay_us(2);
    }
}

/**************************************
读DS1302某地址的的数据
**************************************/
u8 DS1302_ReadData(u8 addr)
{
    u8 dat;

    RST = 0;
    delay_us(2);
    SCLK = 0;
    delay_us(2);
    RST = 1;
    delay_us(2);
    DS1302_WriteByte(addr);         //写地址
    dat = DS1302_ReadByte();        //读数据
    SCLK = 1;
    RST = 0;

    return dat;
}

/**************************************
往DS1302的某个地址写入数据
**************************************/
void DS1302_WriteData(u8 addr, u8 dat)
{
    RST = 0;
    delay_us(2);
    SCLK = 0;
    delay_us(2);
    RST = 1;
    delay_us(2);
    DS1302_WriteByte(addr);         //写地址
    DS1302_WriteByte(dat);          //写数据
    SCLK = 1;
    RST = 0;
}

/**************************************
写入初始时间
**************************************/
void DS1302_SetTime(u8 *p)
{
    u8 addr = 0x80;
    u8 n = 7;

    DS1302_WriteData(0x8e, 0x00);   //允许写操作
    while (n--)
    {
        DS1302_WriteData(addr, *p++);
        addr += 2;
    }
    DS1302_WriteData(0x8e, 0x80);   //写保护
}

/**************************************
读取当前时间
**************************************/
void DS1302_GetTime(u8 *p)
{
    u8 addr = 0x81;
    u8 n = 7;
    u8 temp = 0;

    while (n--)
    {
        temp = DS1302_ReadData(addr);
        *p = ((temp)>>4)*10 + ((temp)&0x0F);
        p++;
        addr += 2;
    }
}

/**************************************
初始化DS1302
**************************************/
void DS1302_Initial()
{
    RST = 0;
    SCLK = 0;
    DS1302_WriteData(0x8e, 0x00);   //允许写操作
    DS1302_WriteData(0x80, 0x00);   //时钟启动
    DS1302_WriteData(0x90, 0xa6);   //一个二极管+4K电阻充电
    DS1302_WriteData(0x8e, 0x80);   //写保护
}

使用iic通信

#include "myiic.h"
#include "delay.h"

//初始化IIC
void IIC_Init(void)
{                         
    GPIO_InitTypeDef GPIO_InitStructure;
    //RCC->APB2ENR|=1<<4;//先使能外设IO PORTC时钟 
    RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE );    
       
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
 
    IIC_SCL=1;
    IIC_SDA=1;

}
//产生IIC起始信号
void IIC_Start(void)
{
    SDA_OUT();     //sda线输出
    IIC_SDA=1;            
    IIC_SCL=1;
    delay_us(4);
     IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
    delay_us(4);
    IIC_SCL=0;//钳住I2C总线,准备发送或接收数据 
}      
//产生IIC停止信号
void IIC_Stop(void)
{
    SDA_OUT();//sda线输出
    IIC_SCL=0;
    IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
     delay_us(4);
    IIC_SCL=1; 
    IIC_SDA=1;//发送I2C总线结束信号
    delay_us(4);                                   
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
    u8 ucErrTime=0;
    SDA_IN();      //SDA设置为输入  
    IIC_SDA=1;delay_us(1);       
    IIC_SCL=1;delay_us(1);     
    while(READ_SDA)
    {
        ucErrTime++;
        if(ucErrTime>250)
        {
            IIC_Stop();
            return 1;
        }
    }
    IIC_SCL=0;//时钟输出0        
    return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=0;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
}
//不产生ACK应答            
void IIC_NAck(void)
{
    IIC_SCL=0;
    SDA_OUT();
    IIC_SDA=1;
    delay_us(2);
    IIC_SCL=1;
    delay_us(2);
    IIC_SCL=0;
}                                          
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答              
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
    SDA_OUT();         
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1;       
        delay_us(2);   //对TEA5767这三个延时都是必须的
        IIC_SCL=1;
        delay_us(2); 
        IIC_SCL=0;    
        delay_us(2);
    }     
}         
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
    unsigned char i,receive=0;
    SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
    {
        IIC_SCL=0; 
        delay_us(2);
        IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
        delay_us(1); 
    }                     
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}


void IIC_WriteBytes(u8 WriteAddr,u8* data,u8 dataLength)
{        
    u8 i;    
    IIC_Start();  

    IIC_Send_Byte(WriteAddr);        //发送写命令
    IIC_Wait_Ack();
    
    for(i=0;i<dataLength;i++)
    {
        IIC_Send_Byte(data[i]);
        IIC_Wait_Ack();
    }                           
    IIC_Stop();//产生一个停止条件 
    delay_ms(10);     
}

void IIC_ReadBytes(u8 deviceAddr, u8 writeAddr,u8* data,u8 dataLength)
{        
    u8 i;    
    IIC_Start();  

    IIC_Send_Byte(deviceAddr);        //发送写命令
    IIC_Wait_Ack();
    IIC_Send_Byte(writeAddr);
    IIC_Wait_Ack();
    IIC_Send_Byte(deviceAddr|0X01);//进入接收模式               
    IIC_Wait_Ack();
    
    for(i=0;i<dataLength-1;i++)
    {
        data[i] = IIC_Read_Byte(1);
    }        
    data[dataLength-1] = IIC_Read_Byte(0);    
    IIC_Stop();//产生一个停止条件 
    delay_ms(10);     
}

void IIC_Read_One_Byte(u8 daddr,u8 addr,u8* data)
{                                                                                                 
    IIC_Start();  
    
    IIC_Send_Byte(daddr);       //发送写命令
    IIC_Wait_Ack();
    IIC_Send_Byte(addr);//发送地址
    IIC_Wait_Ack();         
    IIC_Start();              
    IIC_Send_Byte(daddr|0X01);//进入接收模式               
    IIC_Wait_Ack();     
    *data = IIC_Read_Byte(0);           
    IIC_Stop();//产生一个停止条件        
}

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data)
{                                                                                                  
    IIC_Start();  
    
    IIC_Send_Byte(daddr);        //发送写命令
    IIC_Wait_Ack();
    IIC_Send_Byte(addr);//发送地址
    IIC_Wait_Ack();                                                                 
    IIC_Send_Byte(data);     //发送字节                               
    IIC_Wait_Ack();                     
    IIC_Stop();//产生一个停止条件 
    delay_ms(10);     
}



























这些只是部分代码源代码放链接里了

链接:https://pan.baidu.com/s/1Cfk25AFRfZ3JWcVONCNMzw

提取码:1111

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值