2017-11-18 20 views
1

私はstm32f4-discoveryキットを持っており、hd44870 LCD用のI/Oエクスパンダを試してみたいと思います。私はPCF8574AT link to io example like mine hi2c3ハードウェア上でi2cアドレスが0x3f(i2cスキャナでチェックされている)である8ビットエクスパンダを持っています。 c/C++では、Eclipse環境でHALライブラリを使用します。コードを見てみましょう。stm32f4xx HAL lib&PCF8457AT - 書き込みする応答がありません

まず私は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エキスパンダにデータを送信してみてください。しかし、その前に私は/ 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のエクスパンダが壊れていますか?

+0

あなたはどのようなスキャナーを使用しましたか? Arduinoベース? – Bulkin

+0

Arduinoを使用してI2Cをスキャンすると、それが正しくありません。 I2CアドレスはHIGH 7ビットで、READ/WRITEフラグは1ビットです。 Arduino libはアドレス自体をシフトし、フラグビットも入れます。しかし、STM32では、手動で行う必要があります。 I2Cに書き込む場合、アドレスは '0x3F << 1 |でなければなりません。 0x01 = 7F' – Bulkin

答えて

0

ありがとう、Bulkin

明らかな間違いがありました。 HALライブラリはi2c_addressではありません< < 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); 
0

実際にはHALドライバについてはわかりませんが、実際にHALは使用されませんでした。しかし、私はpcf8574 IOエクスパンダに触れました。 あなたが言ったように、あなたはスキャナーでそれをチェックしており、アドレスを取得すれば、ラインとデバイスはOKです。私はI2CとHALライブラリの専門家ではないため、STM32標準周辺ドライバに依存するI2Cドライバを示し、PCF8574やさまざまなI2Cデバイスで動作します。スニペット(ブロッキングモード、irqベースではありません)の例があります:

  1. IOがビジーでないかどうかを確認してください。

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

    }

  2. 開始条件と(書き込みモードのためのアドレスを持つ)を設定書き込み条件を生成します。

    I2C_SendData(&I2Cx, reg_addr); 
    while(I2C_GetFlagStatus(&I2Cx, I2C_ISR_TC) == RESET){ 
        if((timeout--) == 0) return -EIO; 
    } 
    
  3. 条件を読んで生成してPCF8574から読み取るより:今

    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; 
    } 
    
  4. あなたがデータバイトを送信することができますが、この関数は、登録I2C TX(トランシーバー)に直接書き込む(それはあなたのIO状態です) 、データは書き込まれたものと同じでなければなりません(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); 
    

この手順では、データを読み書きします。とにかく、このチップはそこにいくつかのトリッキーなロジックを持っています、それはそれが単純なOUTPUTと同様に動作しますlike.Actuallyよりも単純です。外部入力はPCF8574ピンを起動するだけで、入力モードの特別な設定はありません。 PCF8574 INTピンを使用する入力モニタでは、PCF8574はINTピンをトリガします。例えば

あなたが入力ピンにしたい場合は、単に論理0にピンを設定するよりも。 INTピンをモニタし、入力に変化が生じた場合、INTピンがトリガされ、I2Cを介してデータを読み取る必要があります。

OUTPUTがローの場合はゼロを書き込みます。

OUTPUTハイセットロジックの場合はtrueです。

HALを使用しているため、内部で何が起こるかを読み取る必要があります。HAL_I2C_Master_Transmit機能。アドレスは7ビットであり、アドレスの最初のバイトもR/W条件を含むことを忘れないでください。最初のバイトのbit0はR/Wビットです。だからあなたはそれを処理すべきです。

は定義して、たとえば:

ここ
#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!

希望: )

関連する問題