资讯详情

初出茅庐的小李第113篇博客项目笔记之机智云智能浇花器实战(2)-基础Demo实现

小李第112篇博客项目笔记机智云智能浇花器实战(1)-基础Demo实现 接(1)

继电器实现

继电器原理图

在这里插入图片描述 继电器为5V控制端是继电器RELAY-1

实现继电器代码

#include "relay.h"  /* 继电器 --- PA4 --- 推挽输出 */ void JDQ_Init(void) { 
          GPIO_InitTypeDef JDQ_InitStruct={ 
        0};    RCC_APB2PeriphClockCmd(JDQ1_CLK,ENABLE);    JDQ_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;///通用推挽  JDQ_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;  JDQ_InitStruct.GPIO_Pin   = JDQ1_PIN;  GPIO_Init(JDQ1_PORT,&JDQ_InitStruct);    JDQ1(0); }  uint8_t GetJDQ1Sta(void) { 
          return JDQ1_STA; }  //extern dataPoint_t currentDataPoint; void JiaoHua(uint8_t Sta) { 
          JDQ1(Sta);  //currentDataPoint.valueRelay_1=Sta; }   
#ifndef _RELAY_H_ #define _RELAY_H_  #include "stm32f10x.h"  #define JDQ1_CLK RCC_APB2Periph_GPIOA #define JDQ1_PORT GPIOA #define JDQ1_PIN GPIO_Pin_4

#define JDQ1(X) X?(GPIO_SetBits(JDQ1_PORT,JDQ1_PIN)):(GPIO_ResetBits(JDQ1_PORT,JDQ1_PIN))
#define JDQ1_STA GPIO_ReadOutputDataBit(JDQ1_PORT,JDQ1_PIN) 

void JDQ_Init(void);

#endif

继电器功能测试

#include "main.h"

typedef struct 
{ 
        
	uint8_t valueRelay_1;
}TestDataPoint_t;


TestDataPoint_t TestDataPoint;

int main(void)
{ 
        
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	USART1_Init(9600);	
	//printf("打印串口初始化 OK !\r\n"); 
  SysTick_Init();   
  //printf("系统嘀嗒初始化 OK !\r\n"); 
	LED_Init();  
  //printf("状态指示初始化 OK !\r\n"); 
  KEY_Init();
  //printf("按键配置初始化 OK !\r\n"); 
	JDQ_Init();
  //printf("继电器配置初始化 OK !\r\n"); 
	while(1)
	{ 
        	
		LED_Task();	
		if(GetKey0())
		{ 
        
			GPIO_TogglePin(LED1_PORT,LED1_PIN);
			JiaoHua(1-TestDataPoint.valueRelay_1);
			TestDataPoint.valueRelay_1 = 1-TestDataPoint.valueRelay_1;
			//JiaoHua(1-currentDataPoint.valueRelay_1);
		}
		if(GetKey1())
		{ 
        
			GPIO_TogglePin(LED2_PORT,LED2_PIN);
			//gizwitsSetMode(WIFI_AIRLINK_MODE);
			//按键进入配网模式
		}
		if(GetKey2())
		{ 
        
			GPIO_TogglePin(LED3_PORT,LED3_PIN);
		}
	}
}


说明

继电器是用来打开浇花的电机的,单片机无法直接控制5V电平就用一个三极管进行转换。 测试时候定义了一个结构体 是因为接下来这个继电器需要通过机智云平台进行控制,继电器的状态要实时的跟网络上的状态保持同步。

DHT11温湿度传感器原理图

DHT11温湿度传感器驱动原理

该传感器是一款非常常用的传感器 采用单总线协议读取 总共读取40bit数据,16位温度数据+16位湿度数据+8位校验数据,这里程序用来一个结构体来描述这5个字节数据

DHT11驱动代码实现

#include "dht11.h"
#include "delay.h"

