Возникли проблемы с кодом I2 C для модуля датчика температуры и влажности SI7021 с использованием STM32F407 u C и кодовых блоков в качестве IDE - PullRequest
0 голосов
/ 05 января 2020

Недавно я приобрел у Adafruit плату для датчика температуры и влажности SI7021. Он использует протокол I2 C, и я относительно новичок в I2 C, я имею в виду, я знаю, как он работает теоретически, но я никогда не писал никакого кода для него. Я использую микроконтроллер STM32F407 от STM и CodeBlocks в качестве моей платформы программирования. Я нашел несколько примеров программ, но все они были для Кейла (я думаю, что это называется) и использовали функции HAL, которые я не могу использовать, и большинство из них смутило меня. Дело в том, что я сделал эту программу, используя пример программы из моего сценария, который я получил в школе, и я также снимал части из видео на YouTube, используя функции HAL. Итак, я в основном взял 2 разные программы и смешал их в одну.

Вот таблица данных датчика, который я использую: https://www.silabs.com/documents/public/data-sheets/Si7021-A20.pdf На странице 20 в таблице данных вы можете увидеть две разные способы связи с датчиком, я решил попробовать тот, который называется: «Hold Master Mode».

Видео YouTube, о котором я упоминал выше: https://www.youtube.com/watch?v=3JrLBHetzn8

#include "SmartcontrolOS.h"
#include "CMSIS.h"
#define DAC_DHR12R1_ADDRESS    0x40007408
#define CODEC_FLAG_TIMEOUT             ((uint32_t)0x2000)
#define CODEC_LONG_TIMEOUT             ((uint32_t)(300 * CODEC_FLAG_TIMEOUT))

__IO uint32_t  CODECTimeout = CODEC_LONG_TIMEOUT;

uint32_t Codec_TIMEOUT_UserCallback(char* caller){
  while (1) { /* Block communication and all processes */

  }
}

ui32 loop_while_stop_flag_is_set(){
    CODECTimeout = CODEC_FLAG_TIMEOUT;
    while(I2C1->CR1 & I2C_CR1_STOP) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f8");}
    return 0;
}

ui32 loop_till_event(uint32_t flag){
    CODECTimeout = CODEC_FLAG_TIMEOUT;
    while (!I2C_CheckEvent(I2C1, flag)){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f2");}
    return 0;
}

ui32 loop_while_flag_is(uint32_t flag, Bool level){
    CODECTimeout = CODEC_LONG_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, flag)==level){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f1");}
    return 0;
}

void Auswertung(){

 RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); /* Enable the I2C1 peripheral clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  GPIO_InitTypeDef
  GPIO_InitStructure            = {0};
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6 | GPIO_Pin_9;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); /* I2C SCL pin Configuration */
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); /* I2C SDA pin Configuration */

  /* I2C1 peripheral configuration */
  I2C_DeInit(I2C1);

  I2C_InitTypeDef
  I2C_InitStructure                         = {0};
  I2C_InitStructure.I2C_Mode                = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle           = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_OwnAddress1         = 0x33;
  I2C_InitStructure.I2C_Ack                 = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed          = 100000;
  I2C_Init(I2C1, &I2C_InitStructure);

  I2C_Cmd(I2C1, ENABLE);              /* Enable the I2C peripheral */


int Sensor_Adresse = 0x40;
ui8 Data[2] = {0};
ui8 index = 0;
ui16 temp_code = 0;
ui16 humidity_code = 0;


//HUmidity
//Writing     Section
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1, ENABLE);

loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);

loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
I2C_SendData(I2C1,0xE5);


//Reading Section
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1,ENABLE);

loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);

loop_while_flag_is(I2C_FLAG_BTF,0);
I2C_GenerateSTART(I2C1,ENABLE);

loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Receiver);

loop_while_flag_is(I2C_FLAG_ADDR,0);

loop_while_flag_is(I2C_FLAG_RXNE,0);

Data[index++] = I2C_ReceiveData(I2C1);

index = 0;

humidity_code = ((Data[0] <<8) | Data[1]);


//Temperature
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1, ENABLE);

loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);

loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);
I2C_SendData(I2C1,0xE0);


