Stanford_sun 2024-08-15 00:36 采纳率: 100%
浏览 5
已结题

对BH1750代码添加OLED后无法正常读取数值。

问题描述

我原来使用Z-stack协议栈来读取BH1750光照传感器,获取环境光照数值。编写代码后,可以正常读取。
代码有BH1750.h、BH1750.c、iic.h、iic.h,如下

iic.h

#ifndef _IIC_H
#define _IIC_H

#include <ioCC2530.h>
typedef unsigned char u8;

#define IIC_SDA_OUTMODE() {P0DIR|=0x1<<1;}
#define IIC_SDA_INPUTMODE() {P0DIR&=~(0x1<<1);}
#define IIC_SDA_OUT P0_1  //数据线输出
#define IIC_SDA_IN P0_1  //数据线输入
#define IIC_SCL P0_0  //时钟线

void DelayUs(u8 t);
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
u8 IIC_GetACK(void);
void IIC_SendACK(u8 stat);
void IIC_WriteOneByteData(u8 data);
u8 IIC_ReadOneByteData(void);
#endif

iic.c

#include "iic.h"
#include "OnBoard.h"
/*
函数功能:IIC接口初始化
硬件连接:
SDA:P0.5
SCL:P0.4
*/
void DelayUs(u8 t)
{
    MicroWait(t);
}
void IIC_Init(void)
{
    P0SEL&=~(0x3<<3); //配置通用GPIO口模式
    P0DIR|=0x3<<3;    //配置为输出模式
}

/*
函数功能:IIC总线起始信号
*/
void IIC_Start(void)
{
    IIC_SDA_OUTMODE(); //初始化SDA为输出模式
    IIC_SDA_OUT=1;     //数据线拉高
    IIC_SCL=1;          //时钟线 拉高
    DelayUs(4);        //电平保持时间
    IIC_SDA_OUT=0;     //数据线拉低
    DelayUs(4);        //电平保持时间
    IIC_SCL=0;         //时钟线拉低
}


/*
函数功能:IIC总线停止信号
*/
void IIC_Stop(void)
{
      IIC_SDA_OUTMODE(); //初始化SDA为输出模式
      IIC_SDA_OUT=0;          //数据线拉低
      IIC_SCL=0;              //时钟线拉低
      DelayUs(4);        //电平保持时间
      IIC_SCL=1;              //时钟线拉高
      DelayUs(4);        //电平保持时间
      IIC_SDA_OUT=1;          //数据线拉高
}

/*
函数功能:获取应答信号
返 回 值:1表示失败,0表示成功
*/
u8 IIC_GetACK(void)
{
    u8 cnt=0;
    IIC_SDA_INPUTMODE();//初始化SDA为输入模式
    IIC_SDA_OUT=1;           //数据线上拉
    DelayUs(2);         //电平保持时间
    IIC_SCL=0;               //时钟线拉低,告诉从机,主机需要数据
    DelayUs(2);         //电平保持时间,等待从机发送数据
    IIC_SCL=1;               //时钟线拉高,告诉从机,主机现在开始读取数据
    while(IIC_SDA_IN)   //等待从机应答信号
    {
        cnt++;
        if(cnt>250)return 1;
    }
    IIC_SCL=0;               //时钟线拉低,告诉从机,主机需要数据
    return 0;
}

/*
函数功能:主机向从机发送应答信号
函数形参:0表示应答,1表示非应答
*/
void IIC_SendACK(u8 stat)
{
      IIC_SDA_OUTMODE(); //初始化SDA为输出模式
      IIC_SCL=0;              //时钟线拉低,告诉从机,主机需要发送数据
      if(stat)IIC_SDA_OUT=1; //数据线拉高,发送非应答信号
      else IIC_SDA_OUT=0;      //数据线拉低,发送应答信号
      DelayUs(2);            //电平保持时间,等待时钟线稳定
      IIC_SCL=1;                  //时钟线拉高,告诉从机,主机数据发送完毕
      DelayUs(2);            //电平保持时间,等待从机接收数据
      IIC_SCL=0;                    //时钟线拉低,告诉从机,主机需要数据
}


