打印
[产品应用]

基于CW32的智能家居系统

[复制链接]
585|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
例程资料链接如下(群文件也可下载):
BD网盘链接:
https://pan.baidu.com/s/1N7MQY7ETFAbKXCm9ZKGYHA?pwd=pqyq
提取码:pqyq
相关视频:基于CW32的智能家居系统

一、实验简介

本智能家居系统是一款功能丰富、易于使用的智能家居解决方案,可以通过检测温湿度、光照强度和空气质量等参数,为我们提供更加舒适、健康、安全的居住环境,让用户享受更加智能的生**验。

该系统采用CW32F030单片机作为核心控制器,通过各种传感器实时监测室内环境参数,并根据预设的阈值进行相应控制。例如,当室内光照不足时,系统会自动打开灯光,确保室内光线充足。室内温湿度数据和空气质量通过屏幕显示,并实时上传到云平台,以实现远程监控。

二、实验器材

本实验使用到了CW32-48F大学计划开发板、ESP8266WIFI模块、DHT11温湿度模块、MQ-135空气检测传感器、光敏电阻模块、热释电传感器模块、LED交通灯模块及Keil5开发环境。





实物图

开发板上预留了ESP8266WIFI模块接口,通过串口与ESP8266通信。



开发板上预留了DHT11模块接口



【MQ-135空气传感器模块与单片机接线】:
VCC – 5V
GND – GND
DO – ×
AO – PA0
【光敏电阻模块与单片机接线】:
VCC – 3.3V
GND – GND
DO – ×
AO – PA4
【热释电人体感应模块与单片机接线】:
VCC – 3.3V
GND – GND
OUT – PB10
【LED交通灯模块与单片机接线】:
R – PA6
Y – PA5
G – PB11
GND – GND


三、核心代码
main.c:
/*传感器数据*/
uint16_t ppm=0;            //空气中甲苯浓度
uint8_t humidity=0;        //湿度
uint8_t temperture=0;      //温度
uint8_t Light_intensity=0; //光照强度(0~100)
uint16_t adc_result[2]={0}; //保存ADC序列转换结果

/*标识控制位*/
_Bool Flag_5s=0;       //5s计时
uint16_t time5scnt=0;  //5s计数
uint16_t time2scnt=0;  //2s计数
_Bool averyflag=0;    //ADC序列采集完成标志位
_Bool send_flag=0;    //数据上云控制位

/*自定义函数*/
void PIR_Proc(void);    //检测人是否存在
void DHT11_Proc(void);  //采集温湿度
void MQ135_Proc(void);  //检测空气质量
void Photo_Proce(void); //检测亮度
void System_Init(void); //系统初始化
void Send2OneNet(void); //数据上云
void Interface(void);   //数据显示界面
void LED_Proc(uint8_t led,uint8_t state); //LED灯

/*主程序*/
int main(void)
{
        System_Init();  //系统初始化
        Interface();    //界面显示
        while(1)
        {       
                PIR_Proc();           //人
                DHT11_Proc();  //温湿度
                MQ135_Proc();  //空气质量
                Photo_Proce(); //光强
                Send2OneNet(); //数据上云
                ADC_SoftwareStartConvCmd(ENABLE); //启动ADC转换
                Delay_ms(500);
        }
}

/*子程序*/
void System_Init(void)  //系统初始化函数
{               
        Lcd_Init();        
        TFT_Welcome(); //开机界面
       
        LED_Init();   
        PIR_Init();           //热释电传感器初始化
        DHT11_Init();  //温湿度传感器初始化
        Buzzer_Init(); //蜂鸣器初始化
        while(DHT11_Check()); //检测DHT11是否已连接
       
        BTIM_Init();  
//        Usart1_Init(115200);  //调试串口
        Usart2_Init(115200);  //ESP8266串口
        ESP8266_Init();       //ESP8266初始化
        ADC_Configuration();  //ADC序列多次转换模式配置
}

