[方案相关]【HC32L196PCTA测评】+传感器检测篇

借助各种传感器的使用,可有效地拓展开发板的功能。这里仅以2种常用的I2C接口的传感器来进行环境状态的检测并通过开发板上的液晶显示屏来加以显示。
1 . BMP085
BMP085是一种温度与大气压传感器,它与开发板的连接关系为:
SCL ---PB7
SDA ---PB8
为便于自由地使用相应的引脚,这里是以GPIO模拟I2C的方式来驱动。
所用引脚输出高低电平的语句定义为:
#define SCL_Set1()      Gpio_SetIO(GpioPortB, GpioPin7)
#define SCL_Clr1()      Gpio_ClrIO(GpioPortB, GpioPin7)
#define SDA_Set1()      Gpio_SetIO(GpioPortB, GpioPin8)
#define SDA_Clr1()      Gpio_ClrIO(GpioPortB, GpioPin8)
数据引脚读取输入信号状态的语句定义为:
#define SDA_IN         Gpio_GetInputIO(GpioPortB, GpioPin8)
对BMP085所用引脚进行配置的函数为:
复制
void App_bmp085_Init(void)

{

    stc_gpio_cfg_t stcGpioCfg;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);

    stcGpioCfg.enDir = GpioDirOut;

    stcGpioCfg.enPu = GpioPuEnable;

    stcGpioCfg.enPd = GpioPdDisable;

    Gpio_Init(GpioPortB, GpioPin7, &stcGpioCfg);

        Gpio_Init(GpioPortB, GpioPin8, &stcGpioCfg);

}

由于在使用过程中,数据引脚既要进行数据输出,又要读取数据,故常要要进行输入与输出模式的转换,为此定义了2个模式设置的函数以供模式切换来使用,其函数内容为:
复制
void INPUT_MODE_SET()

{

    stc_gpio_cfg_t stcGpioCfg;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 

    stcGpioCfg.enDir = GpioDirIn;

    stcGpioCfg.enPu = GpioPuDisable;

    stcGpioCfg.enPd = GpioPdEnable;

    Gpio_ClrIO(GpioPortB, GpioPin8);

    Gpio_Init(GpioPortB, GpioPin8, &stcGpioCfg);

}



void OUTPUT_MODE_SET()

{

    stc_gpio_cfg_t stcGpioCfg;

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE); 

    stcGpioCfg.enDir = GpioDirOut;

    stcGpioCfg.enPu = GpioPuDisable;

    stcGpioCfg.enPd = GpioPdEnable;

    Gpio_ClrIO(GpioPortB, GpioPin8);

    Gpio_Init(GpioPortB, GpioPin8, &stcGpioCfg);

}

BMP085的初始化函数为:
复制
void Init_BMP085()

{

    ac1 = Multiple_read(0xAA);

    ac2 = Multiple_read(0xAC);

    ac3 = Multiple_read(0xAE);

    ac4 = Multiple_read(0xB0);

    ac5 = Multiple_read(0xB2);

    ac6 = Multiple_read(0xB4);

    b1 =  Multiple_read(0xB6);

    b2 =  Multiple_read(0xB8);

    mb =  Multiple_read(0xBA);

    mc =  Multiple_read(0xBC);

    md =  Multiple_read(0xBE);

}

此外,BMP085模拟I2C发送字节数据的函数为:
复制
void BMP085_Send_Byte(char txd)

{

    char t;

    OUTPUT_MODE_SET();

    SCL_Clr1();

    for(t=0;t<8;t++)

    {

        if((txd&0x80)>>7)

            SDA_Set1();

        else

            SDA_Clr1();

        txd<<=1;

        delay1us(1);

        SCL_Set1();

        delay1us(1);

        SCL_Clr1();

        delay1us(1);

    }

}

BMP085读取字节数据的函数为:
复制
char BMP085_Read_Byte(unsigned char ack)