/*
函数功能:IIC发送1个字节数据
函数形参:将要发送的数据
*/
void IIC_WriteOneByteData(u8 data)
{
      u8 i;
      IIC_SDA_OUTMODE(); //初始化SDA为输出模式
      IIC_SCL=0;              //时钟线拉低,告诉从机,主机需要发送数据
      for(i=0;i<8;i++)
      {
          if(data&0x80)IIC_SDA_OUT=1; //数据线拉高,发送1
          else IIC_SDA_OUT=0;      //数据线拉低,发送0
          IIC_SCL=1;                  //时钟线拉高,告诉从机,主机数据发送完毕
          DelayUs(2);            //电平保持时间,等待从机接收数据
          IIC_SCL=0;                       //时钟线拉低,告诉从机,主机需要发送数据
          DelayUs(2);            //电平保持时间,等待时钟线稳定
          data<<=1;              //先发高位
      }
}


/*
函数功能:IIC接收1个字节数据
返 回 值:收到的数据
*/
u8 IIC_ReadOneByteData(void)
{
    u8 i,data;
    IIC_SDA_INPUTMODE();//初始化SDA为输入模式
    for(i=0;i<8;i++)
    {
        IIC_SCL=0;               //时钟线拉低,告诉从机,主机需要数据
        DelayUs(2);         //电平保持时间,等待从机发送数据
        IIC_SCL=1;               //时钟线拉高,告诉从机,主机现在正在读取数据
        data<<=1;           
        if(IIC_SDA_IN)data|=0x01;
        DelayUs(2);         //电平保持时间,等待时钟线稳定
    }
    IIC_SCL=0;                       //时钟线拉低,告诉从机,主机需要数据 (必须拉低,否则将会识别为停止信号)
    return data;
}

BH1750.h

#ifndef _BH1750_H
#define _BH1750_H
#include "iic.h"
#include <ioCC2530.h>
u8 Read_BH1750_Data(void);
#endif

BH1750.c

#include "bh1750.h"
#include "OnBoard.h"
u8 Read_BH1750_Data()
{   IIC_Init();
    unsigned char t0;
    unsigned char t1;
    unsigned char t;
   
    u8 r_s=0; 
    IIC_Start(); //发送起始信号
    IIC_WriteOneByteData(0x46);
    r_s=IIC_GetACK();//获取应答
    if(r_s)
        HalUARTWrite(0,"error:1\n",8); //(串口0,'字符',字符个数。)
    IIC_WriteOneByteData(0x01);
    r_s=IIC_GetACK();//获取应答
    if(r_s)
        HalUARTWrite(0,"error:2\n",8); //(串口0,'字符',字符个数。)
    IIC_Stop(); //停止信号 
    
    IIC_Start(); //发送起始信号
    IIC_WriteOneByteData(0x46);
    r_s=IIC_GetACK();//获取应答
    if(r_s)
        HalUARTWrite(0,"error:3\n",8); //(串口0,'字符',字符个数。)
    IIC_WriteOneByteData(0x01);
    r_s=IIC_GetACK();//获取应答
    if(r_s)
        HalUARTWrite(0,"error:4\n",8); //(串口0,'字符',字符个数。)
    IIC_Stop(); //停止信号 
    
    IIC_Start(); //发送起始信号
    IIC_WriteOneByteData(0x46);
    r_s=IIC_GetACK();//获取应答
    if(r_s)
        HalUARTWrite(0,"error:5\n",8); //(串口0,'字符',字符个数。)
    IIC_WriteOneByteData(0x10);
    r_s=IIC_GetACK();//获取应答
    if(r_s)
        HalUARTWrite(0,"error:6\n",8); //(串口0,'字符',字符个数。)
    IIC_Stop(); //停止信号 
    

    IIC_Start(); //发送起始信号
    IIC_WriteOneByteData(0x47);
    r_s=IIC_GetACK();//获取应答
    if(r_s)
        HalUARTWrite(0,"error:7\n",8); //(串口0,'字符',字符个数。)
    
    t0=IIC_ReadOneByteData(); //接收数据
    IIC_SendACK(0); //发送应答信号
    t1=IIC_ReadOneByteData(); //接收数据
    IIC_SendACK(1); //发送非应答信号
    IIC_Stop(); //停止信号
    
     t=(((t0<<8)|t1)/1.2);
     return t;  
}

