打印
[活动专区]

【赛元SC95F】+ 测试各种传感器和OLED显示(三)

[复制链接]
1146|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本次测试测试了: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
{
}








使用特权

评论回复

相关帖子

沙发
21ic小喇叭| | 2020-4-1 10:49 | 只看该作者
感谢分享,奖励100家园币,家园币可以兑换礼品或抽奖,欢迎体验~

使用特权

评论回复
板凳
海力小卢as| | 2020-4-16 13:00 | 只看该作者
非常的好,太好了

使用特权

评论回复
地板
heimaojingzhang| | 2020-5-13 16:29 | 只看该作者
非常感谢楼主分享

使用特权

评论回复
5
keaibukelian| | 2020-5-13 16:29 | 只看该作者
别的型号可以直接移植吗

使用特权

评论回复
6
labasi| | 2020-5-13 16:30 | 只看该作者
好羡慕楼主 真不错啊

使用特权

评论回复
7
paotangsan| | 2020-5-13 16:30 | 只看该作者
楼主辛苦了 能打包一个工程来吗

使用特权

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

本版积分规则

115

主题

4395

帖子

25

粉丝