由STM32C8T6作为主控芯片,控制温湿度传感器与光照强度传感器来检测温湿度值和光照强度值,取得的数据经过处理后可在0.96寸OLED显示屏上实时显示,还可根据预设值实现蜂鸣器报警和led指示灯报警的功能。
该设计是基于STM32的智能数据采集系统,通过主控芯片STM32C8T6接收传感器采集到光照强度和温湿度数据。
具体工作流程为:当智能数据采集系统上电运行之后,系统首先运行初始化代码,检测各个模块如ESP8266、蜂鸣器、温湿度传感器、光照强度传感器和OLED等与主控板是否连接正常,通过对各个硬件模块的初始化来分别判断各部分功能是否正常。在初始化完成之后,可以通过蜂鸣器进行提示,这时就可以进行正常的工作,OLED就可以正常显示采集到的温度、湿度和光照强度值
使用的模块是BH1750,使用的是I2C协议
留出来5个API,分别是BH1750s上电、BH1750s断电、BH1750复位、BH1750初始化、获取光照强度
对于这一块详细版本,在另外一文
//BH1750s上电
void BH1750_Power_ON(void)
{
BH1750_Byte_Write(POWER_ON);
}
//BH1750s断电
void BH1750_Power_OFF(void)
{
BH1750_Byte_Write(POWER_OFF);
}
//BH1750复位 仅在上电时有效
void BH1750_RESET(void)
{
BH1750_Byte_Write(MODULE_RESET);
}
//BH1750初始化
void BH1750_Init(void)
{
I2C_BH1750_GPIOConfig(); /* 配置GPIO */
BH1750_Power_ON(); //BH1750s上电
//BH1750_RESET(); //BH1750复位
BH1750_Byte_Write(Measure_Mode);
//SysTick_Delay_ms(120);
}
//获取光照强度
float LIght_Intensity(void)
{
return (float)(BH1750_Read_Measure()/1.1f*Resolurtion);
}
使用的模块是DHT11
留出来5个API,分别是DHT11初始化、获取温湿度、DHT11检测、DHT11复位、
对于这一块详细版本,在另外一文
//复位DHT11
void DHT11_Rst(void)
{
DHT11_IO_OUT(); //SET OUTPUT
DHT11_DQ_OUT=0; //拉低DQ
delay_ms(20); //拉低至少18ms
DHT11_DQ_OUT=1; //DQ=1
delay_us(30); //主机拉高20~40us
}
//等待DHT11的回应
//返回1:未检测到DHT11的存在
//返回0:存在
u8 DHT11_Check(void)
{
u8 retry=0;
DHT11_IO_IN();//SET INPUT
while (DHT11_DQ_IN&&retry<100)//DHT11会拉低40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
else retry=0;
while (!DHT11_DQ_IN&&retry<100)//DHT11拉低后会再次拉高40~80us
{
retry++;
delay_us(1);
};
if(retry>=100)return 1;
return 0;
}
//从DHT11读取一个位
//返回值:1/0
u8 DHT11_Read_Bit(void)
{
u8 retry=0;
while(DHT11_DQ_IN&&retry<100)//等待变为低电平
{
retry++;
delay_us(1);
}
retry=0;
while(!DHT11_DQ_IN&&retry<100)//等待变高电平
{
retry++;
delay_us(1);
}
delay_us(40);//等待40us
if(DHT11_DQ_IN)return 1;
else return 0;
}
//从DHT11读取一个字节
//返回值:读到的数据
u8 DHT11_Read_Byte(void)
{
u8 i,dat;
dat=0;
for (i=0;i<8;i++)
{
dat<<=1;
dat|=DHT11_Read_Bit();
}
return dat;
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
u8 DHT11_Read_Data(u8 *humiH,u8 *humiL,u8 *tempH,u8 *tempL)
{
u8 buf[5];
u8 i;
DHT11_Rst();
if(DHT11_Check()==0)
{
for(i=0;i<5;i++)//读取40位数据
{
buf[i]=DHT11_Read_Byte();
}
if((buf[0]+buf[1]+buf[2]+buf[3])==buf[4])
{
*humiH=buf[0]; //坑啊原子哥,说明书明明是湿度在前温度在后
*humiL=buf[1];
*tempH=buf[2];
*tempL=buf[3];
}
}else return 1;
return 0;
}
//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在
u8 DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能PA端口时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; //PA0端口配置
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure); //初始化IO口
GPIO_SetBits(GPIOA,GPIO_Pin_8); //PA0 输出高
DHT11_Rst(); //复位DHT11
return DHT11_Check();//等待DHT11的回应
}
/******************************************************************
* 文件:main.c
* 功能:主函数入口,实现各类函数的初始化,设置判断的阈值执行对应功能
*******************************************************************/
u8 alarmFlag = 0;//是否报警的标志
u8 alarm_is_free = 10;//报警器是否被手动操作,如果被手动操作即设置为0
u8 humidityH; //湿度整数部分
u8 humidityL; //湿度小数部分
u8 temperatureH; //温度整数部分
u8 temperatureL; //温度小数部分
extern char oledBuf[20];
float Light = 0; //光照度
u8 Led_Status = 0;
char PUB_BUF[256];//上传数据的buf
const char *devSubTopic[] = {"/mysmarthome/sub"};
const char devPubTopic[] = "/mysmarthome/pub";
u8 ESP8266_INIT_OK = 0;//esp8266初始化完成标志
int main(void)
{
unsigned short timeCount = 0; //发送间隔变量
unsigned char *dataPtr = NULL;
delay_init(); //延时函数初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
LED_Init(); //初始化与LED连接的硬件接口
KEY_Init(); //初始化与按键连接的硬件接口
EXTIX_Init(); //外部中断初始化
BEEP_Init();
DHT11_Init();
BH1750_Init();
Usart1_Init(115200);//debug串口
Usart2_Init(115200);//stm32-8266通讯串口
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
OLED_Clear();
UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");
if(!ESP8266_INIT_OK){
OLED_Clear();
sprintf(oledBuf,"Waiting For");
OLED_ShowString(16,0,(u8*)oledBuf,16);//8*16 “ABC”
sprintf(oledBuf,"WiFi");
OLED_ShowString(48,18,(u8*)oledBuf,16);//8*16 “ABC”
sprintf(oledBuf,"Connection");
OLED_ShowString(24,36,(u8*)oledBuf,16);//8*16 “ABC”
OLED_Refresh();
}
ESP8266_Init(); //初始化ESP8266
OLED_Clear();
sprintf(oledBuf,"Waiting For");
OLED_ShowString(16,0,(u8*)oledBuf,16);//8*16 “ABC”
sprintf(oledBuf,"MQTT Server");
OLED_ShowString(16,18,(u8*)oledBuf,16);//8*16 “ABC”
sprintf(oledBuf,"Connection");
OLED_ShowString(24,36,(u8*)oledBuf,16);//8*16 “ABC”
OLED_Refresh();
while(OneNet_DevLink()){//接入OneNET
delay_ms(500);
}
OLED_Clear();
TIM2_Int_Init(4999,7199);
TIM3_Int_Init(2499,7199);
BEEP = 0;//鸣叫提示接入成功
delay_ms(250);
BEEP = 1;
OneNet_Subscribe(devSubTopic, 1);
while(1)
{
if(timeCount % 40 == 0)//1000ms / 25 = 40 一秒执行一次
{
/********** 温湿度传感器获取数据**************/
DHT11_Read_Data(&humidityH,&humidityL,&temperatureH,&temperatureL);
UsartPrintf(USART_DEBUG,"\r\n");
UsartPrintf(USART_DEBUG,"温度:%d.%d 湿度:%d.%d ",humidityH,humidityL,temperatureH,temperatureL);
/********** 光照度传感器获取数据**************/
if (!i2c_CheckDevice(BH1750_Addr))
{
Light = LIght_Intensity();
UsartPrintf(USART_DEBUG,"光照度:%.1f lx\r\n", Light);
UsartPrintf(USART_DEBUG,"\r\n");
}
if(alarm_is_free == 10)//报警器控制权是否空闲 alarm_is_free == 10 初始值为10
{
if((humidityH < 80) && (temperatureH < 30) && (Light < 1000))alarmFlag = 0;
else alarmFlag = 1;
}
if(alarm_is_free < 10)alarm_is_free++;
//UsartPrintf(USART_DEBUG,"alarm_is_free = %d\r\n", alarm_is_free);
//UsartPrintf(USART_DEBUG,"alarmFlag = %d\r\n", alarmFlag);
}
if(++timeCount >= 200) // 5000ms / 25 = 200 发送间隔5000ms
{
Led_Status = GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_4);//读取LED0的状态
UsartPrintf(USART_DEBUG,"=========================================\r\n");
UsartPrintf(USART_DEBUG,"发布数据\r\n");
UsartPrintf(USART_DEBUG, "OneNet_Publish\r\n");
sprintf(PUB_BUF,"{\"Hum\":%d.%d,\"Temp\":%d.%d,\"Light\":%.1f,\"Led\":%d,\"Beep\":%d}",
humidityH,humidityL,temperatureH,temperatureL,Light,Led_Status?0:1,alarmFlag);
OneNet_Publish(devPubTopic, PUB_BUF);
UsartPrintf(USART_DEBUG,"=========================================\r\n");
timeCount = 0;
ESP8266_Clear();
}
dataPtr = ESP8266_GetIPD(3);
if(dataPtr != NULL)
OneNet_RevPro(dataPtr);
delay_ms(10);
}
}