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

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

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

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

Особенности хранения литиевых аккумуляторов и батареек

Потеря емкости аккумулятора напрямую зависит от условий хранения и эксплуатации. При неправильном хранении даже самый лучший литиевый источник тока с превосходными характеристиками может не оправдать ожиданий. Технология, основанная на рекомендациях таких известных производителей литиевых источников тока, как компании FANSO и EVE Energy, поможет организовать правильный процесс хранения батареек и аккумуляторов. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 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
Ссылка на комментарий
Поделиться на другие сайты

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

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

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

Коллеги подскажите как лучше и быстрее подключить сканер штрих кода к 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 пользователей онлайн

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

  • Сообщения

    • Вы пишете: "Там логика + 4 релюшки". Никакую логику никакой самый точно подобранный предохранитель не спасёт - скорости не хватит. Защищать обмотку реле предохранителем тоже бессмысленно - есть напряжение - оно сработает, нет напряжения - не сработает. От не очень сильно повышенного напряжения тоже не сгорит. Осюда простой вывод: такую схему предохранитель может защитить разве что от пожара. Поставьте на ток в 3-4 раза больше потребляемого схемой. Этого будет более чем достаточно, чтобы не раздражало постоянное и всегда не вовремя срабатывание предохранителя, работающего "на грани". Если вы посчитали, что эта схема потребляет не более 175 мА, то поставьте предохранитель на 0,5 - 1,0 А. И для такой схемы не важно, быстрый это предохранитель или обычный. Поставьте, какой найдёте.
    • SG3525 ваш путь, гуглите "sg3525 push-pull converter" - схемы простые, а мощность у вас небольшая. Вы их постоянным током питать собрались? Хм... За что вы её любите, с одинокими транзисторами на выходах?  У SG3525 двухтактные выходы, это удобнее.
    • По три раза на дню? 
    • WAT? Чет как то не клеится LT1013 и предусилитель?
    • Например очень удобно монтировать и настраивать ток покоя например. да мало ли.
    • И кто транзисторы закрывать будет? R5 R6? Почему обмотки трансформатора к истокам, а не к стокам? Возьмите схему любого преобразователя напряжения для автомобильного усилителя и добавьте вторичку до нужных 150 В. Это будет быстрее и проще для Вас, чем изучать схемотехнику.
    • Доброго времени суток всем. Перечитав некоторое количество зарубежных форумов и по советовавшись с одним из инженеров из Америки, я пришел к выводу, что мне достаточно интересен данный ОУ. По ковыряв по сути доступные схемы на русскоязычных ресурсах так и не смог найти ни схем, ни информации касаемо изготовления схемы преда на данном ОУ. По сему поднимаю здесь данную тему. Может, что то где то не увидел и пропустил.    Значит стоит задача построения схемы на этом усилителе. Хочу собрать "идеальный" пред для своей системы. Оконечники у меня разные. Есть ланзар, есть переделанная классика унч 50-8, есть сокол, есть Зуев (очень нравится его звучание). Так же есть возможность подключиться к японцу (модель не скажу) и к лампам. Но лампы здесь, вопрос второстепенный. Все же тама Hi-fi.  Со слов зарубежного инженера данный ОУ отличается от многих своей стабильностью и линейностью. Позволяет получить чистый сигнал на выходе сродне студийному звуку.  Так де посмотрев дотащит, параметры сие вполне меня устраивают. Если есть кто то кто достаточно глубоко понимает принципы работы ОУ и строит схемы, был бы рад по общаться, чтоб понимать, что я получу на выходе и попробовать построить схему, возможно даже с последующей оплатой. Админы простите и поймите. Сам я далеко не спец, по этому прощу помощи.    P.S. не кидайтесь помидорами. Посты я писать не умею, знаний инженерных так же обделен... Есть только 12 лет радиокружка с построением простых схем. Но привнести в этот мир лучшее, есть желание. 
×
×
  • Создать...