后来,遇到新的需求,要求将光照数据显示在IIC通信协议的OLED屏幕上;由于hal_lcd.c文件原来是SPI通信协议的,我对其重构为IIC通信协议的代码。

hal_lcd.c代码

/****************************************************************************
* Filename: hal_lcd.c
* Author:      xiaoHuiHui
* Date:        2019-05-11
* Version:     1.0
* Description: OLED driver
****************************************************************************/
#include "hal_types.h"
#include "hal_lcd.h"
#include "OSAL.h"
#include "OnBoard.h"
#include "hal_assert.h"
#include <string.h>

#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
  #include "DebugTrace.h"
#endif

#define SCL P1_2 //串行时钟
#define SDA P1_3 //串行数据

#define XLevelL            0x00
#define XLevelH            0x10
#define XLevel             ((XLevelH&0x0F)*16+XLevelL)
#define Max_Column         128
#define Max_Row            64
#define Brightness         0xCF 
#define X_WIDTH            128
#define Y_WIDTH            64

#define LCD_MAX_BUF        25
#define HAL_LCD_MAX_CHARS  16   // Max number of chars on a single LCD line 


const unsigned char F8X16[]=    
{
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,// 0
 
  0x00,0x06,0x01,0x01,0x02,0x02,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,//~ 94
};


#if (HAL_LCD == TRUE)
void HalLcd_HW_Init(void);
void HalLcd_HW_WaitUs(uint16 i);
void HalLcd_HW_Clear(void);
void HalLcd_HW_Control(uint8 cmd);
void HalLcd_HW_Write(uint8 data);
void HalLcd_HW_SetContrast(uint8 value);
void HalLcd_HW_WriteChar(uint8 line, uint8 col, char text);
void HalLcd_HW_WriteLine(uint8 line, const char *pText);

void DelayMS(unsigned int msec);
void LCD_DLY_ms(unsigned int ms);
void LCD_WrDat(unsigned char dat);
void LCD_WrCmd(unsigned char cmd);
void LCD_Set_Pos(unsigned char x, unsigned char y);
void LCD_Fill(unsigned char bmp_dat) ;
void LCD_CLS(void);
void LcdClearLine(unsigned char y, unsigned char count);

void LCD_P8x16Str(unsigned char x, unsigned char y,unsigned char ch[]);
void HalLcdDisplayPercentBar( char *title, uint8 value );
void LCD_P16x16Ch(unsigned char x, unsigned char y, unsigned char N);
#endif //LCD


/**************************************************************************************************
 * @fn      HalLcdInit
 *
 * @brief   Initilize LCD Service
 *
 * @param   init - pointer to void that contains the initialized value
 *
 * @return  None
 **************************************************************************************************/
void HalLcdInit(void)
{
#if (HAL_LCD == TRUE)
  HalLcd_HW_Init();
#endif
}

/**************************************************************************************************
 * @fn      HalLcdWriteValue
 *
 * @brief   Write a value to the LCD
 *
 * @param   value  - value that will be displayed
 *          radix  - 8, 10, 16
 *          option - display options
 *
 * @return  None
 **************************************************************************************************/
void HalLcdWriteValue ( uint32 value, const uint8 radix, uint8 option)
{
#if (HAL_LCD == TRUE)
  uint8 buf[LCD_MAX_BUF];

  _ltoa( value, &buf[0], radix );
  HalLcdWriteString( (char*)buf, option );
#endif
}

