การระบุแอดเดรสรีจิสเตอร์ด้วยไลบรารี I2C STM32F0 HAL


12

ฉันใหม่มากที่ใช้ห้องสมุด CUBE และ HAL_l ฉันกำลังใช้ไมโครคอนโทรลเลอร์ STM32F0 กับ 32 พิน แผนผังสำหรับ I2C นั้นถูกต้อง ดังนั้นฉันต้องการความช่วยเหลือเล็กน้อยที่นี่

ฉันมีเซ็นเซอร์ capacitive ( FDC1004 ) ที่ใช้การสื่อสาร I2C ฉันต้องเขียนรีจิสเตอร์เหล่านี้เพื่ออ่านข้อมูล

ฉันจะส่งต้นแบบแบบฟอร์มคำขอเริ่มไปยังทาสอย่างถูกต้องได้อย่างไร (ที่อยู่สลาฟคือ A0)

วิธีการตั้งค่าพอยน์เตอร์เป็น 0x0C register?

  • แผ่นข้อมูลเห็น (ลงทะเบียน 0x0C: บิต [7: 4]) ถึง 1) ฉันไม่รู้วิธีการทำเช่นนั้น? และในที่สุดวิธีการอ่านจากการลงทะเบียนเดียวกัน?
  • นอกจากนี้ฉันต้องรอฟิลด์ DONE_x (ลงทะเบียน 0x0C: บิต [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
Voltage Spike

ถ้าอย่างนั้นจะเป็นการดีกว่าถ้าคุณเขียนคำถามใหม่หรือแก้ไขคำถามนี้?
yest111

ดีกว่าที่จะแก้ไขคำถามน้อยลงและเราจะไม่ต้องปิดคำถามนี้
Spike แรงดัน

คำตอบ:


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. ปัญหาเล็กน้อยกับพารามิเตอร์ที่2ที่อยู่อุปกรณ์ทาส ที่อยู่อุปกรณ์ทาสคือb1010000ถ้าเราทำจนเสร็จในรูปแบบ 8 บิตมันจะเป็น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. 3พารามิเตอร์ ( uint8_t *pData) เป็นตัวชี้ไปยังบัฟเฟอร์ซึ่งมีข้อมูลที่จะส่ง ตอนนี้ในการโทรของคุณพารามิเตอร์ที่ 30x0Cคือข้อมูลจริงของคุณที่อยู่การลงทะเบียน ปัญหาคือมันจะถูกตีความว่าเป็นตัวชี้ (โดยHAL_I2C_Master_Transmit()) ไปยังตำแหน่งหน่วยความจำซึ่งข้อมูลบางอย่างที่ไม่ได้กำหนดสามารถพบได้

  3. 4พารามิเตอร์คือขนาดของบัฟเฟอร์จำนวนไบต์ที่จะส่ง หากคุณต้องการส่งไบต์เดียวพารามิเตอร์นี้ควรเป็น1และไม่ใช่ 10

I2C

เขียนทะเบียน

นี่คือแผนภาพที่เกี่ยวข้องจากแผ่นข้อมูล

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นหลังจากที่ส่งที่อยู่ทาสให้กับรถบัสที่สามไบต์มากขึ้นควรจะส่ง: ตัวชี้ลงทะเบียน , MSB ไบต์ , LSB ไบต์ การใช้งานทั่วไปด้วยการลงทะเบียน HAL แบบ 16 บิต:

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ในรหัสของคุณและฉันไม่ทราบว่าจุดประสงค์ของคุณคืออะไร แต่มันจะถูกตีความว่าเป็นตัวชี้ (น่าเสียดายที่ตำแหน่งหน่วยความจำแบบสุ่ม)

อ่านการลงทะเบียน

ป้อนคำอธิบายรูปภาพที่นี่

I2CI2C

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

นอกจากนี้ยังมีฟังก์ชั่น register register ที่กำหนดไว้เช่นกันซึ่งมี

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.