Jump to content
Карен Григорян

проблема с АЦП в stm32 при симуляции в Proteus

Recommended Posts

Posted (edited)

Здравствуйте, товарищи форумчане!

У меня вот такая проблемка: есть такая схема:

image.png.44a66c942a602b7fd28b8bee50f06f7b.png

По сути тут stm32 на который подаётся некоторое постоянное напряжение, а именно на вход PA1. МК получает его, приводит в цифровую форму (разрядность АЦП равна восьми) и выводит их при помощи восьми GPIO выводов, а именно PB0-PB7. Эти выводы соединены со схемой ЦАП, которая преобразует значение, полученное от stm32 обратно в аналоговую форму и выводит в пробнике R2(1).

Проблема в том результат выводится не верный. Точнее говоря не всегда верный. Когда я подаю 1В, то на выходе получаю 0,99В, что верно. Но когда, например, подаю 300мВ, то получаю 1.8В, что совсем не верно. Код прошивки предельно прост:

  while (1)
  {
        HAL_ADC_Start_IT(&hadc1);
        HAL_Delay(10);

}

Код колбека прерывания:

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
    if(hadc->Instance == ADC1) //check if the interrupt comes from ACD1
    {
      int adc = HAL_ADC_GetValue(&hadc1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,(adc>>0)&1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,(adc>>1)&1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,(adc>>2)&1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_3,(adc>>3)&1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,(adc>>4)&1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,(adc>>5)&1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_6,(adc>>6)&1);
            HAL_GPIO_WritePin(GPIOB,GPIO_PIN_7,(adc>>7)&1);
    }
        }

На всякий случай вот настройка АЦП в stm32:

image.png.1299783535650086a3f09c69189fb8a7.png

Вот пример неправильного вычисления:

image.png.179d6bcbbbd0f4590fe34936fb2c1ce6.png

Edited by Карен Григорян

Share this post


Link to post
Share on other sites
Posted (edited)

Ну, потомучто это протеус, не стоит ему доверять на все сто. Да и в реальной схеме можете столкнуться с такой проблемой. Перед использованием АЦП его желательно откалибровать перед запуском.

Edited by Yuriy.pv

Share this post


Link to post
Share on other sites

Оценка точности измерения тока интеллектуальными силовыми ключами PROFET

Интеллектуальные силовые ключи PFOFET производства Infineon могут измерять ток нагрузки с разной точностью, зависящей как от абсолютной величины потребляемого тока, так и от технологии производства конечной продукции, в частности – от наличия или отсутствия этапа калибровки. В статье подробно разбирается расчет коэффициента передачи тока на примере ключа BTS7004-1EPP.
Подробнее

Join the conversation

