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

STM32 для чайника


ART_ME

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

16 минут назад, Signus сказал:

изучил распределение памяти

Погуглите про little-endian и big-endian. Это два разных способа размещения байтов данных в памяти процессоров. В Вашем случае - это little-endian.

Вот картинка из Википедии.

big_little_endian.png

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

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

21 час назад, Koret сказал:

if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)

ADCValue[0] = HAL_ADC_GetValue(&hadc1); // Первый канал

if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)

ADCValue[1] = HAL_ADC_GetValue(&hadc1); // Второй канал

if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)

ADCValue[2] = HAL_ADC_GetValue(&hadc1);  // Третий канал

Решил попробовать ранее мной написанный код, перед тем как с DMA пробовать, и получилось, что значения заносятся в массив как попало. Есть ли возможность в режиме Polling проверять принадлежность к конкретному каналу?

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

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

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

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

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

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

21 hours ago, Koret said:

так нормально? 

я думаю так будет просто отлично. Если еще флаг-инициатор от таймера прикрутите к старту опроса, то вообще будет все автоматом, останется только забрать из массива результат

21 hours ago, Koret said:

Проверяет ли DMA перед занесением данных в массив соответствие

не проверяет. Он просто складывает значения в порядке выдачи их АЦП, а тот уже как раз выкладывает их в порядке установленном приоритетом группы каналов

 

21 hours ago, Koret said:

не получится так, что в ADC_Data[1] занесётся значение с 3-го канала, вместо второго?

у меня еще ни разу не получалось. Думаю и у вас не получится )

32 minutes ago, Koret said:

Есть ли возможность в режиме Polling проверять принадлежность к конкретному каналу?

как попало, потому что возможно у вас нарушен гдето порядок опроса поллингом. Вам перед каждым циклом поллинга надо делать перезапуск АЦП и тогда будет порядок. Ну и не мешало бы проверить порядок опроса каналов (в конфигурации куба)

С ДМА будет надежнее и быстрее.

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

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

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

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

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

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

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

как попало, потому что возможно у вас нарушен гдето порядок опроса поллингом. Вам перед каждым циклом поллинга надо делать перезапуск АЦП и тогда будет порядок. Ну и не мешало бы проверить порядок опроса каналов (в конфигурации куба)

С ДМА будет надежнее и быстрее.

Благодарю за ответы! Будут делать с ДМА, но хотелось бы вначале "добить" (найти причину что не так) с polling. В общем пробовал разные варианты и получилось, что если перед условиями 

if (HAL_ADC_PollForConversion(&hadc1, 100) == HAL_OK)
  ADCValue[0] = HAL_ADC_GetValue(&hadc1); // Первый канал

обнулять элементы массива (ADCValue[0...2]=0), в которые заносятся значения возвращаемые HAL_ADC_GetValue, всё прекрасно работает. А если не обнулять, то чихарда. Почему так получается, ведь значения всё равно перезаписываться должны? Как будто время на что-то процессором тратится и значения получаемые от АЦП приходят с произвольной задержкой.

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

Коллеги подскажите как лучше и быстрее подключить сканер штрих кода к STM32F103C8

У него есть режим USB клавиатуры, эмуляция ком порта и разрыв клавиатуры.

Я думал что проще всего сделать в разрыв клавиатуры аля пи-си пополам, но не взлетело, нужна некая инициализация и как ее сделать пока не понимаю.

После подачи питания сканер молчит если линии дата и клок подтянуть к +5 так же тишина, если клок притянуть к земле то начинают идти какие то импульсы но сканер внешне признаков жизни не подает.

Возможно кто то имел подобный опыт, поделитесь пожалуйста.

Сканер у меня honeywell  MS9520

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

После подтяжки клока к земле  идут импульсы ,но они какие то хаотичные, просто 0xFF с интервалом от 0,2 до 0,9ms и идут бесконечно. Видать он чего то ждет, но что дать ему я не понимаю))

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

К стм это не имеет никакого отношения. Вы либо создайте конкретную тему для своих обильных вопросов, либо разбирайтесь молчком, дабы не захламлять профильную тему

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

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

ну написано же русским языком

Quote

However it is impossible to simulate the behavior of the on-chip peripherals for many devices.

и желательно бы при отладке использовать таки

Quote

 real-world application features

о чем собственно и толкуют (в кратце). Возможность отладки "типа в железе" с использованием специальных костылей оставлена для некоторых устройств. Нам ценно понятно только семейство STM32F100. И все. Фича больше не развивается

Ну и пмсм отладка в железе при такой доступности средств этой самой отладки обязана быть просто безальтернативным вариантом для любого уважающего себя разработчика.

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

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

Ребята, подскажите, в чём ошибка, 3 канала АЦП в режиме Interruption и постоянно выдаётся значение с последнего канала, т.е. того, у которого sConfig.Rank = 3 ?

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



  /* USER CODE BEGIN 2 */
