main.c、DS18B20、BH1750
要求:
- 采集装置水温,联网上传到巴法云。
- 获取装置水位高度(AD采集),上传到巴法云。
- 采集环境光照(iic),上传到巴法云。
- 按键控制水泵开关(这里用继电器代替),按键1按下打开,按键2关闭。
- 水位高于某个值时,打开水泵(继电器),低于时不会自动关闭,需要按键来关闭。
main.c
#include "stm32f10x.h"
#include "Delay.h"
#include "math.h"
#include "oled.h"
#include "LED.h"
#include "DS18B20.h"
#include "BH1750.h"
#include "esp8266.h"
#include "AD.h"
#include "JDQ.h"
#include "Water_Sensor.h"
#include "Key.h"
#define Sun_Max 100
#define Water_Max 30
uint8_t buff[128];
float Temp; //温度
float Sun_Temp; //光强
float Water_High; //AD转换之后水位
uint16_t Water_AD; //AD检测水位值
uint8_t Key1,Key2;
void ShowData(void); //数据页面
void GetData(void); //获取数据
void Menu_key_set(void);//按键扫描
void Key_Mune(void); //按键切换页面操作
void Get_Key(void);
int main(void)
{
SystemInit();
Delay_Init(); //滴答定时器初始化
OLED_Init(); //OLED屏初始化
OLED_Clear();//清屏
OLED_ShowChinese(40,28,"联网中");
OLED_Update(); //更新数据
DS18B20_Init();
BH1750_Init();
AD_Init();
JDQ_Init();
Key_Init();
ESP8266_Config(); //初始化wifi
//连接网络
ConnectToHotspot();
//连接巴法云
ConnectToBaffServer();
sprintf((char*)buff,"cmd=1&uid=%s&topic=%s\r\n",PRODUCTID,"DZQ");
WifiSendStr((char*)buff);
OLED_Clear();
while(1)
{
if(timekey[0]>=timekey[1]) //10ms扫描一次按键
{
Get_Key();
timekey[0]=0;
}
if(timeled[0]>=timeled[1]) //2s进入
{
GetData(); //获取数据
ShowData(); //显示数据
sprintf((char*)buff,"cmd=2&uid=%s&topic=%s&msg=%.2f\r\n",PRODUCTID,"Temp",Temp);
WifiSendStr((char*)buff);
//向巴法云发送温度
sprintf((char*)buff,"cmd=2&uid=%s&topic=%s&msg=%.2f\r\n",PRODUCTID,"Sun",Sun_Temp);
WifiSendStr((char*)buff);
//向巴法云发送光强
sprintf((char*)buff,"cmd=2&uid=%s&topic=%s&msg=#%.2f\r\n",PRODUCTID,"WaterHigh",Water_High);
WifiSendStr((char*)buff);
//向巴法云发送水位
timeled[0]=0;
}
}
}
void ShowData(void)
{
/*温度*/
OLED_ShowChinese(0,0,"温度");
OLED_ShowChar(32,0,':',OLED_8X16);
OLED_ShowFloatNum(41,0,Temp,2,1,OLED_8X16);
/*光强*/
OLED_ShowChinese(0,16,"光强");
OLED_ShowChar(32,16,':',OLED_8X16);
OLED_ShowFloatNum(41,17,Sun_Temp,5,0,OLED_8X16);
/*水位*/
OLED_ShowChinese(0,32,"水位");
OLED_ShowChar(32,32,':',OLED_8X16);
OLED_ShowFloatNum(41,34,Water_High,2,2,OLED_8X16);
OLED_Update();
}
void GetData(void)
{
Temp = DS18B20_GetTemperture();
Sun_Temp = BH1750_GetLightIntensity();
Water_AD = Get_AD_Average(ADC_Channel_1,10); //获取通道1的水位AD值
Water_High = Water_Sensor_Read(ADC_Channel_1,10); //获取通道1水位经过公式转换的具体值
if(Water_High>=Water_Max)
{
JDQ_ON();
}
}
void Get_Key()
{
Key1=Get_Key_1();
Key2=Get_Key_2();
if(Key1 == 1)
JDQ_ON();
if(Key2 == 2)
JDQ_OFF();
}
DS18B20.c
#ifndef _DS18B20_H_
#define _DS18B20_H_
#include "stm32f10x.h"
#include "delay.h"
#include "sys.h"
/* DS18B20时钟端口、引脚定义 */
#define DS18B20_PORT GPIOB
#define DS18B20_PIN (GPIO_Pin_9)
#define DS18B20_PORT_RCC RCC_APB2Periph_GPIOB
IO操作函数
#define DS18B20_DQ_OUT PBout(9) //数据端口
#define DS18B20_DQ_IN PBin(9) //数据端口
u8 DS18B20_Init(void); //初始化DS18B20
float DS18B20_GetTemperture(void); //获取温度
void DS18B20_Start(void); //开始温度转换
void DS18B20_Write_Byte(u8 dat);//写入一个字节
u8 DS18B20_Read_Byte(void); //读出一个字节
u8 DS18B20_Read_Bit(void); //读出一个位
u8 DS18B20_Check(void); //检测是否存在DS18B20
void DS18B20_Reset(void); //复位DS18B20
#endif
BH1750
BH1750.c
#include "stm32f10x.h" // Device header
#include "IIC.h"
#include "BH1750.h"
/*
*==============================================================================
*函数名称:BH1750_Read_Measure
*函数功能:读取BH1750测量数据
*输入参数:无
*返回值:0:读取失败;其他:光照强度
*备 注:无
*==============================================================================
*/
u16 BH1750_Read_Measure (void)
{
u16 receData = 0;
I2C_Start();
// 发送从设备地址,1:读
Send_Byte(BH1750_Addr | 1);
if(I2C_WaitAck() == 1)
{
return 0;
}
// 读取高八位
receData = IIC_Read_Byte();
IIC_Ack();
// 读取低八位
receData = (receData << 8) + IIC_Read_Byte();
IIC_NAck();
I2C_Stop();
return receData; // 返回读取到的数据
}
/*
*==============================================================================
*函数名称:BH1750_Init
*函数功能:初始化BH1750
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void BH1750_Init (void)
{
// 结构体定义
GPIO_InitTypeDef GPIO_InitStructure;
// 开启时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
// 初始化GPIO结构体
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; // 开漏输出
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// 给一个停止信号, 复位I2C总线上的所有设备到待机模式
I2C_Stop();
// BH1750上电
BH1750_Byte_Write(POWER_ON);
// 复位BH1750
BH1750_Byte_Write(MODULE_RESET);
// 写入测量模式
BH1750_Byte_Write(Measure_Mode);
}
/*
*==============================================================================
*函数名称:BH1750_GetLightIntensity
*函数功能:获取光照强度
*输入参数:无
*返回值:光照强度
*备 注:分辨率 光照强度(单位lx)=(High Byte + Low Byte)/ 1.2 * 测量精度
*==============================================================================
*/
float BH1750_GetLightIntensity (void)
{
return (float)(BH1750_Read_Measure() / 1.1f * Resolution); //返回测量光照强度
}
BH1750.h
#ifndef __BH1750_H__
#define __BH1750_H__
//测量模式
#define Measure_Mode CONTINUE_H_MODE
//分辨率 光照强度(单位lx)=(High Byte + Low Byte)/ 1.2 * 测量精度
#if ((Measure_Mode == CONTINUE_H_MODE2)|(Measure_Mode == ONE_TIME_H_MODE2))
#define Resolurtion 0.5
#elif ((Measure_Mode == CONTINUE_H_MODE)|(Measure_Mode == ONE_TIME_H_MODE))
#define Resolution 1
#elif ((Measure_Mode == CONTINUE_L_MODE)|(Measure_Mode == ONE_TIME_L_MODE))
#define Resolution 4
#endif
// SCL
#define BH1750_SCL_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_14)
#define BH1750_SCL_Set() GPIO_SetBits(GPIOB,GPIO_Pin_14)
// SDA
#define BH1750_SDA_Clr() GPIO_ResetBits(GPIOB,GPIO_Pin_13)
#define BH1750_SDA_Set() GPIO_SetBits(GPIOB,GPIO_Pin_13)
// 读取SDA电平
#define BH1750_SDA_DATA() GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_13)
u16 BH1750_Read_Measure (void);
void BH1750_Init (void);
float BH1750_GetLightIntensity (void);
#endif
iic
iic.c
#include "stm32f10x.h" // Device header
#include "BH1750.h"
#include "IIC.h"
/*
*==============================================================================
*函数名称:IIC_Delay
*函数功能:IIC延时
*输入参数:无
*返回值:无
*备 注:数据手册提供
*==============================================================================
*/
void IIC_Delay (void)
{
u8 t = 10;
while (t--);
}
/*
*==============================================================================
*函数名称:I2C_Start
*函数功能:IIC起始信号
*输入参数:无
*返回值:无
*备 注:数据手册提供
*==============================================================================
*/
void I2C_Start (void)
{
BH1750_SDA_Set();//拉高
BH1750_SCL_Set();//拉高
IIC_Delay();
BH1750_SDA_Clr();//拉低
IIC_Delay();
BH1750_SCL_Clr(); //拉低
IIC_Delay();
}
/*
*==============================================================================
*函数名称:I2C_Stop
*函数功能:IIC终止信号
*输入参数:无
*返回值:无
*备 注:数据手册提供
*==============================================================================
*/
void I2C_Stop (void)
{
BH1750_SDA_Clr();
BH1750_SCL_Set();
IIC_Delay();
BH1750_SDA_Set();
}
/*
*==============================================================================
*函数名称:IIC_Ack
*函数功能:CPU产生一个ACK信号
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void IIC_Ack (void)
{
BH1750_SDA_Clr();
IIC_Delay();
BH1750_SCL_Set();
IIC_Delay();
BH1750_SCL_Clr();
IIC_Delay();
BH1750_SDA_Set();
}
/*
*==============================================================================
*函数名称:IIC_NAck
*函数功能:CPU产生一个NACK信号
*输入参数:无
*返回值:无
*备 注:无
*==============================================================================
*/
void IIC_NAck (void)
{
BH1750_SDA_Set();
IIC_Delay();
BH1750_SCL_Set();
IIC_Delay();
BH1750_SCL_Clr();
IIC_Delay();
}
/*
*==============================================================================
*函数名称:I2C_WaitAck
*函数功能:IIC等待应答
*输入参数:无
*返回值:0:未收到应答信号;1:收到应答信号
*备 注:无
*==============================================================================
*/
u8 I2C_WaitAck (void)
{
u8 re;
BH1750_SDA_Set();
IIC_Delay();
BH1750_SCL_Set();
IIC_Delay();
if (BH1750_SDA_DATA())
{
re = 1;
}
else
{
re = 0;
}
BH1750_SCL_Clr();
IIC_Delay();
return re;
}
/*
*==============================================================================
*函数名称:Send_Byte
*函数功能:写入一个字节
*输入参数:dat:需要写入的数据
*返回值:无
*备 注:数据手册提供
*==============================================================================
*/
void Send_Byte (u8 dat)
{
u8 i;
for (i = 0;i < 8;i ++)
{
// 发送数据时,从高位依次写入
if (dat & 0x80)
{
BH1750_SDA_Set();
}
else
{
BH1750_SDA_Clr();
}
IIC_Delay();
BH1750_SCL_Set();
IIC_Delay();
BH1750_SCL_Clr();
// dat左移1位
dat <<= 1;
}
}
/*
*==============================================================================
*函数名称:IIC_Read_Byte
*函数功能:IIC读取一个字节数据
*输入参数:无
*返回值:无
*备 注:读取到的一个字节数据
*==============================================================================
*/
u8 IIC_Read_Byte (void)
{
u8 i;
u8 value;
// 高位在前
value = 0;
// 循环读取8bit数据
for (i = 0; i < 8; i ++)
{
value <<= 1; // 循环左移一位
BH1750_SCL_Set();
IIC_Delay();
// 如果是“1”
if (BH1750_SDA_DATA())
{
value ++;
}
BH1750_SCL_Clr();
IIC_Delay();
}
return value;
}
//BH1750写一个字节
//返回值 成功:0 失败:非0
/*
*==============================================================================
*函数名称:BH1750_Byte_Write
*函数功能:BH1750写一个字节
*输入参数:data:要写入的数据
*返回值:0:写入成功;1/2:写入失败
*备 注:无
*==============================================================================
*/
u8 BH1750_Byte_Write (u8 data)
{
I2C_Start();
// 发送从设备地址,0:写
Send_Byte(BH1750_Addr | 0);
// 收到应答信号
if(I2C_WaitAck() == 1)
{
return 1;
}
//发送控制命令
Send_Byte(data);
// 收到应答信号
if(I2C_WaitAck() == 1)
{
return 2;
}
I2C_Stop();
return 0;
}
iic.h
#ifndef __IIC_H__
#define __IIC_H__
// BH1750的地址(Addr=“H”)
#define BH1750_Addr 0x46
// BH1750指令
#define POWER_OFF 0x00
#define POWER_ON 0x01
#define MODULE_RESET 0x07
#define CONTINUE_H_MODE 0x10
#define CONTINUE_H_MODE2 0x11
#define CONTINUE_L_MODE 0x13
#define ONE_TIME_H_MODE 0x20
#define ONE_TIME_H_MODE2 0x21
#define ONE_TIME_L_MODE 0x23
//测量模式
#define Measure_Mode CONTINUE_H_MODE
//分辨率 光照强度(单位lx)=(High Byte + Low Byte)/ 1.2 * 测量精度
#if ((Measure_Mode == CONTINUE_H_MODE2)|(Measure_Mode == ONE_TIME_H_MODE2))
#define Resolurtion 0.5
#elif ((Measure_Mode == CONTINUE_H_MODE)|(Measure_Mode == ONE_TIME_H_MODE))
#define Resolurtion 1
#elif ((Measure_Mode == CONTINUE_L_MODE)|(Measure_Mode == ONE_TIME_L_MODE))
#define Resolurtion 4
#endif
void IIC_Delay (void);
void I2C_Start (void);
void I2C_Stop (void);
void IIC_Ack (void);
void IIC_NAck (void);
u8 I2C_WaitAck (void);
void Send_Byte (u8 dat);
u8 IIC_Read_Byte (void);
u8 BH1750_Byte_Write (u8 data);
#endif