I2C STM32F0 HAL 라이브러리를 사용한 레지스터 주소 지정


12

저는 STM의 CUBE 및 HAL_libraries를 처음 사용합니다. 32 핀 STM32F0 마이크로 컨트롤러를 사용하고 있습니다. I2C의 회로도가 정확합니다. 여기에 약간의 도움이 필요합니다.

I2C 통신을 사용 하는 용량 성 센서 ( FDC1004 )가 있습니다. 데이터를 읽으려면이 레지스터를 작성해야합니다.

START 요청 양식 마스터를 슬레이브에 올바르게 보낼 수있는 방법 (슬레이브 주소는 A0)?

0x0C 레지스터에 포인터를 설정하는 방법은 무엇입니까?

  • 데이터 시트 (Register 0x0C : bit [7 : 4])를 1로 참조하십시오.) 모르겠습니다. 어떻게해야합니까? 마지막으로 동일한 레지스터에서 읽는 방법은 무엇입니까?
  • 또한 DONE_x 필드 (등록 0x0C : bits [3 : 0])를 읽기 전에 기다려야합니까?

그러나 올바른 레지스터를 처리하고 있는지 모르겠습니다! 센서에서 데이터를 다시 얻지 못하기 때문에!

내 코드는 다음과 같습니다.

int I2Ccomm ()
{

    HAL_I2C_Master_Transmit(&hi2c1,0xA1,0x0C, 10, 100); //start bit and pointer to register
    HAL_Delay(50);
    HAL_I2C_Master_Transmit(&hi2c1,0xA1,0x054, 10, 100); // setting the register
    HAL_Delay(50);

    HAL_I2C_Master_Receive(&hi2c1, 0xA0, 0x0C, 10, 100); //read from this register
    HAL_Delay(50);
    HAL_I2C_Master_Receive(&hi2c1, 0xA0, 0x02, 10, 100); //read data from register

    return ReadREG[1];
}

보다 구체적인 질문을하십시오. X 레지스터를 어떻게 올바르게 처리합니까? 이것은 잘못 표현 된 질문입니다. 자세한 지침은 electronics.stackexchange.com/help/how-to-ask
전압 스파이크를

그렇다면 새로운 질문을 작성하거나이 질문을 편집하는 것이 더 낫습니까?
yest111

더 나은 편집, 더 적은 질문 및 우리는 이것을 닫을 필요가 없습니다.
전압 스파이크

답변:


16

HAL_I2C_Master_Transmit()기능 부터 시작하겠습니다 . 선언을 확인하면 :

 HAL_StatusTypeDef HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);
  1. 슬레이브 장치 주소 인 두 번째 매개 변수에 사소한 문제가 있습니다. 슬레이브 장치 주소는 b10100008 비트 형식으로 완성 0xA0하면 말한 것처럼입니다. 이제 이것을 전달할 때 HAL_I2C_Master_Transmit()R / W 비트를 수동으로 설정할 필요가 없습니다. HAL이 대신 해줍니다. 따라서 HAL_I2C_Master_Transmit()전송 된 R / W 비트 를 호출 하면 쓰기 작업을 나타내는 자동으로 0이HAL_I2C_Master_Receive() 되고, 전송 된 R / W 비트 를 호출 하면 쓰기 작업을 나타내는 자동으로 1 이됩니다 . R / W 값을 혼합했지만 함수에 신경 쓰지 않는 비트라고 생각하므로 코드의 실제 오류는 아닙니다.

  2. 번째 매개 변수 ( uint8_t *pData)는 전송할 데이터가 들어 있는 버퍼에 대한 포인터 입니다. 이제 호출에서 3 번째 매개 변수는 실제 데이터 인 레지스터 주소입니다. 문제는 정의되지 않은 데이터를 찾을 수있는 메모리 위치에 대한 포인터로 해석 된다는 것입니다.0x0CHAL_I2C_Master_Transmit()

  3. 넷째 매개 변수 인 버퍼의 크기 (바이트 단위)의 개수가 전송된다. 단일 바이트 를 보내려면 이 매개 변수는 10이 아닌 1 이어야합니다 .

