Перейти к содержанию

STM32 для чайника


ART_ME

Рекомендуемые сообщения

Мда, хрень какая-то... На отладочной плате пробуешь, или что то другое? Странно конечно, I2C он же со своим стробом, даже если бы тактовая частота была не стабильная, должно было бы работать. А всё остальное нормально работает? К примеру UART. Подключить его к пк и передать символов 200, посмотреть не будет ли ошибок. Но это всё так, предположения... Может какая нога питания или земли плохо пропаяна и при включении PLL чудеса начинаются. Если только I2C не работает, я бы попробовал рассмотреть пакеты осциллографом, может станет что то яснее...

Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

Закрутил скорость на максимум, до 36 МГц

На I2C1 посадил DS3231 - работает как часы:D MPU-6050 на I2C2 традиционно не работает.

Экспериментирую на PinBoard 2 от Di Halt'а.

Изменено пользователем Darth_Vader
Ссылка на комментарий
Поделиться на другие сайты

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Нужно наверное эратту смотреть. Там вроде что то было про работу I2C2 с SPI2 или UART3. Ща глянем

Самое главное не спросил) Как себя проявляет, неработающий I2C, он стаёт занят после первой передачи?

Ссылка на комментарий
Поделиться на другие сайты

Выбираем схему BMS для корректной работы литий-железофосфатных (LiFePO4) аккумуляторов

 Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ, также как и для других, очень важен контроль процесса заряда и разряда, а специализированных микросхем для этого вида аккумуляторов не так много. Инженеры КОМПЭЛ подготовили список имеющихся микросхем и возможных решений от разных производителей. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Первый же HAL_I2C_Master_Transmit возвращает HAL_BUSY.

Errata читал, косяк с I2C там есть.

И это тоже видел...

Просто не увидел там связи с частотой тактирования

 

Изменено пользователем Darth_Vader
Ссылка на комментарий
Поделиться на другие сайты

Ну да прямой связи с PLL вроде бы не наблюдается, попробуй сбросить как тут написано, если после этого заведётся значит проблема эта, нет значит другая:

void I2C_ClearBusyFlagErratum(struct I2C_Module* i2c)
{
  GPIO_InitTypeDef GPIO_InitStructure;

  // 1. Clear PE bit.
  i2c->instance.Instance->CR1 &= ~(0x0001);

  //  2. Configure the SCL and SDA I/Os as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
  GPIO_InitStructure.Mode         = GPIO_MODE_OUTPUT_OD;
  GPIO_InitStructure.Alternate    = I2C_PIN_MAP;
  GPIO_InitStructure.Pull         = GPIO_PULLUP;
  GPIO_InitStructure.Speed        = GPIO_SPEED_FREQ_HIGH;

  GPIO_InitStructure.Pin          = i2c->sclPin;
  HAL_GPIO_Init(i2c->sclPort, &GPIO_InitStructure);
  HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_SET);

  GPIO_InitStructure.Pin          = i2c->sdaPin;
  HAL_GPIO_Init(i2c->sdaPort, &GPIO_InitStructure);
  HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_SET);

  // 3. Check SCL and SDA High level in GPIOx_IDR.
  while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
  {
    asm("nop");
  }

  while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
  {
    asm("nop");
  }

  // 4. Configure the SDA I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
  HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_RESET);

  //  5. Check SDA Low level in GPIOx_IDR.
  while (GPIO_PIN_RESET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
  {
    asm("nop");
  }

  // 6. Configure the SCL I/O as General Purpose Output Open-Drain, Low level (Write 0 to GPIOx_ODR).
  HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_RESET);

  //  7. Check SCL Low level in GPIOx_IDR.
  while (GPIO_PIN_RESET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
  {
    asm("nop");
  }

  // 8. Configure the SCL I/O as General Purpose Output Open-Drain, High level (Write 1 to GPIOx_ODR).
  HAL_GPIO_WritePin(i2c->sclPort, i2c->sclPin, GPIO_PIN_SET);

  // 9. Check SCL High level in GPIOx_IDR.
  while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sclPort, i2c->sclPin))
  {
    asm("nop");
  }

  // 10. Configure the SDA I/O as General Purpose Output Open-Drain , High level (Write 1 to GPIOx_ODR).
  HAL_GPIO_WritePin(i2c->sdaPort, i2c->sdaPin, GPIO_PIN_SET);

  // 11. Check SDA High level in GPIOx_IDR.
  while (GPIO_PIN_SET != HAL_GPIO_ReadPin(i2c->sdaPort, i2c->sdaPin))
  {
    asm("nop");
  }

  // 12. Configure the SCL and SDA I/Os as Alternate function Open-Drain.
  GPIO_InitStructure.Mode         = GPIO_MODE_AF_OD;
  GPIO_InitStructure.Alternate    = I2C_PIN_MAP;

  GPIO_InitStructure.Pin          = i2c->sclPin;
  HAL_GPIO_Init(i2c->sclPort, &GPIO_InitStructure);

  GPIO_InitStructure.Pin          = i2c->sdaPin;
  HAL_GPIO_Init(i2c->sdaPort, &GPIO_InitStructure);

  // 13. Set SWRST bit in I2Cx_CR1 register.
  i2c->instance.Instance->CR1 |= 0x8000;

  asm("nop");

  // 14. Clear SWRST bit in I2Cx_CR1 register.
  i2c->instance.Instance->CR1 &= ~0x8000;

  asm("nop");

  // 15. Enable the I2C peripheral by setting the PE bit in I2Cx_CR1 register
  i2c->instance.Instance->CR1 |= 0x0001;

  // Call initialization function.
  HAL_I2C_Init(&(i2c->instance));
}

 