/* 修改DHT11数据线的模式 */
void DHT111_ChangeMode(DHT11_MODE Mode)
{ 
        
	GPIO_InitTypeDef               DHT11_InitStruct;
	if(Mode == MODE_OUT)
	{ 
        
		DHT11_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP;
	}
	else
	{ 
        
		DHT11_InitStruct.GPIO_Mode  = GPIO_Mode_IPU;
	}
	DHT11_InitStruct.GPIO_Speed   = GPIO_Speed_50MHz;	
	DHT11_InitStruct.GPIO_Pin     = DHT11_DATA_PIN;	  //PB5
  GPIO_Init(DHT11_PORT, &DHT11_InitStruct);
}
     
//复位DHT11 -- 起始信号
void DHT11_Rset(void)	   
{ 
                         
	DHT11_IO_OUT(); 	 //SET OUTPUT
	DHT11_DQ_OUT(0); 	 //拉低DQ
	Delay_nms(20);     //拉低至少18ms
	DHT11_DQ_OUT(1); 	 //DQ=1 
	Delay_nus(30);     //主机拉高20~35us 等待从机响应
}

//等待DHT11的回应
//返回1:未检测到DHT11存在
//返回0:存在
uint8_t DHT11_Check(void) 	   
{ 
           
	uint8_t retry = ERR;              //假设没有响应
	DHT11_IO_IN();                    //设置成输入模式 
  while (DHT11_DQ_IN()&&(retry<100))//DHT11会拉低40~50us
	{ 
        
		retry++;
		Delay_nus(1);
	}	 
	if(retry>=100)return ERR;         //超时未等到信号变低就证明没有回复
	else retry=0;                     //未超时则证明DHT11有信号回复
  while(!DHT11_DQ_IN()&&(retry<100))//DHT11拉低后会再次拉高 40~80us(即是等待高电平)
	{ 
        
		retry++;
		Delay_nus(1);
	}
	if(retry>=100)return ERR;//超时未等到信号变低就证明没有回复 
	return OK;
}
//从DHT11读取一个位
//返回值:1/0 5 * 8 = 40 bit 32bit 信息 8bit 校验
//bit 1 或者 0 1是如何定义 0的如何定义的
uint8_t DHT11_Read_Bit(void) 			 
{ 
        
 	uint8_t retry = 0;
	while(DHT11_DQ_IN()&&(retry<100))//等待变为低电平
	{ 
        
		retry++;
		Delay_nus(1);
	}
	retry = 0;
	while(!DHT11_DQ_IN()&&retry<100)//等待变高电平
	{ 
        
		retry++;
		Delay_nus(1);
	}
	Delay_nus(40);                 //等待40us
	if(DHT11_DQ_IN())              //判断了电平是高电平
		return 1;
	else 
		return 0;	                   //否则就返回低电平 
}
//从DHT11读取一个字节
//返回值:读到的数据
uint8_t DHT11_Read_Byte(void)    
{ 
                
	uint8_t i,data;
	data=0;
	for (i=0;i<8;i++) 
	{ 
        
		data<<=1; 
		data|=DHT11_Read_Bit();    //读8次一个字节
	}						    
	return data; //读一个字节数据
}
//从DHT11读取一次数据
//temp:温度值(范围:0~50°)
//humi:湿度值(范围:20%~90%)
//返回值:0,正常;1,读取失败
uint8_t DHT11_Read_Data(float *Temp,float *Humi)    
{ 
             
	DHT11_t DHT11 ={ 
        0};                //温湿度传感器结构体初始化成0
	DHT11_Rset();                      //先复位温湿度传感器
	if(DHT11_Check()==OK)
	{ 
        
		DHT11.Humi_H = DHT11_Read_Byte(); //湿度高字节
		DHT11.Humi_L = DHT11_Read_Byte(); //湿度低字节
	  DHT11.Temp_H = DHT11_Read_Byte(); //温度高字节
		DHT11.Temp_L = DHT11_Read_Byte(); //温度低字节
		DHT11.Check  = DHT11_Read_Byte(); //传感器的校验字节
		if(DHT11.Check==(DHT11.Humi_H+DHT11.Humi_L+DHT11.Temp_H+DHT11.Temp_L))
		{ 
                                         /*1111 1111*/
			*Temp = DHT11.Temp_H+(0.1*(int8_t)(DHT11.Temp_L)); //校验通过
			*Humi = DHT11.Humi_H+(0.1*(int8_t)(DHT11.Humi_L));
		}
	}
	else return 1;
	return 0;	    
}

