Всех приветствую! И сегодня речь снова пойдет об использовании STM32CubeMx, на очереди модуль цифро-аналогового преобразователя, он же ЦАП, он же DAC.
В общем, открываем STM32CubeMx и создаем новый проект. Я буду использовать для тестирования плату с микроконтроллером STM32F103VE. Соответственно, его я и выбрал при создании проекта. Теперь давайте разберемся с периферией - пусть будет задействован модуль DAC и выход DAC_OUT2 (PA5). Так и настраиваем:
Вывод PA5 CubeMx автоматически настроил на работу в нужном режиме:
В принципе, больше ничего пока менять не будем, генерируем проект и видим, что CubeMx добавил в main.c функцию инициализации модуля DAC, что, собственно, от него и требовалось:
static void MX_DAC_Init(void) { /* USER CODE BEGIN DAC_Init 0 */ /* USER CODE END DAC_Init 0 */ DAC_ChannelConfTypeDef sConfig = {0}; /* USER CODE BEGIN DAC_Init 1 */ /* USER CODE END DAC_Init 1 */ /** DAC Initialization */ hdac.Instance = DAC; if (HAL_DAC_Init(&hdac) != HAL_OK) { Error_Handler(); } /** DAC channel OUT2 config */ sConfig.DAC_Trigger = DAC_TRIGGER_NONE; sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE; if (HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_2) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN DAC_Init 2 */ /* USER CODE END DAC_Init 2 */ }
В STM32 DAC 12-ти битный, поэтому мы можем преобразовать в аналоговый сигнал любое цифровое значение от 0 до 4095. Для примера выведем на PA5 уровень напряжения, равный 1.65 В. Поскольку 3.3 Вольтам соответствует цифровой код 4095, то для 1.65 В - нужное значение в 2 раза меньше, то есть примерно 2048. Это и осуществляем в функции main()
после инициализации периферии:
int main(void) { /* USER CODE BEGIN 1 */ /* USER CODE END 1 */ /* MCU Configuration--------------------------------------------------------*/ /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ HAL_Init(); /* USER CODE BEGIN Init */ /* USER CODE END Init */ /* Configure the system clock */ SystemClock_Config(); /* USER CODE BEGIN SysInit */ /* USER CODE END SysInit */ /* Initialize all configured peripherals */ MX_GPIO_Init(); MX_DAC_Init(); /* USER CODE BEGIN 2 */ uint16_t currentDACData = 2048; // Включаем ЦАП, нужный канал HAL_DAC_Start(&hdac, DAC_CHANNEL_2); HAL_DAC_SetValue(&hdac, DAC_CHANNEL_2, DAC_ALIGN_12B_R, currentDACData); /* USER CODE END 2 */ /* Infinite loop */ /* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ } /* USER CODE END 3 */ }
Как видите, все сводится к вызову функции HAL_DAC_SetValue()
, да и только. Параметры тут все понятные - структура, которая соответствует нашему модулю DAC, номер канала, выравнивание данных (по левому краю, либо по правому) и последний аргумент - сами данные. Измерив сигнал на PA5, обнаружим там напряжение, равное 1.65 В, как и было задумано.
Статья получилась небольшая, но базовый пример работает успешно, так что на этом и заканчиваем 👍
А не будет ли интереснее рассмотреть какую-нибудь Discovery с её усилителем и выводом звука на наушники, через уже разведенный разъем?
Тут несколько факторов )
Такая статья уже была для F4Discovery,
Там просто передаются данные по I2S на микросхему, непосредственно ЦАП даже не используется,
Ну и плюс это дополнительное увеличение себестоимости устройства при разработке - использовать ЦАП и собрать усилительный каскад будет в любом случае дешевле.
Знаете, ничего не работало, пока не нашёл в примере от STM тот факт, что нужно перед уставкой значения,нужно запустить сам DAC:
HAL_DAC_Start(&hdac, DAC_CHANNEL_2);
А так, спасибо за уроки!
Добавлю в статью описание этого нюанса, спасибо ) У меня видимо версия Куба постарее, поэтому там работало так...
а где вторая и третья статьи? хоть бы ссылки на них
Добрый день!
Да проблема тут в том, что до их написания руки так и не дошли, примеры я сделал, а потом времени не хватило свободного...
Уберу из статьи этот вводящий в заблуждение абзац и со временем постараюсь статьи про звук все-таки довести до ума.
Приношу свои извинения!
Здравствуйте, а как можно прогнать ШИМ от таймера через ЦАП?
Добрый день, не совсем понял, в чем состоит задача...
Да, извините, этот вопрос я уже решил, буду преобразовывать ШИМ внешним фильтром. У меня есть еще один вопрос, мне необходимо управлять скважностью с помощью 4х-разрядного кода и исходить он должен от ВНЕШНЕГО источника, что можно для этого использовать? Только не злитесь, если вопрос глупый, я новичок)
Добрый день!
А в качестве внешнего источника что используется?
Счетчик на триггерах, мне надо как-то с него считывать данные
У счетчика по всей видимости несколько сигнальных линий на выходе, на которых либо низкий уровень, либо высокий. У STM32 напряжение высокого уровня = 3.3В, но большинство выводов может спокойно обрабатывать и 5В на входе. Таким образом, заводим все эти сигналы на контроллер и в программе анализируем состояние входов. Ну и, соответственно, получив результат меняем скважность ШИМ - можно в прерывании прямо в регистр записывать новое значение.
Плата Nucleo-F413ZH. Генерирую прогу в Кубе, в Кейле добавляю Ваш код. Не работает. Вроде все делаю правильно, но результат нулевой.
Добрый день!
Если есть возможность, вышлите проект на почту, я могу посмотреть.