/**************************************************************************************************
 * @fn      HalLcdWriteScreen
 *
 * @brief   Write a value to the LCD
 *
 * @param   line1  - string that will be displayed on line 1
 *          line2  - string that will be displayed on line 2
 *
 * @return  None
 **************************************************************************************************/
void HalLcdWriteScreen( char *line1, char *line2 )
{
#if (HAL_LCD == TRUE)
  HalLcdWriteString( line1, 1 );
  HalLcdWriteString( line2, 2 );
#endif
}

/**************************************************************************************************
 * @fn      HalLcdWriteStringValue
 *
 * @brief   Write a string followed by a value to the LCD
 *
 * @param   title  - Title that will be displayed before the value
 *          value  - value
 *          format - redix
 *          line   - line number
 *
 * @return  None
 **************************************************************************************************/
void HalLcdWriteStringValue( char *title, uint16 value, uint8 format, uint8 line )
{
#if (HAL_LCD == TRUE)
  uint8 tmpLen;
  uint8 buf[LCD_MAX_BUF];
  uint32 err;

  tmpLen = (uint8)osal_strlen( (char*)title );
  osal_memcpy( buf, title, tmpLen );
  //buf[tmpLen] = ' ';
  err = (uint32)(value);
  _ltoa( err, &buf[tmpLen], format );
  HalLcdWriteString( (char*)buf, line );    
#endif
}

/**************************************************************************************************
 * @fn      HalLcdWriteStringValue
 *
 * @brief   Write a string followed by a value to the LCD
 *
 * @param   title   - Title that will be displayed before the value
 *          value1  - value #1
 *          format1 - redix of value #1
 *          value2  - value #2
 *          format2 - redix of value #2
 *          line    - line number
 *
 * @return  None
 **************************************************************************************************/
void HalLcdWriteStringValueValue( char *title, uint16 value1, uint8 format1,
                                  uint16 value2, uint8 format2, uint8 line )
{

#if (HAL_LCD == TRUE)

  uint8 tmpLen;
  uint8 buf[LCD_MAX_BUF];
  uint32 err;

  tmpLen = (uint8)osal_strlen( (char*)title );
  if ( tmpLen )
  {
    osal_memcpy( buf, title, tmpLen );
    //buf[tmpLen++] = ' ';
  }

  err = (uint32)(value1);
  _ltoa( err, &buf[tmpLen], format1 );
  tmpLen = (uint8)osal_strlen( (char*)buf );

  buf[tmpLen++] = ',';
  buf[tmpLen++] = ' ';
  err = (uint32)(value2);
  _ltoa( err, &buf[tmpLen], format2 );

  HalLcdWriteString( (char *)buf, line );   

#endif
}

#if (HAL_LCD == TRUE)
void DelayMS(unsigned int msec)
{ 
    unsigned int i,j;
    
    for (i=0; i<msec; i++)
        for (j=0; j<530; j++);
}

/*********************LCD 延时1ms************************************/
void LCD_DLY_ms(unsigned int ms)
{                         
    unsigned int a;
    while(ms)
    {
        a=1800;
        while(a--);
        ms--;
    }
    return;
}
/**********************************************
//IIC Start
**********************************************/
void IIC_start()
{
   SCL = 1;   
   SDA = 1;
    asm("NOP");
    asm("NOP");
   SDA = 0;
    asm("NOP");
    asm("NOP");
   SCL = 0;
}

/**********************************************
//IIC Stop
**********************************************/
void IIC_stop()
{
   SCL = 0;
   SDA = 0;
    asm("NOP");
    asm("NOP");
   SCL = 1;
   SDA = 1;
    asm("NOP");
    asm("NOP");
}