//初始化DHT11的IO口 DQ 同时检测DHT11的存在
//返回1:不存在
//返回0:存在 
uint8_t DHT11_Init(void)
{ 
        	
	RCC_APB2PeriphClockCmd(DHT11_CLK,ENABLE);
	
 	GPIO_InitTypeDef              DHT11_InitStruct;
 	DHT11_InitStruct.GPIO_Mode  = GPIO_Mode_Out_PP; 		     //推挽输出
 	DHT11_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	DHT11_InitStruct.GPIO_Pin   = DHT11_DATA_PIN;		
	
 	GPIO_Init(DHT11_PORT,&DHT11_InitStruct);	              //PB5的初始化
	
 	GPIO_SetBits(DHT11_PORT,DHT11_DATA_PIN);					     //空闲 输出高 
	DHT11_Rset();                                          //复位DHT11
	return DHT11_Check();                                  //等待DHT11的回应
} 

#ifndef __DHT11_H_
#define __DHT11_H_

#include "stm32f10x.h"


#define OK 0 //响应的电平是高
#define ERR 1 //响应的电平是高

//DHT11 ---- PB5 输入模式测量电平的高低 输出模式模式输出高低
#define DHT11_CLK RCC_APB2Periph_GPIOB
#define DHT11_PORT GPIOB
#define DHT11_DATA_PIN GPIO_Pin_5

typedef enum
{ 
         
	MODE_IN  = 0,   //输入模式 浮空输入 
	MODE_OUT = 1,   //输出模式 推挽输出
}DHT11_MODE; 
//DHT11 温湿度传感器的结构体
typedef struct
{ 
        
	uint8_t Temp_H;  //温度整数部分
	uint8_t Temp_L;  //温度小数部分
	uint8_t Humi_H;  //湿度正数部分
	uint8_t Humi_L;  //湿度小数部分
	uint8_t Check;   //传感器校验结果
}DHT11_t;          


//IO方向设置
#define DHT11_IO_IN() DHT111_ChangeMode(MODE_IN)
#define DHT11_IO_OUT() DHT111_ChangeMode(MODE_OUT)
IO操作函数 
#define DHT11_DQ_OUT(X) X?(GPIO_SetBits(DHT11_PORT,DHT11_DATA_PIN)):(GPIO_ResetBits(DHT11_PORT,DHT11_DATA_PIN)) 
#define DHT11_DQ_IN() GPIO_ReadInputDataBit(DHT11_PORT,DHT11_DATA_PIN) //读输入的数据

uint8_t DHT11_Init(void);                            //初始化DHT11
void DHT11_Rset(void);                               //复位DHT11 
void DHT111_Change_Mode(DHT11_MODE Mode);            //切换模式
uint8_t DHT11_Read_Bit(void);                        //读出一个位
uint8_t DHT11_Read_Byte(void);                       //读出一个字节
uint8_t DHT11_Check(void);                           //检测是否存在DHT11
uint8_t DHT11_Read_Data(float *Temp,float *Humi);    //读取温湿度

#endif

DHT11数据手册

需要可以去群里自行下载 点击链接加入群聊【电子学习交流群】:https://jq.qq.com/?_wv=1027&k=KWZfGS3X

写到这其实才发现传感器数据无法显示,因为串口没有引出来在开发板上是可以打印数据,所以下面还需要再整一个屏幕的显示代码把传感器数据显示到屏幕上来。

OLED屏幕原理图

OLED屏幕是一个I2C接口的屏幕,代码都是很成熟的代码我这里直接贴出来了

OLED屏幕驱动代码

#include "oled.h"
#include "oledfont.h"
#include "delay.h"
#include <stdlib.h>

uint8_t OLED_GRAM[144][8];