void Interface(void)    //界面显示函数
{
        Lcd_Clear(BLUE);
        Gui_DrawFont_GBK16(0,8,WHITE,BLUE,"  智能家居系统 ");
        Gui_DrawLine(0,32,128,32,GRAY1);                       //分割线
        Gui_DrawFont_GBK16(0,48,WHITE,BLUE," 当前温度:");
        Gui_DrawFont_GBK16(0,80,WHITE,BLUE," 当前湿度:");
        Gui_DrawFont_GBK16(0,112,WHITE,BLUE," 空气质量:");
}

void PIR_Proc(void)   //人体检测函数
{
        if(ReadPIR())    //有人在
        {
                Flag_5s=1;   //在中断中开始5s计时
                LED_Proc(LED_Yellow,1); //打开黄灯
        }
        else             //没有人
        {
                Flag_5s=0;   //清除计时标识
                time5scnt=0; //清零计数值
                Buzzer(0);         //关闭蜂鸣器
                LED_Proc(LED_Red,0); //关闭红灯
                LED_Proc(LED_Yellow,0); //关闭红灯
        }
       
        if(time5scnt>=500) //计数值超过500,5秒计时到
        {
                time5scnt=0;  //清零计数值
                Buzzer(1);    //打开蜂鸣器
                LED_Proc(LED_Red,1); //打开红灯
        }       
}

void DHT11_Proc(void)  //温湿度采集函数
{
        char display[8]=" ";
       
        DHT11_Read_Data(&temperture,&humidity);  //采集温湿度
        sprintf(display,"%d ℃",temperture);
        TFTShowString(3,11,display);
        sprintf(display,"%d %%",humidity);
        TFTShowString(5,11,display);
}

void MQ135_Proc(void)   //空气质量检测函数
{
        double v_dat=0;
       
        if(averyflag)    //ADC转换完成
        {
                adc_result[0]/=10;  //采集10次求平均值
                v_dat=(double)adc_result[0]*3.3/4960.0;  //AD值传换成电压
                ppm = pow((3.4880*10*v_dat)/(5-v_dat),(1.0/0.3203)); //计算甲苯浓度(参数因环境而异)
                if(v_dat<0.3)      Gui_DrawFont_GBK16(90,112,WHITE,BLUE,"优");  //依据电压值人为划分空气质量等级
                else if(v_dat<0.5) Gui_DrawFont_GBK16(90,112,WHITE,BLUE,"良");
                else                           Gui_DrawFont_GBK16(90,112,WHITE,BLUE,"差");
        }
}

void Photo_Proce(void)   //光照强度采集函数
{
        double v_dat=0;  
       
        if(averyflag)  //ADC转换完毕
        {
                adc_result[1]/=10;  //求平均值
                Light_intensity=(1.0-(float)adc_result[1]/4096.0)*100.0;  //转换成光照强度(仅供参考)
                v_dat=(double)adc_result[1]*3.3/4960.0; //转换成电压值
               
                if(v_dat>1.5) LED_Proc(LED_Green,1);  //自定义阈值,光照强度过低打开绿灯
                else                  LED_Proc(LED_Green,0);               
        }
}

void LED_Proc(uint8_t led,uint8_t state)  //LED控制函数
{
        if(led==LED_Red)
                GPIO_WritePin(CW_GPIOA,GPIO_PIN_6,(GPIO_PinState)(state));
        else if(led==LED_Yellow)
                GPIO_WritePin(CW_GPIOA,GPIO_PIN_5,(GPIO_PinState)(state));
        else if(led==LED_Green)
                GPIO_WritePin(CW_GPIOB,GPIO_PIN_11,(GPIO_PinState)(state));
}

void Send2OneNet(void)  //数据上传函数
{
        if(send_flag)
        {               
                OneNet_SendData();        //数据上传到OneNET
                ESP8266_Clear();    //清除缓存
                send_flag=0;  
        }
}

void BTIM1_IRQHandler(void)   //基本定时器1中断
{
  if(BTIM_GetITStatus(CW_BTIM1,BTIM_IT_OV))  
        {
                if(++time2scnt>200) {send_flag=1;time2scnt=0;} //2s计时
                if(Flag_5s) time5scnt++;                       //5s计时
                BTIM_ClearITPendingBit(CW_BTIM1,BTIM_IT_OV); //清除标志位
        }
}