Ссылка на комментарий
Поделиться на другие сайты

Коллеги, прошу помощи в передаче по SPI! Вывожу картинку на дисплей ILI9341 из массива.  Если передавать даные по одному байту,  все прекрасно отображается, но работает медленно.

for(i=0; i<words; i++)      //Цикл по массиву изображения uint16_t img[]
        {     
        color_h8=img[i]>>8;     //Старший байт цвета
        color_l8=img[i]&0xFF;   //Младший байт цвета      
        HAL_SPI_Transmit_IT(&hspi1, &color_h8, 1); //Передача старшего байта цвета
        HAL_SPI_Transmit_IT(&hspi1, &color_l8, 1); //Передача младшего байта цвета
        }

Если передаю все сразу,  дисплей получает данные цвета с поменяными местами младшим и старшим байтами.  

HAL_SPI_Transmit_IT(&hspi1, (uint8_t *)img,  words*2); //Передача всего массива uint16_t img[]
while( hspi1.State != HAL_SPI_STATE_READY) {}

Причем если массив img описан не как uint16_t, а как uint8_t,  вторая команда тоже работает корректно.  Не пойму, какая разница, ведь физически img - просто адрес начала массива? Или тут какие-то тонкости в организации распределения данных по памяти у транслятора, в зависимости от описания типа?

Ссылка на комментарий
Поделиться на другие сайты

6 часов назад, GOR23 сказал:

Ну да прямой связи с PLL вроде бы не наблюдается, попробуй сбросить как тут написано, если после этого заведётся значит проблема эта, нет значит другая:

Немножко другая проблема, не с PLL.

Скажем так:

Цитата

При работе с некоторыми устройствами I2C (например, MPU-6050, RDA5807M) получаю HAL_BUSY при тактировании интерфейса частотой выше 8 Мгц, а некоторые (например, DS3231, DS1307) продолжают прекрасно работать и при тактировании аж до 36 Мгц.

 

4 часа назад, Signus сказал:

Или тут какие-то тонкости в организации распределения данных по памяти у транслятора, в зависимости от описания типа?

Получается, что у знаковых и беззнаковых типов старший и младший байты хранятся в разной последовательности. Странно как-то.

Изменено пользователем Darth_Vader
Ссылка на комментарий
Поделиться на другие сайты

9 часов назад, GOR23 сказал:

попробуй сбросить как тут написано

Для STM32F103 строчка ниже выдаёт ошибку.

  GPIO_InitStructure.Alternate    = I2C_PIN_MAP;

Я её закомментировал (без понимания последствий, если честно).

При получении HAL_BUSY вызываю ClearBusyFlagErratum - ничего не изменилось. Следующий вызов HAL_I2C_Master_Transmit опять возвращает HAL_BUSY.

Сегодня продолжу ковырять.

Ссылка на комментарий
Поделиться на другие сайты

Коллеги кто нибудь использовал SIM800L в своих проектах на HAL? Не покажите как смс отправить? На ардуино без проблем отправлял тут не уходят и все.

Ссылка на комментарий
Поделиться на другие сайты

Подскажите, пжл, по типам данных в CooCox: u8 - uint8_t, u16 - uint16_t и т.д. Какой смысл в этих "магических" объявлениях? Как объявляется float или  double, например?

Ссылка на комментарий
Поделиться на другие сайты

bool Send_SMS(uint64_t tel, char * message) {

	char tel[10];
	memset(tel, 0, sizeof(tel));
	sprintf(tel, "%lld", tel1);
	memset(str_rx3, 0, sizeof(str_rx3));
	memset(str_tx3, 0, sizeof(str_tx3));
	sprintf(str_tx3, "AT+CMGF=1\r");
	HAL_UART_Transmit( & huart3, (uint8_t * )str_tx3, strlen(str_tx3), 100);
	memset(str_tx3, 0, sizeof(str_tx3));

	sprintf(str_tx3, "AT+CMGS=\"%s\"\r", tel);
	HAL_UART_Transmit(&huart3, (uint8_t * )str_tx3, strlen(str_tx3), 100);
	memset(str_tx3, 0, sizeof(str_tx3));

	sprintf(str_tx3, ">%s\r", message);
	HAL_UART_Transmit(&huart3, (uint8_t * )str_tx3, strlen(str_tx3), 5000);
	memset(str_tx3, 0, sizeof(str_tx3));

	HAL_UART_Transmit(&huart3, (uint8_t * )0x1A, 1, 500);
	HAL_UART_Receive(&huart3, (uint8_t * )str_rx3, sizeof(str_rx3), 1000);
	printf("GSM - %s", str_rx3);

}

 