/**********************************************
// 通过I2C总线写一个字节
**********************************************/
void Write_IIC_Byte(unsigned char IIC_Byte)
{
  unsigned char i;
  for(i=0;i<8;i++)
  {
    if(IIC_Byte & 0x80)
      SDA=1;
    else
      SDA=0;
        asm("NOP");
        asm("NOP");        
    SCL=1;
        asm("NOP");
        asm("NOP");        
    SCL=0;
    IIC_Byte<<=1;
  }
  SDA=1;
    asm("NOP");
    asm("NOP");
  SCL=1;
    asm("NOP");
    asm("NOP");
  SCL=0;
    asm("NOP");
    asm("NOP");
}
/*********************LCD写数据************************************/ 
void LCD_WrDat(unsigned char dat)     
{
  IIC_start();
  Write_IIC_Byte(0x78);
  Write_IIC_Byte(0x40);     //write data
  Write_IIC_Byte(dat);
  IIC_stop();
}

/*********************LCD写命令************************************/                                        
void LCD_WrCmd(unsigned char cmd)
{
  IIC_start();
  Write_IIC_Byte(0x78);            //Slave address,SA0=0
  Write_IIC_Byte(0x00);     //write command
  Write_IIC_Byte(cmd);
  IIC_stop();   
}

/*********************LCD 设置坐标************************************/
void LCD_Set_Pos(unsigned char x, unsigned char y) 
{ 
  LCD_WrCmd(0xb0+y);
  LCD_WrCmd(((x&0xf0)>>4)|0x10);
  LCD_WrCmd((x&0x0f)|0x01); 
} 

/*********************LCD全屏************************************/
void LCD_Fill(unsigned char bmp_dat) 
{
    unsigned char y,x;
    for(y=0;y<8;y++)
    {
        LCD_WrCmd(0xb0+y);
        LCD_WrCmd(0x01);
        LCD_WrCmd(0x10);
        for(x=0;x<X_WIDTH;x++)
            LCD_WrDat(bmp_dat);
    }
}

/*********************LCD复位************************************/
void LCD_CLS(void)
{
    unsigned char y,x;    
    for(y=0;y<8;y++)
    {
        LCD_WrCmd(0xb0+y);
        LCD_WrCmd(0x01);
        LCD_WrCmd(0x10); 
        for(x=0;x<X_WIDTH;x++)
            LCD_WrDat(0);
    }
}

void LcdClearLine(unsigned char y, unsigned char count)
{
    unsigned char x,j;  
    
    for(j=y; j<(y+count); j++)
    {
        LCD_WrCmd(0xb0+j);
        LCD_WrCmd(0x01);
        LCD_WrCmd(0x10); 
        for(x=0;x<X_WIDTH;x++)
           LCD_WrDat(0);
    }
}

void HalLcdWriteString (char *str, uint8 option)
{
  uint8 x=0,y=0,strLen;
  uint8 lcdBuf[HAL_LCD_MAX_CHARS+1];
    
  x=0;
  y = (option-1)*2;
  strLen = (uint8)osal_strlen( (char*)str );

  /* Check boundries */
  if ( strLen > HAL_LCD_MAX_CHARS )
    strLen = HAL_LCD_MAX_CHARS;

  osal_memset(lcdBuf, 0, HAL_LCD_MAX_CHARS+1);
  osal_memcpy( lcdBuf, str, strLen );
  
  LcdClearLine(y, 2);
  LCD_P8x16Str(x, y, lcdBuf);
}

/***能描述:显示8*16一组标准ASCII字符串     显示的坐标(x,y),y为页范围0~7***/
void LCD_P8x16Str(unsigned char x, unsigned char y,unsigned char ch[])
{
    unsigned char c=0,i=0,j=0;
    
    while (ch[j]!='\0')
    {    
        c =ch[j]-32;
        if(x>120){
          x=0;
          y++;
        }
        LCD_Set_Pos(x,y);    
        for(i=0;i<8;i++)     
            LCD_WrDat(F8X16[c*16+i]);
        LCD_Set_Pos(x,y+1);    
        for(i=0;i<8;i++)     
            LCD_WrDat(F8X16[c*16+i+8]);  
        x+=8;
        j++;
    }
}