HAL_ADC_Start_IT(&hadc1);
  /* USER CODE END 2 */

/* ADC1 init function */
static void MX_ADC1_Init(void)
{

  ADC_ChannelConfTypeDef sConfig;

    /**Common config 
    */
  hadc1.Instance = ADC1;
  hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;
  hadc1.Init.DiscontinuousConvMode = DISABLE;
  hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  hadc1.Init.NbrOfConversion = 3;
  if (HAL_ADC_Init(&hadc1) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_0;
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_13CYCLES_5;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_1;
  sConfig.Rank = 2;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

    /**Configure Regular Channel 
    */
  sConfig.Channel = ADC_CHANNEL_2;
  sConfig.Rank = 3;
  if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
  {
    _Error_Handler(__FILE__, __LINE__);
  }

}

/* USER CODE BEGIN 4 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc1)
{
		adcResult[0] = HAL_ADC_GetValue(hadc1);
		adcResult[1] = HAL_ADC_GetValue(hadc1);
		adcResult[2] = HAL_ADC_GetValue(hadc1);
}
/* USER CODE END 4 */


 

В adcResult[0...2] значения получаемые с 3-го канала. Если сконфигурировать на 2-а канала, то будут значения с 2-го канала.

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

ну правильно. Вы же никак не делите результаты преобразования. Во все элементы массива заносится всегда одно и то же HAL_ADC_GetValue(hadc1); три раза подряд. Регистр данных то один

 

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

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

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

12 часа назад, Koret сказал:

подскажите, в чём ошибка

Колл-бак функция HAL_ADC_ConvCpltCallback() вызывается при окончании каждого преобразования, для всех каналов одна и та же. А функция HAL_ADC_GetValue(hadc1) просто перекладывает готовый результат преобразования в массив adcResult[], она не вызывает новое преобразование.

Поэтому, чтобы отличить результат какого канала лежит в АЦП, нужно завести переменную-индекс, которая будет увеличиваться на 1 при каждом вызове HAL_ADC_ConvCpltCallback(). И этот индекс будет индексом массива результатов.

После преобразования всех каналов этот индекс надо сбросить в 0, чтобы в следующий раз начать с начала массива. Признак последнего канала - флаг окончания сканирования каналов ADC_FLAG_EOS.

uint8_t index = 0;

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc1)  
{
	if (__HAL_ADC_GET_FLAG(hadc1, ADC_FLAG_EOC)) 
  	{
  		adcResult[index] = HAL_ADC_GetValue(hadc1); 
  		index++;
  	}
	if (__HAL_ADC_GET_FLAG(hadc1, ADC_FLAG_EOS))  
 	{
 		index=0;
	}
}

 

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

3 часа назад, Yurkin2015 сказал:

Признак последнего канала - флаг окончания сканирования каналов ADC_FLAG_EOS.

Почему-то на на флаг (ADC_FLAG_EOS) ругается как незадекларированный. 

Я вчера пробовал через простое условие сортировать, т.е. если i==0 это первый элемент массива, i==1 - 2-й, i==2 - 3-й и обнуляем в ноль. Но что-то результата не дало. А по Вашему коду ругается на ADC_FLAG_EOS.

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

Ребята, а ещё по DMA (ПДП) не подскажите, почему-то при "бесконечной" работе АЦП (Continuos Conversion Mode) и ПДП (Mode: Circular) записанные значения в 1-ом и 2-ом элементах массива изменяются незначительно, в пределах 5-10 единиц, а вот в 3-ем (последнем) элементе периодически значения могут опускаться на 300-400 единиц. При этом если поменять источники АЦП местами, всё равно именно в последнем элементе массива сильно скачут значения.

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

7 часов назад, Koret сказал:

ругается на ADC_FLAG_EOS

Значит в Вашем процессоре нет такого флага. Поищите другой флаг, который определяет начало или конец преобразования группы входов АЦП.

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

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

Значит в Вашем процессоре нет такого флага.

Уже сообразил. Сейчас немножко разбираюсь с ПДП и получилось, что АЦП в режиме ПДП вызывает функцию HAL_ADC_ConvCpltCallback() только после занесения данных со всех каналов, т.е. получается для ПДП нет необходимости сравнивать флаги (не в плане сортировки значений по каналам, а выполнения какого-то кода после преобразования всех данных) или я ошибаюсь? Т.е. не нужен флаг ADC_FLAG_EOS, т.к. функция HAL_ADC_ConvCpltCallback и так вызывается после всех преобразований и копирований ПДП.

Подскажите, если я 3-й таймер настроил на запуск по переполнению АЦП, который в свою очередь работает в режиме ПДП, как собственно указать ПДП какой массив использовать. Т.е. команду HAL_ADC_Start_DMA(&hadc1,(uint32_t*) &ADC_Data,3);   уже выполнять не надо, но куда ПДП сохранять результаты не указано, как это сделать?

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

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

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

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

