本次测试测试了:DS18B20温度传感器,DHT11温湿度传感器,人体红外感应和VS1838B红外按键解码。
DS18B20:Pin---》P12
DHT11: Pin---》P54
红外人体感应:Pin-----》P17
VS1838B解码:Pin-----》P16
OLED屏:
OLED_RES_PIN (P47) // 复位
OLED_DC_PIN (P06) // 数据/命令控制
OLED_CS_PIN (P46) // 片选
OLED_DIN_PIN (P05) // D1(MOSI)数据
OLED_CLK_PIN (P04) // D0(SCLK) 时钟
/*=============================================================================
* filename: DHT11.c
* author: Wood Wang
* date: 2020.03
* describe:
*===========================================================================*/
/* Includes -----------------------------------------------------------------*/
#include "main.h"
//=================================================================
// DHT11温湿度传感器
//=================================================================
sbit DHT_Pin = P5^4;
#define PinSet() DHT_Pin = 1
#define PinClr() DHT_Pin = 0
#define PinDirIn() P5CON &= ~0x10;P5PH |= 0x10;
#define PinDirOut() P5CON |= 0x10;P5PH &= ~0x10;
#define PinGet() DHT_Pin
//============================================
uint8_t DHTReadData(void)
{
uint8_t i;
uint8_t RHdata,Timeout;
RHdata = 0;
for(i=0;i<8;i++)
{
//等待从机50us低电平
Timeout = 2;
while((!PinGet()) && Timeout++) Delay_us(1); //
if(Timeout == 1) break; //超时则跳出for循环
RHdata <<= 1;
Delay_us(4);//等待30us到50us
if(PinGet()) RHdata |= 0x01; //判断数据位是0还是1
//等待数据高电平结束
Timeout = 2;
while((PinGet()) && Timeout++) Delay_us(1); //
if(Timeout == 1) break; //超时则跳出for循环
}
return RHdata;
}
uint8_t RH_Read(uint8_t * rh,uint8_t * t)
{
unsigned char RHdata[5],Timeout;
*rh = 0;
*t = 0;
PinDirOut();
PinClr();
Delay_ms(20); //主机拉低>18ms
PinSet();
Delay_us(2);//总线拉高 主机延时20us-40us
//主机设为输入 判断从机响应信号
PinDirIn();
PinSet();
Delay_us(4);
//判断从机是否有低电平响应信号 如不响应则跳出,响应则向下运行
if(!PinGet())
{
//判断从机是否发出 80us 的低电平响应信号是否结束
Timeout = 2;
while((!PinGet()) && Timeout++) Delay_us(1); //等待IO从低电平到高电平退出
if(Timeout == 1) return 3; //超时
//判断从机是否发出 80us 的高电平,如发出则进入数据接收状态
Timeout = 2;
while((PinGet()) && Timeout++) Delay_us(1) ; //等待IO从高电平到低电平退出
if(Timeout == 1) return 3; //超时
//准备数据接收
RHdata[0] = DHTReadData();
RHdata[1] = DHTReadData();
RHdata[2] = DHTReadData();
RHdata[3] = DHTReadData();
RHdata[4] = DHTReadData();
PinSet();
// Uart0SendStrlen(RHdata, 5);
//数据校验
Timeout = RHdata[0]+RHdata[1]+RHdata[2]+RHdata[3];
// Uart0Send(0xa1);
if(Timeout == RHdata[4])
{
//数据正确
*rh = RHdata[0];
*t = RHdata[2];
return 0;
}else return 2;
}
// Uart0Send(0xa2);
return 1;
}
uint8_t DHT11_Init(void)
{
return 0;
}
/*=============================================================================
* filename: DS18B20.c
* author: Wood Wang
* date: 2020.03
* describe:
*===========================================================================*/
/* Includes -----------------------------------------------------------------*/
#include "main.h"
//读传感器 端口位定义,可修改
sbit DS18B20_Pin = P1^2;
#define DS18B20_PIN_H() DS18B20_Pin = 1;
#define DS18B20_PIN_L() DS18B20_Pin = 0;
#define DS18B20_IN() DS18B20_Pin
#define DS18B20_DIR_In() P1CON &= ~0x04;P1PH |= 0x04;
#define DS18B20_DIR_Out() P1CON |= 0x04;P1PH &= ~0x04;
void DS18B20_Rst(void)
{
DS18B20_DIR_Out(); //SET OUTPUT
DS18B20_PIN_H(); //
DS18B20_PIN_L(); //低
Delay_us(80); // 0 >480us
DS18B20_PIN_H(); //高
Delay_us(1); //
}
U8 DS18B20_Check(void)
{
U8 retry=0;
DS18B20_Rst();
DS18B20_DIR_In();//SET INPUT
while (DS18B20_IN() && retry<200)
{
retry++;
Delay_us(1);
};
if(retry >= 200) return 1;
else retry=0;
while (!DS18B20_IN() && retry<240) //0: 60-240us
{
retry++;
Delay_us(1);
};
if(retry >= 240) return 1;
return 0;
}
U8 DS18B20_Read_Byte(void) // read one byte
{
U8 i,Data;
Data=0;
DS18B20_DIR_Out();//SET OUTPUT
DS18B20_PIN_H();
for (i=0;i<8;i++)
{
DS18B20_PIN_L();
Data >>= 1;
Delay_us(1);
DS18B20_PIN_H();
Delay_us(1);
DS18B20_DIR_In();
if(DS18B20_IN()) Data|=0x80;
Delay_us(10);
DS18B20_DIR_Out();//SET OUTPUT
DS18B20_PIN_H();
}
return Data;
}
void DS18B20_Write_Byte(U8 Data)
{
U8 i;
U8 testb;
DS18B20_DIR_Out();//SET OUTPUT
for (i=0;i<8;i++)
{
testb = Data&0x01;
Data=Data>>1;
if (testb)
{
DS18B20_PIN_L();
Delay_us(1);
DS18B20_PIN_H();
Delay_us(10);
}else
{
DS18B20_PIN_L();
Delay_us(1);
DS18B20_PIN_L();
Delay_us(10);
}
DS18B20_PIN_H();
}
}
U16 DS18B20_Temp_Raw(void)
{
U8 tl,th;
U16 tem;
DS18B20_Rst();
if(DS18B20_Check()) return 0;
DS18B20_Write_Byte(0xcc); // skip rom
DS18B20_Write_Byte(0x44); // convert
DS18B20_Rst();
if(DS18B20_Check()) return 0;
DS18B20_Write_Byte(0xcc);// skip rom
DS18B20_Write_Byte(0xbe);// convert
tl=DS18B20_Read_Byte(); // LSB
th=DS18B20_Read_Byte(); // MSB
tem=(th<<8)|tl; //
// Uart0Send(0xF0);
// Uart0Send(th);
// Uart0Send(tl);
return tem;
}
float DS18B20_TempValue(U16 tem)
{
if(tem&0xF800) return -(((~tem)+1)*0.0625); //返回温度值
else return (tem*0.0625);
}
U8 DS18B20_Init(void)
{
DS18B20_Rst();
if(DS18B20_Check()) return 1;
DS18B20_Temp_Raw();
return 0;
}
/*=============================================================================
* filename: VS1838B.c
* author: Wood Wang
* date: 2020.03
* describe:
*===========================================================================*/
/* Includes -----------------------------------------------------------------*/
#include "main.h"
U8 Ir_Status;
U8 Ir_Press;
U8 Ir_receive_ok;
U8 Ir_Receive_Count;
U32 Ir_Receive_Data;
U16 Interval;
sbit IR_Pin = P1^6; //int16
/*
********************************************************************************
红外接收数据处理函数
********************************************************************************
*/
U8 IR_Init(void)
{
Ir_Status = 0;
Ir_receive_ok = 0;
Ir_Receive_Count = 0;
Interval = 0;
Ir_Receive_Data = 0;
return 0;
}
U8 IR_Process(U8 *Ir_num)
{
U8 Address_H,Address_L; //地址码,地址反码
U8 Data_H,Data_L; //数据码,数据反码
if(Ir_receive_ok==1) //接收完成
{
Address_H=Ir_Receive_Data>>24; //得到地址码
Address_L=(Ir_Receive_Data>>16)&0xff; //得到地址反码
Ir_receive_ok = 0;
//if((Address_H==(u8)~Address_L)&&(Address_H==REMOTE_ID))//检验遥控识别码(ID)及地址
if((Address_H==(U8)~Address_L))//检验遥控识别码(ID)及地址
{
Data_H=Ir_Receive_Data>>8; //得到数据码
Data_L=Ir_Receive_Data; //得到数据反码
if(Data_H==(U8)~Data_L) //接收数据码正确
{
*Ir_num=Data_H; //正确键值返回键值
Ir_Receive_Data=0;
return 1;
}
}
}
if(Ir_Press)
{
return 2;
}
return 0;
}
//外部中断下降沿调用
void IR_Receive_Handler(void)
{
U16 Interval_tim=0;//两个下降沿间隔时间
switch(Ir_Status)
{
case 0://第一个下降沿,定时器开始计数
Ir_Status=1;
Interval = 0;
TR1 = 1;
Ir_Press = 0; //无按下
break;
case 1://第二个下降沿,定时器关闭,读取定时器计数值
//读取定时器计数值
Interval_tim = Interval;
Interval = 0;
//Uart0Send(Interval_tim);
if( (Interval_tim>=120)&&(Interval_tim<=150) )//判断引导码是否正确9+4.5ms
{
Ir_Status=2; //进入下一状态
}else //引导码错误,从新接收
{
Ir_Status=0;
TR1 = 0;
Ir_Receive_Count=0;
}
break;
case 2://开始32位数据的接收
//读取定时器计数值
Interval_tim = Interval;
Interval = 0;
if( (Interval_tim>=9)&&(Interval_tim<=13) ) //间隔1.12ms ->0
{
Ir_Receive_Data=Ir_Receive_Data<<1;
Ir_Receive_Count++;
}else if( (Interval_tim>=19)&&(Interval_tim<=26) ) //间隔2.25ms ->1
{
Ir_Receive_Data=Ir_Receive_Data<<1;
Ir_Receive_Data=Ir_Receive_Data|0x0001;
Ir_Receive_Count++;
}else//不是0,1 接收错误,从新接收
{
Ir_Status=0;
TR1 = 0;
Ir_Receive_Data=0;
Ir_Receive_Count=0;
}
//超出接收数据位数,接收下一个
if(Ir_Receive_Count==32)
{
Ir_receive_ok=1;//红外接收完成
Ir_Press = 1; //按下
Ir_Status=3;
TR1 = 1;
Ir_Receive_Count=0;
}
break;
case 3:
//读取定时器计数值
Interval_tim = Interval;
Interval = 0;
if(Interval_tim < 1000) //100ms
{
Ir_Press = 1; //按下
}else
{
Ir_Press = 0;
Ir_Status=0;
TR1 = 0;
}
break;
default :
Ir_Status = 0;
TR1 = 0;
break;
}
}
//100us 一次
void IR_Timer_Handler(void)
{
if(Interval < 1000) Interval++;
else
{
Ir_Status = 0;
Ir_Press = 0;
}
}
/*=============================================================================
* filename: main.c
* author: Wood Wang
* date: 2020.03
* describe:
*===========================================================================*/
/* Includes -----------------------------------------------------------------*/
#include "main.h"
#include "oled.h"
sbit led1 = P5^2;
sbit led2 = P5^3;
sbit beep = P1^0;
U16 RH_Read_Time;
U8 P_Check;
//=================================================================
//
//=================================================================
volatile unsigned int TimeTick;
volatile unsigned int Time_1ms;
void Delay_ms(unsigned int ms)
{
Time_1ms = ms;
while(Time_1ms);
}
void Delay_us(unsigned int us)
{
unsigned char i;
while(us--) for(i=30;i>0;i--) ;
}
//=============================================================
void Timer01_Init(void)
{
TimeTick = 0;
//Timer0=1ms
TMOD = 0X11; //16位定时器
TCON = 0X00;
TMCON = 0X00; //12分频
TL0 = (65536-(32000/(12*1))); //定时1ms
TH0 = (65536-(32000/(12*1)))>>8; //
TR0 = 1;
ET0 = 1; //中断
//Timer1=100us
TL1 = (65536-(3200/(12*1))); //定时100us
TH1 = (65536-(3200/(12*1)))>>8; //
TR1 = 1;
ET1 = 1; //中断
}
void GPIO_Init(void)
{
P0CON = 0x00; //设置P0为输入带上拉模式
P0PH = 0xFF;
P1CON = 0x01; //设置P1为高阻输入模式
P1PH = 0x00;
P2CON = 0xFC; //设置P20,P21为输入带上拉模式,其他推挽输出
P2PH = 0x03;
P3CON = 0xFF; //设置P3为强推挽模式
P3PH = 0x00;
P4CON = 0xFF; //设置P4为强推挽模式
P4PH = 0x00;
P5CON = 0xFF; //设置P5为强推挽模式
P5PH = 0x00;
//P16,P17=外部中断
P1CON &= 0X3F; //中断IO口设置为高阻输入
P1PH |= 0xC0; //中断IO口设置为高阻带上拉
//配置P16下降沿中断、P17边沿中断
//下降沿设置
INT0F = 0X00 ; //xxxx 0000 0关闭 1使能
INT1F = 0XC0 ; //xxxx xxxx 0关闭 1使能
INT2F = 0X00 ; //0000 xxxx 0关闭 1使能
//上升沿设置
INT0R = 0X00 ; //xxxx 0000 0关闭 1使能
INT1R = 0X80 ; //xxxx xxxx 0关闭 1使能
INT2R = 0X00 ; //0000 xxxx 0关闭 1使能
//外部中断设置
IE &= ~0x01; //0000 0x0x INT0使能
IE |= 0x04; //0000 0x0x INT1使能
IE1 &= ~0x08; //0000 x000 INT2使能
beep = 1;
led1 = 1;
led2 = 1;
}
//==============================================
int main(void)
{
U8 str[16];
U8 IR_num;
U8 rh,tem;
float t;
RH_Read_Time = 0;
P_Check = 0;
GPIO_Init();
Timer01_Init();
BTM_Init();
EA = 1;
Uart_Init(0,115200); //调试
Uart0SendStr("SinOne SC95F8617 Test. By WoodData.\n");
OLED_Init();
LCD12864RAM_ShowString(0,0,"SinOne SC95F8617.By WoodData.");
LCD12864RAM_DrawRect(0,0,OLED_MAX_X,OLED_MAX_Y,1);
LCD12864RAM_Refresh();
Delay_ms(1000);
LCD12864RAM_Clear();
if(IR_Init() == 0) Uart0SendStr("VS1838B IR Init OK.\n");
if(DS18B20_Init() == 0) Uart0SendStr("DS18B20 Init OK.\n");
if(DHT11_Init() == 0) Uart0SendStr("DHT11 Init OK.\n");
while(1)
{
if(IR_Process(&IR_num) == 1)
{
sprintf(str,"IR Key:%3bu\n",IR_num);
LCD12864RAM_ShowString(0,0,str);
LCD12864RAM_Refresh();
Uart0SendStr(str);
}
if(RH_Read_Time == 0)
{
if(RH_Read(&rh,&tem) == 0)
{
sprintf(str,"H:%3bu,T:%3bu\n",rh,tem);
LCD12864RAM_ShowString(0,16,str);
LCD12864RAM_Refresh();
Uart0SendStr(str);
}
t = DS18B20_TempValue(DS18B20_Temp_Raw());
sprintf(str,"T:%0.2f",t);
LCD12864RAM_ShowString(0,32,str);
LCD12864RAM_Refresh();
Uart0SendStr(str);
RH_Read_Time = 1000;
}
if(P_Check == 1)
{
LCD12864RAM_ShowString(0,48,"People In ");
LCD12864RAM_Refresh();
P_Check = 0;
}else if(P_Check == 2)
{
LCD12864RAM_ShowString(0,48,"People Out");
LCD12864RAM_Refresh();
P_Check = 0;
}
}
}
//===============================================
//中断
void Timer0_ISR() interrupt 1
{
TL0 = (65536-(32000/(12*1))); //定时1ms
TH0 = (65536-(32000/(12*1)))>>8; //
if(Time_1ms) Time_1ms--;
if(RH_Read_Time) RH_Read_Time--;
TimeTick++;
}
void Timer1_ISR() interrupt 3
{
TL1 = (65536-(3200/(12*1))); //定时100us
TH1 = (65536-(3200/(12*1)))>>8; //
IR_Timer_Handler();
}
void EX0() interrupt 0
{
TCON &= 0XFD;
}
void EX1() interrupt 2
{
TCON &= 0XF7;
//VS1838B红外解码
if(P16 == 0) //下降沿
{
led1 = ~led1;
IR_Receive_Handler();
}
//人体红外感应
if(P17 == 0) //下降沿
{
//beep = 1;
led2 = 1;
P_Check = 2;
}else
{
//beep = 0;
led2 = 0;
P_Check = 1;
}
}
void EX2() interrupt 10
{
}
|