//Reading Section
loop_while_flag_is(I2C_FLAG_BUSY,1);
I2C_GenerateSTART(I2C1,ENABLE);

loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Transmitter);

loop_while_flag_is(I2C_FLAG_BTF,0);
I2C_GenerateSTART(I2C1,ENABLE);

loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);
I2C_Send7bitAddress(I2C1,Sensor_Adresse,I2C_Direction_Receiver);

loop_while_flag_is(I2C_FLAG_ADDR,0);

loop_while_flag_is(I2C_FLAG_RXNE,0);

Data[index++] = I2C_ReceiveData(I2C1);

index = 0;

temp_code = ((Data[0] <<8) | Data[1]);

float Humidity = 0;
float Temperature = 0;

Humidity = ((125.0f * humidity_code) / 65536.0f) - 6.0f;
Temperature = ((175.72f * temp_code) / 65536.0f) - 46.85f;

LCD__write(_,"%15.2f\n%15.2f",wf(Temperature),wf(Humidity));
}


void CPE_App__Wetterstation_I2C_RH_T(){
  Resources__ExBoard_init(_,"");
  while(1){

Auswertung();
  }
}

Надеюсь, вы поможете мне лучше понять I2 C и программирование в целом, а также завершить эту программу. Хорошего дня.

Редактировать: После просмотра этого поста я понял, что не добавил вторую программу, о которой говорил, так что вот она. Это из моего сценария, который я получил из школы.

#include "SmartcontrolOS.h"
#include "CMSIS.h"

#define CODEC_FLAG_TIMEOUT             ((uint32_t)0x2000)
#define CODEC_LONG_TIMEOUT             ((uint32_t)(300 * CODEC_FLAG_TIMEOUT))
#define CODEC_ADDRESS                   0x94  /* b00100111 */
#define  CODEC_STANDARD                0x04

__IO uint32_t  CODECTimeout = CODEC_LONG_TIMEOUT;

uint32_t Codec_TIMEOUT_UserCallback(char* caller){
  while (1) { /* Block communication and all processes */
      LCD__write(_, caller);
  }
}