void HalLcd_HW_WaitUs(uint16 microSecs)
{
  while(microSecs--)
  {
    /* 32 NOPs == 1 usecs */
    asm("nop"); asm("nop"); asm("nop"); asm("nop");
    asm("nop"); asm("nop"); asm("nop"); asm("nop");
  }
}

void HalLcd_HW_Init(void)
{ 
    P1SEL &= 0xF3;
    P1DIR |= 0x0C;  //P05、P06定义为输出
    LCD_DLY_ms(50);  
    
  LCD_WrCmd(0xae);//--turn off oled panel
  LCD_WrCmd(0x00);//---set low column address
  LCD_WrCmd(0x10);//---set high column address
  LCD_WrCmd(0x40);//--set start line address  Set Mapping RAM Display Start Line (0x00~0x3F)
  LCD_WrCmd(0x81);//--set contrast control register
  LCD_WrCmd(Brightness); // Set SEG Output Current Brightness
  LCD_WrCmd(0xa1);//--Set SEG/Column Mapping     0xa0左右反置 0xa1正常
  LCD_WrCmd(0xc8);//Set COM/Row Scan Direction   0xc0上下反置 0xc8正常
  LCD_WrCmd(0xa6);//--set normal display
  LCD_WrCmd(0xa8);//--set multiplex ratio(1 to 64)
  LCD_WrCmd(0x3f);//--1/64 duty
  LCD_WrCmd(0xd3);//-set display offset Shift Mapping RAM Counter (0x00~0x3F)
  LCD_WrCmd(0x00);//-not offset
  LCD_WrCmd(0xd5);//--set display clock divide ratio/oscillator frequency
  LCD_WrCmd(0x80);//--set divide ratio, Set Clock as 100 Frames/Sec
  LCD_WrCmd(0xd9);//--set pre-charge period
  LCD_WrCmd(0xf1);//Set Pre-Charge as 15 Clocks & Discharge as 1 Clock
  LCD_WrCmd(0xda);//--set com pins hardware configuration
  LCD_WrCmd(0x12);
  LCD_WrCmd(0xdb);//--set vcomh
  LCD_WrCmd(0x40);//Set VCOM Deselect Level
  LCD_WrCmd(0x20);//-Set Page Addressing Mode (0x00/0x01/0x02)
  LCD_WrCmd(0x02);//
  LCD_WrCmd(0x8d);//--set Charge Pump enable/disable
  LCD_WrCmd(0x14);//--set(0x10) disable
  LCD_WrCmd(0xa4);// Disable Entire Display On (0xa4/0xa5)
  LCD_WrCmd(0xa6);// Disable Inverse Display On (0xa6/a7) 
  LCD_WrCmd(0xaf);//--turn on oled panel
  LCD_Fill(0x00);  //初始清屏 
  LCD_Set_Pos(0,0); 
}


#endif

重新烧录之后,OLED能够正常显示,但是无法读取BH1750光照强度了。我也没有改BH1750的代码,为什么会出现这种情况?

  • 写回答

3条回答 默认 最新

  • Stanford_sun 2024-08-15 16:45
    关注

    是引脚未正确初始化

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 8月23日
  • 已采纳回答 8月15日
  • 创建了问题 8月15日

悬赏问题

  • ¥15 想问一下STM32创建工程模板时遇到得问题
  • ¥15 Fiddler抓包443
  • ¥20 Qt Quick Android 项目报错及显示问题
  • ¥15 而且都没有 OpenCVConfig.cmake文件我是不是需要安装opencv,如何解决?
  • ¥15 oracleBIEE analytics
  • ¥15 H.264选择性加密例程
  • ¥50 windows的SFTP服务器如何能批量同步用户信息?
  • ¥15 centos7.9升级python3.0的问题
  • ¥15 安装CentOS6时卡住
  • ¥20 c语言写的8051单片机存储器mt29的模块程序