stm32f4xx HAL lib& PCF8457AT - 没有写入响应

时间:2017-11-18 18:27:08

标签: stm32 stm32f4discovery stm32f4

我有stm32f4-discovery工具包,我想尝试用于hd44870 LCD的i / o扩展器。我有一个PCF8574AT link to io example like mine 8位扩展器,其中i2c地址是hi2c3硬件上的0x3f(由i2c扫描器检查)。对于c / c ++,在Eclipse环境中使用HAL库。好的,看看代码。

首先,我初始化i2c3 - 就像SCL上的数据表100kHz一样:

static void MX_I2C3_Init(void)
{

  hi2c3.Instance = I2C3;
  hi2c3.Init.ClockSpeed = 100000;
  hi2c3.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c3.Init.OwnAddress1 = 0;
  hi2c3.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c3.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c3.Init.OwnAddress2 = 0;
  hi2c3.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c3.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c3) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

然后尝试将数据发送到I / O扩展器。但在此之前,我检查i / o是否可以使用:

result = HAL_I2C_IsDeviceReady(&hi2c3,0x3f , 2, 2);
if (result == HAL_BUSY)
        {
          HD44780_Puts(6, 1, "busy");
        }else{
            HD44780_Puts(6, 1, "ready");
            uint8_t data_io = 0xff;
            HAL_I2C_Master_Transmit(&hi2c3, 0x3f, data_io, 1, 100);
        }

在同一个扩展器上没有任何变化。什么错误或者i / 0扩展器的任何想法都被打破了?

2 个答案:

答案 0 :(得分:0)

我不确定HAL驱动程序,真的从未使用过HAL。但我已触及pcf8574 IO扩展器。 正如您所说,您已经使用扫描仪进行了检查,如果您获得了地址,则线路和设备都可以。由于我不是I2C和HAL库的专家,我将展示我的I2C驱动程序,它依赖于STM32标准外设驱动程序,它适用于PCF8574和各种I2C设备。有一个例子,片段(阻止模式,不基于irq):

  1. 检查IO是否不忙。

    while(I2C_GetFlagStatus(&I2Cx, I2C_FLAG_BUSY) == SET){
    if((timeout--) == 0) return -ETIMEDOUT;
    

    }

  2. 生成开始条件并设置写入条件(写入模式的地址)。

    I2C_TransferHandling(&I2Cx, dev_addr, 1, I2C_SoftEnd_Mode, I2C_Generate_Start_Write);
    while(I2C_GetFlagStatus(&I2Cx, I2C_ISR_TXIS) == RESET){
        if((timeout--) == 0) return -ENODEV;
    }
    
  3. 现在您可以发送数据字节(这是您的IO状态),此函数直接写入I2C TX(收发器)寄存器:

    I2C_SendData(&I2Cx, reg_addr);
    while(I2C_GetFlagStatus(&I2Cx, I2C_ISR_TC) == RESET){
        if((timeout--) == 0) return -EIO;
    }
    
  4. 生成读取条件而不是从PCF8574读取数据应该与刚刚写入的数据相同(如果没有切换IO扩展器)。基本上你可以读取字节或更多字节(取决于设备)。在你的情况下,PCF8574(8位)只提供1个字节。

    I2C_TransferHandling(dev->channel,dev_addr, len,  I2C_AutoEnd_Mode,I2C_Generate_Start_Read);
    size_t i;
    for(i=0;i<len;i++){
        timeout = I2C_TIMEOUT;
        while(I2C_GetFlagStatus(dev->channel, I2C_ISR_RXNE) == RESET){
            if((timeout--) == 0) return -EIO;
        }
    
        data[i] = I2C_ReceiveData(dev->channel);
    }
    
  5. 您可以继续进行RW操作,或者只是等到设备自动停止在线转换:

    while(I2C_GetFlagStatus(&I2Cx, I2C_FLAG_STOPF) == RESET){
        if((timeout--) == 0) return -EIO;
    }
    
    I2C_ClearFlag(&I2Cx, I2C_ICR_STOPCF);
    
  6. 此步骤将写入和读取数据。无论如何,这个芯片在那里有一些棘手的逻辑,它比看起来更简单。实际上它的工作原理就像输出一样简单。外部输入只触发PCF8574引脚,仅此而已,输入模式无特殊配置。对于确保使用PCF8574 INT引脚的输入监视器,PCF8574将触发INT引脚。

    例如:

    如果您需要输入引脚,只需将引脚设置为逻辑0即可。并监视INT引脚,如果输入发生变化,INT引脚将被触发,您应该通过I2C读取数据。

    对于OUTPUT low,只需写入零。

    对于OUTPUT高设置逻辑是真的。

    您正在使用HAL,因此您必须阅读 HAL_I2C_Master_Transmit 功能中发生的事情。不要忘记地址是7位,地址的第一个字节也包括R / W条件。第一个字节bit0是R / W位。所以你应该处理它。

    例如,使用define:

    #define PCF8574_WRITE_ADRESS  (0x40) /*for writing to chip*/
    #define PCF8574_READ_ADRESS  ((0x40)|0x01) /*for reading chip*/
    

    以下是一些链接: i2c explanations

    this may help

    Really nice guide!

    希望这有助于理解您的问题并解决它。:)

答案 1 :(得分:0)

谢谢,Bulkin

我发现了明显的错误。 HAL库不是i2c_address&lt;&lt; 1。 我/你必须在代码中加入相同的结果!

HAL_I2C_Master_Transmit(&hi2c3, (0x3f<<1), data_io, 1, 100);

$define i2c_address_write (0x3f <<1 )
HAL_I2C_Master_Transmit(&hi2c3, i2c_address_write , data_io, 1, 100);

阅读:

$define i2c_address_read ((0x3f <<1) | 0x01)
HAL_I2C_Master_Transmit(&hi2c3, i2c_address_read , data_io, 1, 100);