//反显函数
void OLED_ColorTurn(uint8_t i)
{ 
        
	if(i==0)
	{ 
        
		OLED_WR_Byte(0xA6,OLED_CMD);//正常显示
	}
	if(i==1)
	{ 
        
		OLED_WR_Byte(0xA7,OLED_CMD);//反色显示
	}
}

//屏幕旋转180度
void OLED_DisplayTurn(u8 i)
{ 
        
	if(i==0)
	{ 
        
		OLED_WR_Byte(0xC8,OLED_CMD);//正常显示
		OLED_WR_Byte(0xA1,OLED_CMD);
	}
	if(i==1)
	{ 
        
		OLED_WR_Byte(0xC0,OLED_CMD);//反转显示
		OLED_WR_Byte(0xA0,OLED_CMD);
	}
}

//延时
void IIC_delay(void)
{ 
        
	uint8_t t=3;
	while(t--);
}

//起始信号
void I2C_Start(void)
{ 
        
	OLED_SDA_Set();
	OLED_SCL_Set();
	IIC_delay();
	OLED_SDA_Clr();
	IIC_delay();
	OLED_SCL_Clr();
	IIC_delay();
}

//结束信号
void I2C_Stop(void)
{ 
        
	OLED_SDA_Clr();
	OLED_SCL_Set();
	IIC_delay();
	OLED_SDA_Set();
}

//等待信号响应
void I2C_WaitAck(void) //测数据信号的电平
{ 
        
	OLED_SDA_Set();
	IIC_delay();
	OLED_SCL_Set();
	IIC_delay();
	OLED_SCL_Clr();
	IIC_delay();
}

//写入一个字节
void Send_Byte(uint8_t dat)
{ 
        
	uint8_t i;
	for(i=0;i<8;i++)
	{ 
        
		if(dat&0x80)//将dat的8位从最高位依次写入
		{ 
        
			OLED_SDA_Set();
    }
		else
		{ 
        
			OLED_SDA_Clr();
    }
		IIC_delay();
		OLED_SCL_Set();
		IIC_delay();
		OLED_SCL_Clr();//将时钟信号设置为低电平
		dat<<=1;
  }
}

//发送一个字节
//mode:数据/命令标志 0,表示命令;1,表示数据;
void OLED_WR_Byte(u8 dat,u8 mode)
{ 
        
	I2C_Start();
	Send_Byte(0x78);
	I2C_WaitAck();
	if(mode){ 
        Send_Byte(0x40);}
  else{ 
        Send_Byte(0x00);}
	I2C_WaitAck();
	Send_Byte(dat);
	I2C_WaitAck();
	I2C_Stop();
}

//开启OLED显示 
void OLED_DisPlay_On(void)
{ 
        
	OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
	OLED_WR_Byte(0x14,OLED_CMD);//开启电荷泵
	OLED_WR_Byte(0xAF,OLED_CMD);//点亮屏幕
}

//关闭OLED显示 
void OLED_DisPlay_Off(void)
{ 
        
	OLED_WR_Byte(0x8D,OLED_CMD);//电荷泵使能
	OLED_WR_Byte(0x10,OLED_CMD);//关闭电荷泵
	OLED_WR_Byte(0xAE,OLED_CMD);//关闭屏幕
}

//更新显存到OLED 
void OLED_Refresh(void)
{ 
        
	u8 i,n;
	for(i=0;i<8;i++)
	{ 
        
		OLED_WR_Byte(0xb0+i,OLED_CMD); //设置行起始地址
		OLED_WR_Byte(0x00,OLED_CMD);   //设置低列起始地址
		OLED_WR_Byte(0x10,OLED_CMD);   //设置高列起始地址
		I2C_Start();
		Send_Byte(0x78);
		I2C_WaitAck();
		Send_Byte(0x40);
		I2C_WaitAck();
		for(n=0;n<128;n++)
		{ 
        
			Send_Byte(OLED_GRAM[n][i])
        标签: 2x1继电器三极管128300pa2pa传感器jq4150继电器sta继电器继电器3e4

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台