{

      unsigned char i,receive=0;

      INPUT_MODE_SET();

      for(i=0;i<8;i++)

      {

        SCL_Clr1();

        delay1us(1);

        SCL_Set1();

        receive<<=1;

        if(SDA_IN) receive++;

        delay1us(1);

    }

    if(!ack)

        BMP085_NAck();

    else

        BMP085_Ack();

    return receive;

}

BMP085读取温度与大气压的功能函数为:
复制
long bmp085ReadTemp(void)

{

    BMP085_Start();

    BMP085_Send_Byte(BMP085_SlaveAddress);

    while(BMP085_Wait_Ack());

    BMP085_Send_Byte(0xF4);

    while(BMP085_Wait_Ack());

    BMP085_Send_Byte(0x2E);

    while(BMP085_Wait_Ack());

    BMP085_Stop();

    delay1ms(10);

    return (long) Multiple_read(0xF6);

}



long bmp085ReadPressure(void)

{

    long pressure = 0;

    BMP085_Start();

    BMP085_Send_Byte(BMP085_SlaveAddress);

    while(BMP085_Wait_Ack()){}

    BMP085_Send_Byte(0xF4);

    while(BMP085_Wait_Ack()){}

    BMP085_Send_Byte(0x34);

    while(BMP085_Wait_Ack()){}

    BMP085_Stop();

    delay1ms(10);

    pressure = Multiple_read(0xF6);

    pressure &= 0x0000FFFF;

    return pressure;

}

实现检测数据数值变换的函数为:
复制
void bmp085Convert()

{

      unsigned int ut;

      unsigned long up;

      long x1, x2, b5, b6, x3, b3, p;

      unsigned long b4, b7;

      ut = bmp085ReadTemp();

      up = bmp085ReadPressure();

      x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;

      x2 = ((long) mc << 11) / (x1 + md);

      b5 = x1 + x2;

      temperature1 = ((b5 + 8) >> 4);

      b6 = b5 - 4000;

      x1 = (b2 * (b6 * b6)>>12)>>11;

      x2 = (ac2 * b6)>>11;

      x3 = x1 + x2;

      b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

      x1 = (ac3 * b6)>>13;

      x2 = (b1 * ((b6 * b6)>>12))>>16;

      x3 = ((x1 + x2) + 2)>>2;

      b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

      b7 = ((unsigned long)(up - b3) * (50000>>OSS));

      if (b7 < 0x80000000)

        p = (b7<<1)/b4;

      else

        p = (b7/b4)<<1;

      x1 = (p>>8) * (p>>8);

      x1 = (x1 * 3038)>>16;

      x2 = (-7357 * p)>>16;

      pressure = p+((x1 + x2 + 3791)>>4);

}

利用液晶显示屏实现温度与大气压检测值显示的主程序为:
复制
int32_t main(void)

{

        int8_t i=0;

    Sysctrl_ClkSourceEnable(SysctrlClkRCL,TRUE);            ///< 使能RCL时钟

    Sysctrl_SetRCLTrim(SysctrlRclFreq32768);                ///< 配置内部低速时钟频率为32.768kHz

    Sysctrl_SetPeripheralGate(SysctrlPeripheralLcd,TRUE);      ///< 开启LCD时钟

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);     ///< 开启GPIO时钟

    App_PortCfg();               ///< LCD端口配置

    App_LcdCfg();                ///< LCD模块配置

    Lcd_ClearDisp();              ///< 清屏

    Lcd_WriteRam(0,0x00000000);   ///< 赋值寄存器LCDRAM0

        Lcd_WriteRam(1,0x00000000);   ///< 赋值寄存器LCDRAM1

        App_bmp085_Init();

        Init_BMP085();

           bmp085Convert();

        delay1ms(500);

        key_init();

    while(1)

    {

                            if(Gpio_GetInputIO(GpioPortA, GpioPin7)==0)

                            {

                                s=(d[(pressure/100)%1000/100]<<16)+d[(pressure/100)/1000];

                                Lcd_WriteRam(0,s);

                                s=(d[(pressure/100)%10]<<16)+d[(pressure/100)%100/10];

                                Lcd_WriteRam(1,s);

                                }

                                else 

                                {

                                s=0;

                                  Lcd_WriteRam(0,s);

                                    s=(d[(temperature1/10)%10]<<16)+d[(temperature1/10)/10];

                                Lcd_WriteRam(1,s);

                          }

                          delay1ms(500);

                          bmp085Convert();

    }

}