Ссылка на комментарий
Поделиться на другие сайты

Я говорю, что после

12 минуты назад, MihaNN52 сказал:

AT+CMGS="89200019555"

необходимо дождаться от SIM800 приглашения для ввода sms в виде знака ">"

Изменено пользователем Darth_Vader
Ссылка на комментарий
Поделиться на другие сайты

15 hours ago, Signus said:

Не пойму, какая разница, ведь физически img - просто адрес начала массива?

проблема в том, что при передаче байта по указателю сначала передается младший полубайт, а потом уже старший. А в ручную у вас наоборот.

Можно сделать финт ушами и поправить библиотечную функцию "под себя". Так как у вас в проекте будет копия библиотеки, то ничего страшного не случится. Либо второй вариант - изменить формат битмап массива. Многие проги форматтеры позволяют это сделать

И вобще, лучше пользоваться DMA при работе с дисплеем. Скорость вырастет еще на порядок

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

1 час назад, mail_robot сказал:

Скорость вырастет еще на порядок

А, вот, интересно, почему вырастет? Неужели частота клоков SPI увеличится?

Ссылка на комментарий
Поделиться на другие сайты

нет, скорость выдачи в шину возрастет

я с этим дисплеем уже много чего наработал, поэтому знаю о чем говорю. Там каждый сэкономленый такт процессора в кассу. А загрузить SPI на полную мощность даже STM-ке не так то просто на самом деле, если при этом не забывать еше про основной полезный код, который кто-то должен исполнять параллельно

этот дисплей спокойно преживает скорость в 12 мегагерц на шине, а скорость проца 103-го всего 72. То есть на каждые 96 тактов он должен выкинуть байт. Не густо с ресурсами однако получается, если прикидывать в среднем. Конечно если стоит задача только пульнуть картинку и потом минут 10 пырится в нее, то пофигу

Изменено пользователем mail_robot

Нужно делать то, что нужно. А то, что не нужно, делать не нужно. (С) Винни Пух

Ссылка на комментарий
Поделиться на другие сайты

Я продолжил ковыряться с чудесами шины I²C - взял плату STM32VLDISCOVERY с процессором STM32F100RBT6B.

Ситуация не идентичная, но, по-сути, такая же.

Если частота тактирования модуля I²C 8 МГц или 16 МГц - модуль MPU6050 работает (на HAL_I2C_Master_Transmit отвечает HAL_OK),  если сделать частоту 24 МГц - всё, HAL_BUSY.

Тескт программы:

Скрытый текст

#include "main.h"
#include "stm32f1xx_hal.h"

#define MPU6050_ADDR	(0x68<<1)

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);

int main(void)
{
	HAL_Init();
	SystemClock_Config();
	MX_GPIO_Init();
	MX_I2C1_Init();
  
	HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
	HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_RESET);
	HAL_StatusTypeDef result;
	result = HAL_I2C_Master_Transmit(&hi2c1, MPU6050_ADDR, (uint8_t *) 0x75, 1, 1000);
	switch(result){
		case HAL_OK:
			HAL_GPIO_WritePin(LD3_GPIO_Port, LD3_Pin, GPIO_PIN_SET);
			break;
		case HAL_BUSY:
			HAL_GPIO_WritePin(LD4_GPIO_Port, LD4_Pin, GPIO_PIN_SET);
			break;
	}

  while (1)
  {
  }
}

void SystemClock_Config(void)
{

  RCC_OscInitTypeDef RCC_OscInitStruct;
  RCC_ClkInitTypeDef RCC_ClkInitStruct;

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Initializes the CPU, AHB and APB busses clocks 
    */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure the Systick interrupt time 
    */
  HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);

    /**Configure the Systick 
    */
  HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);

  /* SysTick_IRQn interrupt configuration */
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

/* I2C1 init function */
static void MX_I2C1_Init(void)
{

  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 100000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/** Configure pins as 
        * Analog 
        * Input 
        * Output
        * EVENT_OUT
        * EXTI
*/
static void MX_GPIO_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct;

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOC_CLK_ENABLE();
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOC, LD4_Pin|LD3_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pins : LD4_Pin LD3_Pin */
  GPIO_InitStruct.Pin = LD4_Pin|LD3_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

}

void _Error_Handler(char * file, int line)
{
  while(1) 
  {
  }
}

#ifdef USE_FULL_ASSERT

  void assert_failed(uint8_t* file, uint32_t line)
{
}

#endif

 

Что это за фокусы с I²C, куда копать?

UPD: Установил, что MPU6050 отваливается в вечный HAL_BUSY при HCLK=24 МГц и пофиг какая частота приходит APB1 (I2C1 от APB1 же тактируется?)

 

Изменено пользователем Darth_Vader
Ссылка на комментарий
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу

×
×
  • Создать...