나는2

레지스터 쓰기

데이터 시트의 해당 다이어그램은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

따라서 슬레이브 주소를 버스로 보낸 후 register pointer , MSB byte , LSB byte 등 3 바이트를 더 전송해야합니다 . 16 비트 레지스터를 작성하는 HAL을 사용한 일반적인 구현 :

void write_register(uint8_t register_pointer, uint16_t register_value)
{
    uint8_t data[3];

    data[0] = register_pointer;     // 0x0C in your example
    data[1] = register_value>>8;    // MSB byte of 16bit data
    data[2] = register_value;       // LSB byte of 16bit data

    HAL_I2C_Master_Transmit(&hi2c1, 0xA0, data, 3, 100);  // data is the start pointer of our array
}

당신의 가치를 가진 예 : write_register(0x0C, 0x0054);

또는 레지스터 주소 및 주소 크기를 전달하기위한 추가 매개 변수가있는 HAL 정의 레지스터 쓰기 기능도 사용할 수 있습니다.

void write_register(uint8_t register_pointer, uint16_t register_value)
{
    HAL_StatusTypeDef status = HAL_OK;

    status = HAL_I2C_Mem_Write(&hi2c1, 0xA0, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, (uint8_t*)(&register_value), 2, 100); 

    /* Check the communication status */
    if(status != HAL_OK)
    {
        // Error handling, for example re-initialization of the I2C peripheral
    }
}

이제 HAL_I2C_Master_Receive()기능은 다른 것과 거의 동일합니다.

HAL_StatusTypeDef HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);

차이점은 3 번째 파라미터는 수신 된 데이터 가 저장 될 버퍼에 대한 포인터라는 것입니다. 그것은 0x02당신의 코드에 있으며 당신의 목적이 무엇인지 알지 못하지만 (불행히도 임의의 메모리 위치에 대한) 포인터로 해석됩니다.

레지스터 읽기

여기에 이미지 설명을 입력하십시오

나는2나는2

void read_register(uint8_t register_pointer, uint8_t* receive_buffer)
{
    // first set the register pointer to the register wanted to be read
    HAL_I2C_Master_Transmit(&hi2c1, 0xA0, &register_pointer, 1, 100);  // note the & operator which gives us the address of the register_pointer variable

    // receive the 2 x 8bit data into the receive buffer
    HAL_I2C_Master_Receive(&hi2c1, 0xA0, receive_buffer, 2, 100);   
}

예:

uint8_t reg_ptr = 0x0C;
uint8_t buffer[2];

read_register(reg_ptr, buffer);

// the register content available in the buffer

HAL 정의 레지스터 읽기 기능도 있습니다.

uint16_t read_register(uint8_t register_pointer)
{
    HAL_StatusTypeDef status = HAL_OK;
    uint16_t return_value = 0;

    status = HAL_I2C_Mem_Read(&hi2c1, 0xA0, (uint16_t)register_pointer, I2C_MEMADD_SIZE_8BIT, &return_value, 2, 100);

    /* Check the communication status */
    if(status != HAL_OK)
    {

    }

    return return_value;
}

을 통해 읽기 8.5 프로그래밍 의 섹션 데이터 시트 자세한 내용은.


귀하의 답변에 감사드립니다. 이제 효과가 있습니다. 그러나 하나 더 질문? 독서를 위해 몇 군데의 비밀을 기다려야합니까, 아니면 지체없이 읽을 수 있습니까?
yest111

나는 지연이 필요하다고 생각하지 않으며, 먼저 시도하지 않아도됩니다.
Bence Kaulics

1
기다릴 필요가 없습니다. I2C는 슬레이브가 완료 될 때까지 클럭 신호를 반복합니다.
Mahmoud Al-Qudsi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.