经程序的编译与下载,其相应效果如图1和图2所示。

由于液晶显示屏的显示内容有限,故在显示时是通过开发板上的用户键来切换显示的内容,其通常状态下是显示温度值,而在按下按键后是显示大气压值。

图1  温度检测

图2 气压检测
2.BH1750
所用的另一种传感器是光照强度传感器BH1750,由于它也是一种I2C器件,故在基本用法上较为相同,其主要区别在于功能处理方面。

BH1750发送字节数据的函数为:
复制
void BH1750_SendByte(char data)

{

    char i;

    IIC_OUTPUT_MODE_SET();

    SCL_Clr();

    delay1us(2);

    for (i=0;i<8;i++)

    {

        if(data&0x80) SDA_Set();

        else SDA_Clr();

        data <<= 1;

        SCL_Set();

        delay1us(2);

        SCL_Clr();

        delay1us(2);

    }

}

BH1750接收字节数据的函数为:
复制
char BH1750_RecvByte()

{

    char i;

    char data = 0;

    IIC_INPUT_MODE_SET();

    for (i=0;i<8;i++)

    {

        SCL_Clr();

        delay1us(2);

        SCL_Set();

        data <<= 1;

        SCL_Set();

        if(IIC_SDA_IN) data|=0x01;

        delay1us(2);

    }

    SCL_Clr();

    return data;

}

读取光照强度的函数为:
复制
void Get_Sunlight_Value()

{

    int dis_data=0;

    float temp;

    char i=0;

    unsigned int sd;

    Single_Write_BH1750(0x01);

    Single_Write_BH1750(0x10);

    delay1ms(180);

    Multiple_Read_BH1750();

    for(i=0;i<3;i++)    dis_data=BUF[0];

    dis_data=(dis_data<<8)+BUF[1];

    temp=(float)dis_data/1.2;

    sd=temp;

        s=(d[sd%1000/100]<<16)+d[sd/1000];

        Lcd_WriteRam(0,s);

        s=(d[sd%10]<<16)+d[sd%100/10];

        Lcd_WriteRam(1,s);

}

使用液晶屏来显示光照强度的主程序为:
复制
int32_t main(void)

{

        int8_t i=0;

        Sysctrl_ClkSourceEnable(SysctrlClkRCL,TRUE);            ///< 使能RCL时钟

    Sysctrl_SetRCLTrim(SysctrlRclFreq32768);                ///< 配置内部低速时钟频率为32.768kHz

    Sysctrl_SetPeripheralGate(SysctrlPeripheralLcd,TRUE);     ///< 开启LCD时钟

    Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE);    ///< 开启GPIO时钟

    App_PortCfg();                ///< LCD端口配置

    App_LcdCfg();                 ///< LCD模块配置

    Lcd_ClearDisp();               ///< 清屏

    Lcd_WriteRam(0,0x00000000);   ///< 赋值寄存器LCDRAM0

    Lcd_WriteRam(1,0x00000000);   ///< 赋值寄存器LCDRAM1

        BH1750_Init();

        delay1ms(500);

        key_init();

    while(1)

    {

                  Get_Sunlight_Value();

                  delay1ms(500);

    }

}

经程序的编译与下载,其相应效果如图3所示。

图3  检测效果
---------------------
作者:jinglixixi
链接:https://bbs.21ic.com/icview-3319922-1-1.html
来源:21ic.com
此文章已获得原创/原创奖标签,著作权归21ic所有,任何人未经允许禁止转载。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值