программа зависает при вызове функции записи I2C - PullRequest
0 голосов
/ 28 апреля 2019

Плата: STM32F4 Discovery

У меня проблемы с инициализацией I2C, я думаю!Когда программа достигает функции I2C_write, она зависает!Я пытаюсь связаться с датчиком температуры и шума HDC1080 от TI.С оборудованием все в порядке, я тестировал его с библиотеками cubeMX и HAL, и он работает нормально!

У меня есть логический анализатор saleae, подключенный к PB8 (SCL) и PB9 (SDA), нет активности!

Я удалил часть init_usart, думая, что, возможно, они мешают, потому что они разделяюттот же порт (GPIOB).

void init_usart(void)
{
  //enable AHB1 peripheral clock
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);
  //Init GPIOB
  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_6 | GPIO_Pin_7;
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_USART1);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_USART1);

  //Enable USART peripheral clock
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
  //Init usart
  USART_InitTypeDef USART_InitStruct;
  USART_InitStruct.USART_BaudRate = 57600;
  USART_InitStruct.USART_WordLength = USART_WordLength_8b;
  USART_InitStruct.USART_StopBits = USART_StopBits_1;
  USART_InitStruct.USART_Parity = USART_Parity_No ;
  USART_InitStruct.USART_Mode = USART_Mode_Tx;
  USART_InitStruct.USART_HardwareFlowControl = 
  USART_HardwareFlowControl_None;
  USART_Init(USART1, &USART_InitStruct);
  USART_Cmd(USART1, ENABLE);
}
void InitializeI2C()
{
  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOB, ENABLE);

  GPIO_InitTypeDef GPIO_InitStruct;
  GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_8 | GPIO_Pin_9; // 8=SCL 9=SDA
  GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
  GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
  GPIO_InitStruct.GPIO_OType = GPIO_OType_OD;
  GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;
  GPIO_Init(GPIOB, &GPIO_InitStruct);

  GPIO_PinAFConfig(GPIOB, GPIO_PinSource8, GPIO_AF_I2C1);
  GPIO_PinAFConfig(GPIOB, GPIO_PinSource9, GPIO_AF_I2C1);

  /* enable APB1 peripheral clock for I2C1*/
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1 , ENABLE);

  I2C_InitTypeDef I2C_InitStruct;
  I2C_InitStruct.I2C_ClockSpeed = 100000;
  I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
  I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
  I2C_InitStruct.I2C_OwnAddress1 = 0x01;
  I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
  I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
  I2C_Init(I2C1, &I2C_InitStruct);
  I2C_Cmd(I2C1, ENABLE);
}
void I2C_write( uint8_t HW_address, uint8_t addr, uint8_t data)
{
  I2C_GenerateSTART(I2C1, ENABLE);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
  I2C_Send7bitAddress(I2C1, HW_address, I2C_Direction_Transmitter);
  while (!I2C_CheckEvent(I2C1, 
  I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));
  I2C_SendData(I2C1, addr);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  I2C_SendData(I2C1, data);
  while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
  I2C_GenerateSTOP(I2C1, ENABLE);
  while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY));
}
int main(void)
{
  init_usart()
  InitializeI2C();

  while (1)
  {
    delay_div(50);
    I2C_write( 0x40 << 1 , 0x01, 0x00);  //here it stops!!!
  }

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

Одна возможная проблема: вы используете неинициализированные данные.

Из вашего кода:

I2C_InitTypeDef I2C_InitStruct;
I2C_InitStruct.I2C_ClockSpeed = 100000;
//I2C_InitStruct.I2C_Mode = I2C_Mode_I2C;
I2C_InitStruct.I2C_DutyCycle = I2C_DutyCycle_2;
I2C_InitStruct.I2C_OwnAddress1 = 0x01;
I2C_InitStruct.I2C_Ack = I2C_Ack_Enable;
I2C_InitStruct.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
I2C_Init(I2C1, &I2C_InitStruct);

По крайней мере, I2C_Mode здесь не инициализируется, и вы не можете принять значение равным0. Это будет просто то, что находится в стеке в то время.

Вы либо захотите установить для структуры значение 0, либо неявно инициализировать другие члены равными нулю при объявлении:

I2C_InitTypeDef I2C_InitStruct = {
    .I2C_ClockSpeed = 100000,
    //.I2C_Mode = I2C_Mode_I2C,
    .I2C_DutyCycle = I2C_DutyCycle_2,
    .I2C_OwnAddress1 = 0x01,
    .I2C_Ack = I2C_Ack_Enable,
    .I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit,
};
I2C_Init(I2C1, &I2C_InitStruct);
0 голосов
/ 29 апреля 2019

Мой датчик температуры и шума мертв! I2C init отлично , попробовал его с дисплеем i2c oled, и я могу видеть активность на шине!

Просто короткое и окончательное обновление !!! Потерпи меня, пожалуйста!

Мой датчик температуры и шума (HDC1080) был в порядке! Потратив 40 минут пайки проводов на новый датчик (контакты 0,4 мм), я обнаружил, что это тоже не работает. С точки зрения аппаратного обеспечения ничего не изменилось из моего успешного первоначального теста, который я проводил с использованием библиотеки HAL, макета с 2 x 10k (вот что у меня было) подтягивающих резисторов, источника питания 3 В от платы обнаружения stm32. Похоже, что по неизвестным причинам тест HAL работал с этими двумя подтягиваниями по 10 тыс., А библиотека SP - нет. Так как мой дисплей SSD1306 oled поставляется на печатной плате с уже установленными резисторами 4.7k, я смог обнаружить, что могу общаться как с датчиком температуры и шума, так и с дисплеем. Окончательный вывод, подтягивающие резисторы были моей проблемой в конце концов!

...