ui32 loop_while_stop_flag_is_set(){
    CODECTimeout = CODEC_FLAG_TIMEOUT;
    while(I2C1->CR1 & I2C_CR1_STOP) { if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f8");}
    return 0;
}

ui32 loop_till_event(uint32_t flag){
    CODECTimeout = CODEC_FLAG_TIMEOUT;
    while (!I2C_CheckEvent(I2C1, flag)){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f2");}
    return 0;
}

ui32 loop_while_flag_is(uint32_t flag, Bool level){
    CODECTimeout = CODEC_LONG_TIMEOUT;
    while(I2C_GetFlagStatus(I2C1, flag)==level){ if((CODECTimeout--) == 0) return Codec_TIMEOUT_UserCallback("f1");}
    return 0;
}

static uint32_t Codec_ReadRegister(uint8_t RegisterAddr){
  uint32_t result = 0;

  loop_while_flag_is(I2C_FLAG_BUSY,1);                                  /*!< While the bus is busy */
  I2C_GenerateSTART(I2C1, ENABLE);                                      /* Start the config sequence */

  loop_till_event(I2C_EVENT_MASTER_MODE_SELECT);                        /* Test on EV5 and clear it */
  I2C_Send7bitAddress(I2C1, CODEC_ADDRESS, I2C_Direction_Transmitter);  /* Transmit the slave address and enable writing operation */

  loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);          /* Test on EV6 and clear it */
  I2C_SendData(I2C1, RegisterAddr);                                     /* Transmit the register address to be read */

  loop_while_flag_is(I2C_FLAG_BTF, 0); /*!< Wait till all data have been physically transferred on the bus */
  I2C_GenerateSTART(I2C1, ENABLE);     /*!< Send START condition a second time */

  loop_till_event(I2C_EVENT_MASTER_MODE_SELECT); /*!< Test on EV5 and clear it (cleared by reading SR1 then writing to DR) */
  I2C_Send7bitAddress(I2C1, CODEC_ADDRESS, I2C_Direction_Receiver); /*!< Send Codec address for read */

  loop_while_flag_is(I2C_FLAG_ADDR,0);  /* Wait on ADDR flag to be set (ADDR is still not cleared at this level */
  I2C_AcknowledgeConfig(I2C1, DISABLE); /*!< Disable Acknowledgment */

  (void)I2C1->SR2; /* Clear ADDR register by reading SR1 then SR2 register (SR1 has already been read) */

  I2C_GenerateSTOP(I2C1, ENABLE);      /*!< Send STOP Condition */

  loop_while_flag_is(I2C_FLAG_RXNE,0); /* Wait for the byte to be received */
  result = I2C_ReceiveData(I2C1);      /*!< Read the byte received from the Codec */

  loop_while_stop_flag_is_set(); /* Wait to make sure that STOP flag has been cleared */
  I2C_AcknowledgeConfig(I2C1, ENABLE);   /*!< Re-Enable Acknowledgment to be ready for another reception */
  I2C_ClearFlag(I2C1, I2C_FLAG_AF); /* Clear AF flag for next communication */

  return result; /* Return the byte read from Codec */
}

static uint32_t Codec_WriteRegister(uint8_t RegisterAddr, uint8_t RegisterValue){
  uint32_t result = 0;

  loop_while_flag_is(I2C_FLAG_BUSY,1); /*!< While the bus is busy */
  I2C_GenerateSTART(I2C1, ENABLE);    /* Start the config sequence */

  loop_till_event(I2C_EVENT_MASTER_MODE_SELECT); /* Test on EV5 and clear it */
  I2C_Send7bitAddress(I2C1, CODEC_ADDRESS, I2C_Direction_Transmitter); /* Transmit the slave address and enable writing operation */

  loop_till_event(I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED); /* Test on EV6 and clear it */
  I2C_SendData(I2C1, RegisterAddr); /* Transmit the first address for write operation */

  loop_till_event(I2C_EVENT_MASTER_BYTE_TRANSMITTING); /* Test on EV8 and clear it */
  I2C_SendData(I2C1, RegisterValue);                   /* Prepare the register value to be sent */

  loop_while_flag_is(I2C_FLAG_BTF, 0); /*!< Wait till all data have been physically transferred on the bus */
  I2C_GenerateSTOP(I2C1, ENABLE); /* End the configuration sequence */

  result = (Codec_ReadRegister(RegisterAddr) == RegisterValue)? 0:1; /* Verify that the data has been correctly written */

  return result; /* Return the verifying value: 0 (Passed) or 1 (Failed) */
}

void micro_App__CMSIS_I2C(){
  Resources__ExBoard_init(_, "CMSIS-I2C");

  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); /* Enable the I2C1 peripheral clock */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

  GPIO_InitTypeDef
  GPIO_InitStructure            = {0};
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6 | GPIO_Pin_9;
  GPIO_Init(GPIOB, &GPIO_InitStructure);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1); /* I2C SCL pin Configuration */
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1); /* I2C SDA pin Configuration */

  /* I2C1 peripheral configuration */
  I2C_DeInit(I2C1);

  I2C_InitTypeDef
  I2C_InitStructure                         = {0};
  I2C_InitStructure.I2C_Mode                = I2C_Mode_I2C;
  I2C_InitStructure.I2C_DutyCycle           = I2C_DutyCycle_2;
  I2C_InitStructure.I2C_OwnAddress1         = 0x33;
  I2C_InitStructure.I2C_Ack                 = I2C_Ack_Enable;
  I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_InitStructure.I2C_ClockSpeed          = 100000;
  I2C_Init(I2C1, &I2C_InitStructure);

  I2C_Cmd(I2C1, ENABLE);              /* Enable the I2C peripheral */

  DO__write(PD4->owner, PD4, 0);
  volatile int i = 0; for(;i < 10000; i++);
  DO__write(PD4->owner, PD4, 1);

  Codec_WriteRegister(0x02, 0x01);           /* Keep Codec powered OFF */
  Codec_WriteRegister(0x04, 0xAF);           /* SPK always OFF & HP always ON */
  Codec_WriteRegister(0x05, 0x81);           /* Clock configuration: Auto detection */
  Codec_WriteRegister(0x06, CODEC_STANDARD); /* Set the Slave Mode and the audio Standard */

  while(1){}
}

...