46 минут назад, mail_robot сказал:

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

Собственно и интересует вопрос как сделать, чтобы ПДП с АЦП запускались без использования возвратных функций таймера, т.е. как Вы ранее писали: "Если еще флаг-инициатор от таймера прикрутите к старту опроса, то вообще будет все автоматом", чтобы всё было автоматически.

Ребята, вопросами уже всех, конечно, замучил, но здесь одно из немногих мест, где помогают. Подскажите, есть ли какое нибудь глобальное прерывание с наивысшим приоритетом на случай, если контроллер подвис или не отвечает определённое время? Т.е. если вдруг какая-то нестандартная ситуация, чтобы можно было вывести какую-нибудь сигнализацию.

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

9 hours ago, Koret said:

Подскажите, есть ли какое нибудь глобальное прерывание с наивысшим приоритетом на случай, если контроллер подвис или не отвечает определённое время?

почитайте про WDT и WWDT. Много полезного

9 hours ago, Koret said:

как сделать, чтобы ПДП с АЦП

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

Я расскажу, но скоро начнет надоедать уже разжевывать.

Запускается ПДП как обычно и "прицепляется" к своей группе АЦП. Как только АЦП имеет в регистре данных результат, он запускает цикл работы ПДП и тот переносит значение в память или еще там куда то. Этот процесс непрерывный. Вопрос - как им управлять? Очень просто - в конфигурации АЦП указать, что стартовым условием будет являться не софт, не авто, а таймер такой то. Как только таймер сработал, АЦП выполнил преобразование, пдп увидел и отработал. Остановили таймер, остановился весь паровоз. Сложно?

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

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

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

5 часов назад, mail_robot сказал:

Читайте внимательно документацию на процессор. Хоть чуть чуть труда то надо прикладывать

Вы не поверите, но стараюсь читать и внимательно, но ввиду того, что с микроконтроллерами начал своё знакомство только недели 2 назад, многое просто с первого-второго... раза сложно для понимания. Что-то незначительное упускается из виду и в результате в целом делаются неправильные выводы. 

5 часов назад, mail_robot сказал:

Запускается ПДП как обычно и "прицепляется" к своей группе АЦП. Как только АЦП имеет в регистре данных результат, он запускает цикл работы ПДП и тот переносит значение в память или еще там куда то. Этот процесс непрерывный. Вопрос - как им управлять? Очень просто - в конфигурации АЦП указать, что стартовым условием будет являться не софт, не авто, а таймер такой то. Как только таймер сработал, АЦП выполнил преобразование, пдп увидел и отработал. Остановили таймер, остановился весь паровоз. Сложно?

Можно было так и не разжёвывать, т.к. многое (выделил серым) было и так понятно, но главного (в пред. сообщении: "как собственно указать ПДП какой массив использовать") так и не понял. Непонятно для меня следующее: я в Кубе добавил таймер, включил АЦП (непрерывное преобразование выключено), в АЦП указал, чтобы он включался по переполнению таймера, привязал ПДП к АЦП (режим normal). Вопрос, куда ПДП будет переносить значения, если мы не указали ему начальный адрес в памяти (массив) относительно которого он со смещением будет раскладывать значения? В обычном варианте, как в документации написано, я вызываю функцию HAL_ADC_Start_DMA() которой в качестве одного из аргументов передаю массив (в Си это просто указатель) и всё нормально работает.

Если я, например, в main после инициализации периферии запущу один раз HAL_ADC_Start_DMA(), то, насколько я понимаю, после переноса значений ПДП HAL выполнит HAL_ADC_Stop_DMA() и "привязка" ПДП к массиву "слетит". Поэтому я и спрашивал, как указать ПДП массив, чтобы он не "слетал".

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

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

Если я, например, в main после инициализации периферии запущу один раз HAL_ADC_Start_DMA(), то, насколько я понимаю, после переноса значений ПДП HAL выполнит HAL_ADC_Stop_DMA() и "привязка" ПДП к массиву "слетит". Поэтому я и спрашивал, как указать ПДП массив, чтобы он не "слетал".

Насколько я знаю ХАЛ сам ничего не выполняет - надо вызвать! Насколько я знаю ДМА после запуска с указателем на буфер, он сам должен остановиться по заполнению буфера, там еще длина буфера должна передаваться обязательно.

Вообще, у вас исходники для этих функций присутствуют HAL_ADC_...??? Если ДА, то проще всего вам сопоставить то что вы читаете в документации на ДМА модуль с тем, что написано в исходниках этих функций, это вознесет ваше понимание документации на недосягаемую высоту, поверьте, проверено не раз :).

Если что то все же останется не понятно в исходниках - выкладывайте, я поясню.

Можно сделать все! Но чем больше можно, тем больше нельзя!

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

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

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

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

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

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

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

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

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

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

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

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