You are posting as a guest. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

  • Сообщения

    • Ну и выкиньте эти магниты. Всё равно на хорошем ухабе телефон своим "наклеенным металлическим кольцом для примагничивания" не удержится, искать его потом по всему салону. Самое надёжное - слот для телефона типа "карман". Про теорию "почему ошибки" могу предположить, что большое количество железа вокруг катушки (в том числе магниты) являются приличной нагрузкой. Вихревые токи никто не отменял.   Терморезистор. Откусывать нельзя. И "синенький проводочек над микросхемой" восстановите. Это "земля". На двухслойной плате нормально не развелось, вот и пустили поверху. Без него вероятно будет сбоить эта микросхема при работающем двигателе.
    • Осталось подобрать конденсатор, который работает при -50 (твердотельный, может?)  и при этом выпускался в СССР. Как вариант рассмотреть маховик . Потом все остальное. Хотя, конденсатор - это тоже химический источник в некотором смысле.
    • Ошибаешься. Нуждается. Любопытство - двигатель прогресса. Так уж человек устроен, что ему необходима новая информация и знания, которые он будет всегда стремиться получить.   Для нас - да. А для них - нет. Люди не просто так отдают большие деньги на то, чтобы подняться в космос и посмотреть на Землю со стороны.    Можно завидовать, можно сожалеть, а можно наворовать как наши чинуши, и свалить туда жить, как они и делают.
  • Similar Content

    • By dim21841
      Добрый день.
      Прошу помощи в выборе контроллера stm32 под следующую задачу:
      Bluetooth HC-05 (1 uart) необходимо связывать по uart с:
      1) MAX232 (2 uart) по 9600, иногда 115200,
      2) с Atmega328 (3 uart) по 115200.
      Задача stm32 выставлять скорость на hc-05 и соединять между собой нужные uart в соответствии с выбором (4 switch в dip-8 корпусе).
      Кто может что-то посоветовать?
      В stm32 пока совсем начинающий.
      STM32 выбрал потому что в перспективе хочу добавить возможность параллельно  выводить данные и на lcd.
      Зарание благодарен за помощь.
    • By Serhii Serheiev
      Помогите пожалуйста советом. Бьюсь несколько дней с опцией ADC.
      Я использую двухканальный АЦП IN0 и IN1 на микроконтроллере STM32L010RB через библиотеку HAL.
      Если проверять по отдельности, все в порядке, но когда я проверяю вместе, у меня все время одна и та же проблема: первый канал перезаписывает данные на втором канале, и у меня одинаковые данные на IN0 и IN1 в терминале
      Функция для выбора IN0.
      void ADC_Select_CH0(void) { ADC_ChannelConfTypeDef sConfig_0 = {0}; sConfig_0.Channel = ADC_CHANNEL_0; sConfig_0.Rank = 0; if (HAL_ADC_ConfigChannel(&hadc, &sConfig_0) != HAL_OK) { Error_Handler(); } } Функция для выбора IN1
      void ADC_Select_CH1(void) { ADC_ChannelConfTypeDef sConfig_1 = {0}; sConfig_1.Channel = ADC_CHANNEL_1; sConfig_1.Rank = 0; if (HAL_ADC_ConfigChannel(&hadc, &sConfig_1) != HAL_OK) { Error_Handler(); } } основной цикл
      while(1) { ADC_Select_CH0(); HAL_ADC_Start(&hadc); HAL_ADC_PollForConversion(&hadc, 100); Axis[0] = HAL_ADC_GetValue(&hadc); HAL_ADC_Stop(&hadc); ADC_Select_CH1(); HAL_ADC_Start(&hadc); HAL_ADC_PollForConversion(&hadc, 100); Axis[1] = HAL_ADC_GetValue(&hadc); HAL_ADC_Stop(&hadc); sprintf(Tx_Data, "Axis X: %d;\r\nAxis Y: %d;\r\n\n\n", Axis[0], Axis[1]); HAL_UART_Transmit(&huart2, (uint8_t*)Tx_Data, strlen(Tx_Data), 1000); } ADC конфигурация:
      static void MX_ADC_Init(void) { hadc.Instance = ADC1; hadc.Init.OversamplingMode = DISABLE; hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.SamplingTime = ADC_SAMPLETIME_160CYCLES_5; hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.ContinuousConvMode = ENABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.DMAContinuousRequests = DISABLE; hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV; hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED; hadc.Init.LowPowerAutoWait = DISABLE; hadc.Init.LowPowerFrequencyMode = DISABLE; hadc.Init.LowPowerAutoPowerOff = DISABLE; if (HAL_ADC_Init(&hadc) != HAL_OK) { Error_Handler(); } }  
    • By Родион Евченко
      Здравствуйте! Не могу понять, почему на дисплей выводятся только черные квадраты, если смотреть прямо, а если под углом, то видно строку, которую я вывожу. Как убрать эти квадраты, а строку сделать видимой?
    • By SWAP
      Доброго времени суток, форумчане. Вопрос хотел задать на робофоруме, однако, похоже там сон-час (последние лет 5).
      На моих роботах стоят raspberryPi с помощью которых я в эклипсе удаленно дебажу и прогаю находящиеся на борту STMки через "openocd": https://www.instructables.com/Wireless-Programming-and-Debugging-With-STM32-and-/
      Однако, есть серьезное неудобство. При включении робота, требуется вручную подключаться к пишке по ssh и запускать команду: "sudo openocd", после чего все работает.
      Пробовал различные варианты автозапуска команды "sudo openocd" при старте пишки, выпавшие в первых страницах гугла, но результата не получил.
      Быть может, кто-нибудь из местных имеет опыт запуска "openocd" при старте системы?
      (p.s.: мои распбианы без десктопа)
       
       
       
       
    • By Константин Галкин
      Начинаю знакомство с STM32 после AVRок. Решил сделать дрыганог через прерывание по таймеру. Плата Nucleo на базе STM32F446re, частота работы до 180МГц, собираю проект в CubeIDE.
      Для опыта решил взять таймер6 (на самом деле мне всё равно какой) и вызывать прерывания по переполнению счётчика. По даташиту, его тактирование идёт от APB1, которая работает на 45МГц, с множителем Х2 (т.е получается 90МГЦ). Прескалер выставил в 89 (т.е счёт должен идти с частотой 1 МГц), каунтер на 1 (т.е по идее я должен получать прерывания с частотой 500КГц).
      static void MX_TIM6_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; htim6.Instance = TIM6; htim6.Init.Prescaler = 89; htim6.Init.CounterMode = TIM_COUNTERMODE_UP; htim6.Init.Period = 1; htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; if (HAL_TIM_Base_Init(&htim6) != HAL_OK) { Error_Handler(); } sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK) { Error_Handler(); } } В обработчике прерывания вызываю смену состояния светодиода на PA5.
      void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if(htim->Instance == TIM6) //check if the interrupt comes from TIM1 { HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5); } } Загрузив код и проверив логическим анализатором я получаю частоту 254,5Кгц. Меняя значения прескалера в меньшую сторону увеличения частоты добиться не могу (основной цикл пуст, в программе никаких вычислений кроме этого нет). Почему так происходит?


×
×
  • Create New...