四、效果演示



————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

原文链接:https://blog.csdn.net/2302_81038468/article/details/136456863

使用特权

评论回复
沙发
weifeng90| | 2025-3-7 22:59 | 只看该作者
这个只能说是演示原理的,实际产品还是差异很大的。

使用特权

评论回复
板凳
小小蚂蚁举千斤| | 2025-3-13 22:11 | 只看该作者
芯源的开发板嘛?

使用特权

评论回复
地板
jf101| | 2025-3-20 17:28 | 只看该作者
CW32-48F大学计划开发板如何获取的?

使用特权

评论回复
5
rickluo| | 2025-3-22 11:44 | 只看该作者



温湿度传感器 IIC源代码分享

#define GET_I2C_SDA()             GPIO_ReadDataBit(GPIOF,GPIO_Pin_7)    // 读取SDA端口
#define SET_I2C_SCL()             GPIO_SetBits(GPIOF,GPIO_Pin_6)          // 时钟线SCL输出高电平
#define CLR_I2C_SCL()             GPIO_ResetBits(GPIOF,GPIO_Pin_6)        // 时钟线SCL输出低电平
#define SET_I2C_SDA()             GPIO_SetBits(GPIOF,GPIO_Pin_7)          // 数据线SDA输出高电平
#define CLR_I2C_SDA()             GPIO_ResetBits(GPIOF,GPIO_Pin_7)        // 数据线SDA输出低电平
#define I2C_DELAY           10            
static void GpioInit(void)
{
         /*配置I2C管脚的功能 */
         GPIO_InitTypeDefGPIO_InitStructure;//定义一个GPIO_InitTypeDef类型的结构体
         GPIO_InitStructure.GPIO_Pin= GPIO_Pin_6 | GPIO_Pin_7;//选择要控制的GPIO引脚
         GPIO_InitStructure.GPIO_Mode= GPIO_Mode_OutOD;//设置引脚模式为
         GPIO_InitStructure.GPIO_Pull= GPIO_Pull_NoPull;//模式
         GPIO_Init(GPIOF,&GPIO_InitStructure);
         
         
//GPIOF GPIO_Pin_7 I2C0 SDA
//GPIOF GPIO_Pin_6 I2C0 SCL
}
/**
*******************************************************************
* @function 产生IIC起始时序,准备发送或接收数据前必须由起始序列开始
* @param
* @brief   SCL为高电平时,SDA由高电平向低电平跳变,开始传输数据
*          生成下图所示的波形图,即为起始时序
*                1 2    3    4   
*                    __________     
*          SCL : __/          \_____
*                 ________         
*          SDA :         \___________
*******************************************************************
*/
static void I2CStart(void)
{
         SET_I2C_SDA();          // 1#数据线SDA输出高电平
         SET_I2C_SCL();          // 2#时钟线SCL输出高电平   
         DelayNus(I2C_DELAY);            // 延时4us
         CLR_I2C_SDA();          // 3#数据线SDA输出低电平
         DelayNus(I2C_DELAY);            // 延时4us
         CLR_I2C_SCL();          // 4#时钟线SCL输出低电平,保持I2C的时钟线SCL为低电平,准备发送或接收数据
         DelayNus(I2C_DELAY);            // 延时4us
}
/**
*******************************************************************
* @function 产生IIC停止时序  
* @param
* @return
* @brief   SCL为高电平时,SDA由低电平向高电平跳变,结束传输数据
*         生成下图所示的波形图,即为停止时序
*                1 2   3 4   
*                       _______________     
*         SCL : ______/         
*                __        ____________  
*         SDA:    \______/
*******************************************************************
*/
static void I2CStop(void)
{
         CLR_I2C_SDA();          //2#数据线SDA输出低电平
         DelayNus(I2C_DELAY);            //延时4us
         SET_I2C_SCL();          //3#时钟线SCL输出高电平
         DelayNus(I2C_DELAY);  
         SET_I2C_SDA();          //4#数据线SDA输出高电平,发送I2C总线结束信号
}
/**
*******************************************************************
* @function 发送一字节,数据从高位开始发送出去
* @param   byte
* @return
* @brief   下面是具体的时序图
*                1 2     3     4
*                         ______
*          SCL: ________/      \______   
*                ______________________   
*          SDA: \\\___________________
*******************************************************************
*/
static void I2CSendByte(uint8_t byte)
{                          
         for(uint8_t i = 0; i < 8; i++)   // 循环8次,从高到低取出字节的8个位
         {     
                   if((byte & 0x80))            // 2#取出字节最高位,并判断为‘0’还是‘1’,从而做出相应的操作
                   {
                            SET_I2C_SDA();            // 数据线SDA输出高电平,数据位为‘1
                   }
                   else
                   {  
                            CLR_I2C_SDA();           // 数据线SDA输出低电平,数据位为‘0
                   }
                  
                   byte<<= 1;                              // 左移一位,次高位移到最高位
                  
                   DelayNus(I2C_DELAY);                     // 延时4us
                   SET_I2C_SCL();                // 3#时钟线SCL输出高电平
                   DelayNus(I2C_DELAY);                     // 延时4us
                   CLR_I2C_SCL();                            // 4#时钟线SCL输出低电平
                   DelayNus(I2C_DELAY);                  // 延时4us  
         }  
}
/**
*******************************************************************
* @function 读取一字节数据
* @param   
* @return  读取的字节
* @brief   下面是具体的时序图
*                       ______
*          SCL: ______/      \___        
*                ____________________   
*          SDA: \\\\______________\\\
*******************************************************************
*/
static uint8_t I2CReadByte(void)
{
         uint8_tbyte = 0;                             // byte用来存放接收的数据
         SET_I2C_SDA();                      // 释放SDA
         for(uint8_t i = 0; i < 8; i++)     // 循环8次,从高到低读取字节的8个位
         {
                   SET_I2C_SCL();                        //时钟线SCL输出高电平
                   DelayNus(I2C_DELAY);                          //延时4us
                   byte<<= 1;                               // 左移一位,空出新的最低位
                   if(GET_I2C_SDA())                     // 读取数据线SDA的数据位
                   {
                            byte++;                                   //SCL的上升沿后,数据已经稳定,因此可以取该数据,存入最低位
                   }
                   CLR_I2C_SCL();                        //时钟线SCL输出低电平
                   DelayNus(I2C_DELAY);                          //延时4us
         }
         returnbyte;                                               // 返回读取到的数据
}
/**
*******************************************************************
* @function 等待接收端的应答信号
* @param   
* @return  1,接收应答失败;0,接收应答成功
* @brief   SDA拉低后,表示接收到ACK信号,然后,拉低SCL
*          此处表示发送端收到接收端的ACK
*                _______|____     
*          SCL:        |    \_________   
*                _______|     
*          SDA:         \_____________
*******************************************************************
*/
static bool I2CWaitAck(void)
{
         uint16_terrTimes = 0;
         
         SET_I2C_SDA();             // 释放SDA总线,很重要
         DelayNus(I2C_DELAY);               // 延时4us
         
         SET_I2C_SCL();             // 时钟线SCL输出高电平
         DelayNus(I2C_DELAY);               // 延时4us
         while(GET_I2C_SDA())      // 读回来的数据如果是高电平,即接收端没有应答
         {
                   errTimes++;            // 计数器加1
                   if(errTimes > 250)    // 如果超过250次,则判断为接收端出现故障,因此发送结束信号
                   {
                            I2CStop();         // 产生一个停止信号
                            returnfalse;      // 返回值为1,表示没有收到应答信号
                   }
         }
         CLR_I2C_SCL();             // 表示已收到应答信号,时钟线SCL输出低电平
         DelayNus(I2C_DELAY);               // 延时4us
         
         returntrue;               // 返回值为0,表示接收应答成功  
}
/**
*******************************************************************
* @function 发送应答信号
* @param   
* @return  
* @brief   下面是具体的时序图
*                 1 2     3     4      5     
*                         ______
*          SCL: ________/     \____________   
*                __                     ______
*          SDA:   \___________________/        
*******************************************************************
*/
void I2CSendAck(void)
{
         CLR_I2C_SDA();          // 2#数据线SDA输出低电平
         DelayNus(I2C_DELAY);            // 延时4us
         SET_I2C_SCL();          // 3#时钟线SCL输出高电平,SCL上升沿前就要把SDA拉低,为应答信号
         DelayNus(I2C_DELAY);            // 延时4us
         CLR_I2C_SCL();          // 4#时钟线SCL输出低电平
         DelayNus(I2C_DELAY);            // 延时4us
         SET_I2C_SDA();          // 5#数据线SDA输出高电平,释放SDA总线,很重要
}
/**
*******************************************************************
* @function 发送非应答信号
* @param   
* @return  
* @brief   下面是具体的时序图
*               1 2     3     4
*                        ______
*         SCL: ________/      \______   
*               __ ___________________   
*         SDA: __/
*******************************************************************
*/
void I2CSendNack(void)
{
         SET_I2C_SDA();          // 2#数据线SDA输出高电平
         DelayNus(I2C_DELAY);            // 延时4us
         SET_I2C_SCL();          // 3#时钟线SCL输出高电平,在SCL上升沿前就要把SDA拉高,为非应答信号
         DelayNus(I2C_DELAY);            // 延时4us
         CLR_I2C_SCL();          // 4#时钟线SCL输出低电平
         DelayNus(I2C_DELAY);            // 延时4us
}
#define NSHT30_DEV_ADDR                            0x44 //NSHT30的设备地址
#define NSHT30_I2C_WR                                       0                //写控制bit
#define NSHT30_I2C_RD                1                // 读控制bit
#define TRIG_TEMP_MEASUREMENT_HM          0xE3   // command trig. temp meas. hold master
#define TRIG_HUMI_MEASUREMENT_HM                0xE5    // command trig. humiditymeas. hold master
#define TRIG_TEMP_MEASUREMENT_POLL            0xF3    // command trig. tempmeas. no hold master
#define TRIG_HUMI_MEASUREMENT_POLL    0xF5    // command trig. humiditymeas. no hold master
#define TRIG_TEMP_HUMI_MEASUREMENT    0x2C06   // command trig.humidity  temp meas
#define NSHT30_SOFT_RESET                0x30A2    // command soft reset
#define NSHT30_RESOLUTION_REG                         0xE6   // 设置分辨率寄存器地址
#define NSHT30_RESOLUTION_VAL                         0x83   // 设置分辨率bit7 = 1,bit0 = 0,对应湿度10bit,温度13bit
#define NSHT30_READ_REG                                              0XE7
//NSHT30驱动代码
#define CMD_MEAS_SINGLE_H 0x2400 //measurement: SINGLE Mode high repeatability
#define CMD_MEAS_SINGLE_M 0x240B //measurement: SINGLE Mode medium repeatability
#define CMD_MEAS_SINGLE_L 0x2416 //measurement: SINGLE Mode low repeatability
#define CMD_MEAS_PERI_05_H 0x2032 //measurement: periodic Mode 0.5 mps high repeatability
#define CMD_MEAS_PERI_05_M 0x2024 //measurement: periodic Mode 0.5 mps medium repeat[1]ability
#define CMD_MEAS_PERI_05_L 0x202F //measurement: periodic Mode 0.5 mps low repeatability
#define CMD_MEAS_PERI_1_H 0x2130 //measurement: periodic Mode 1 mps high repeatability
#define CMD_MEAS_PERI_1_M 0x2126 //measurement: periodic Mode 1 mps medium repeatability
#define CMD_MEAS_PERI_1_L 0x212D //measurement: periodic Mode 1 mps low repeatability
#define CMD_MEAS_PERI_2_H 0x2236 //measurement: periodic Mode 2 mps high repeatability
#define CMD_MEAS_PERI_2_M 0x2220 //measurement: periodic Mode 2 mps medium repeatability
#define CMD_MEAS_PERI_2_L 0x222B //measurement: periodic Mode 2 mps low repeatability
#define CMD_MEAS_PERI_4_H 0x2334 //measurement: periodic Mode 4 mps high repeatability
#define CMD_MEAS_PERI_4_M 0x2322 //measurement: periodic Mode 4 mps medium repeatability
#define CMD_MEAS_PERI_4_L 0x2329 //measurement: periodic Mode 4 mps low repeatability
#define CMD_MEAS_PERI_10_H 0x2737 //measurement: periodic Mode 10 mps high repeatability
#define CMD_MEAS_PERI_10_M 0x2721 //measurement: periodic Mode 10 mps medium repeat[1]ability
#define CMD_MEAS_PERI_10_L 0x272A //measurement: periodic Mode 10 mps low repeatability
static bool Nsht30SoftReset(void)                    
{
         I2CStart();
         I2CSendByte((NSHT30_DEV_ADDR<<1)| NSHT30_I2C_WR);
         if(!I2CWaitAck())
         {
                   gotoi2c_err;
         }
         
         
         I2CSendByte((NSHT30_SOFT_RESET&0xFF00)>>8);
         if(!I2CWaitAck())
         {
                   gotoi2c_err;
         }
         
         I2CSendByte(NSHT30_SOFT_RESET&0xFF);
         if(!I2CWaitAck())
         {
                   gotoi2c_err;
         }
         
         
         I2CStop();
         returntrue;
i2c_err:          // 命令执行失败后,要发送停止信号,避免影响I2C总线上其他设备
         I2CStop();
         returnfalse;
}
static bool Nsht30SetResolution(uint8_t*pBuffer)
{
         uint16_tnumToRead=5;
         
         I2CStart();
         I2CSendByte((NSHT30_DEV_ADDR<<1)| NSHT30_I2C_WR);
         if(!I2CWaitAck())
         {
                   gotoi2c_err;
         }
         
         I2CSendByte((CMD_MEAS_SINGLE_L&0xFF00)>>8);
         if(!I2CWaitAck())
         {
                   gotoi2c_err;
         }
         
         I2CSendByte(CMD_MEAS_SINGLE_L&0xFF);
         if(!I2CWaitAck())
         {
                   gotoi2c_err;
         }
         
         
         I2CStop();
         
         DelayNms(I2C_DELAY);
         I2CStart();                                        // 发送起始信号         
         I2CSendByte((NSHT30_DEV_ADDR<<1)| NSHT30_I2C_RD);      // 发送器件地址和读写模式,1 0 1 0 x  x  x R/~W  0xA1           
         if(!I2CWaitAck())                                // 等待应答
         {
                   gotoi2c_err;
         }
         
         while(numToRead--)                                // 数据未读完
         {
                   *pBuffer++= I2CReadByte();                   // 逐字节读出存放到数据数组
                   I2CSendAck();
         }
         *pBuffer= I2CReadByte();                        // 最后一个字节发送非应答
         I2CSendNack();  
         
         I2CStop();
i2c_err:          // 命令执行失败后,要发送停止信号,避免影响I2C总线上其他设备
         I2CStop();
         returnfalse;
}
bool TempHumizhuanhuan(uint8_t *dat,double*pot)
{
         uint16_ttem,hum;
         
         tem= ((uint16_t)dat[0]<<8) | dat[1];
         hum= ((uint16_t)dat[3]<<8) | dat[4];
         if((crc8(dat,2)== dat[2]) && (crc8(dat+3,2) == dat[5]))
         {
                   pot[0]=(175.0*(double)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
                   pot[1]=(100.0*(double)hum/65535.0);// RH = hum*100 / (2^16-1)
                   return1;
         }
         else
         {
                   return0;
         }
}
float tempData, humiData;
uint8_t buffer[10];
double rth[2];
void TempHumiDrvTest(void)
{
         
         Nsht30SetResolution(buffer);
         printf("Get%x %x %x %x %x%x\n",buffer[0],buffer[1],buffer[2],buffer[3],buffer[4],buffer[5]);
         TempHumizhuanhuan(buffer,rth);
         printf("%3.4f,%3.6f%%\r\n",rth[0],rth[1]);
}


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

27

主题

90

帖子

0

粉丝