2017-11-18 1 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 - 쓰기 위해 응답 없음

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 확장기에 데이터를 보내려고 : SCL에 데이터 시트는 100kHz 같은 -

먼저 나는 i2c3를 초기화합니다. 그러나 그 전에 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 확장기가 고장 났습니까?

+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. I/YOU는 코드에 같은 결과가 아니어야합니다!

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 드라이버에 대한 확실하지 않은 Im은 실제로 HAL을 사용하지 않았습니다. 하지만 나는 pcf8574 입출력 확장기를 만졌다. 당신이 말했듯이, 당신은 스캐너로 그것을 확인하고 주소를 얻으면, 라인과 장치는 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처럼 작동합니다. 외부 입력은 PCF8574 핀을 트리거링하며 아무것도 입력 모드에 대한 특수 구성이 없습니다. PCF8574 INT 핀을 사용하는 입력 모니터의 경우, PCF8574는 INT 핀을 트리거합니다. 예를 들어

:

당신이 입력 핀을 원하는 경우에, 단순히 논리 0으로 핀을 설정보다. INT 핀을 모니터하고, 입력이 변경되면 INT 핀이 트리거되고 I2C를 통해 데이터를 읽어야합니다.

OUTPUT 로우의 경우 0을 씁니다.

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!

희망 :)