Программирование синусоидального и пилообразного сигналов с помощью цифро-аналогового преобразователя на микроконтроллере STM32
Емельянов Александр Александрович, доцент;
Бесклеткин Виктор Викторович, ассистент;
Иванин Александр Юрьевич, студент;
Пестеров Дмитрий Ильич, студент;
Юнусов Тимур Шамильевич, студент;
Иванов Павел Евгеньевич, студент;
Соснин Александр Сергеевич, студент.
Российский государственный профессионально-педагогический университет (г. Екатеринбург)
Целью данной работы является программирование студентами на лабораторном стенде синусоидального и пилообразного сигналов с помощью цифро-аналогового преобразователя (ЦАП) [1], [2], [3]. Программирование осуществляется в среде CooCox CoIDE.
ЦАП (DAC) – цифро-аналоговый преобразователь, устройство для преобразования входного дискретного (обычно двоичного) кода в аналоговый сигнал. ЦАП является интерфейсом между дискретным цифровым миром и реальным аналоговым.
ЦАП в STM32F407VGT6 имеет следующие характеристики:
‒ напряжение от 0 до 3,3 В;
‒ аппаратная генерация шума и треугольных импульсов;
‒ два независимых канала;
‒ возможность переключения между 8- и 12-разрядными режимами с выравниванием битов по левому или по правому краю.
ЦАП использует два вывода отладочной платы PA4 и PA5. Именно эти выводы задействованы в данной работе.
ЦАП в STM32 можно использовать как генератор псевдослучайных чисел. В таком случае на цифровом осциллографе можно будет наблюдать шум. Помимо этого, можно задавать амплитуду треугольных импульсов.
Синусоидальный сигнал аппаратно получить нельзя, поэтому рекомендуется использовать ЦАП совместно с DMA для отправки значений синуса в регистр ЦАП. Также синусоидальный сигнал можно сгенерировать, используя прерывания, и описать в обработчике прерывания запись значений массива синуса в регистр ЦАП.
Алгоритм набора кода в среде разработки CooCox CoIDE состоит в следующем:
- Запускаем среду программирования CooCox CoIDE.
- После запуска CooCox CoIDE в строке меню нажать: Project → New Project.
- В появившемся окне в поле «Project name» ввести имя своему проекту.
- Далее нужно выбрать поле с надписью «Chip».
- Появится окно с выпадающими списками различных фирм микроконтроллеров (рис. 1). Необходимо открыть список ST, затем из выпадающего списка открыть подсписок STM32F4x, после чего найти микроконтроллер STM32F407VG, выбрать его левым щелчком мыши и нажать Finish (рис. 2).
Рис. 1. Выбор фирмы микроконтроллера
Рис. 2. Выбор микроконтроллера
- После проделанных действий появится главное окно с репозиторием для выбора библиотек (рис. 3). Необходимо подключить следующие библиотеки:
‒ RCC – для управления тактовым генератором;
‒ GPIO – для управления портами ввода-вывода;
‒ TIM – для управления таймерами;
‒ DMA – для управления прямым доступом к памяти (DMA);
‒ DAC – для работы с цифро-аналоговым преобразователем.
Рис. 3. Выбор библиотек в репозитории
- После выбора библиотек необходимо на панели инструментов выбрать «New file» и создать файлы «dac_user.c» и «dac_user.h» (рис. 4).
Рис. 4. Создание файлов «dac_user.c» и «dac_user.h»
- В панели файлов открыть «dac_user.h», два раза щелкнув по нему левой кнопкой мыши, и с помощью директивы «#include <>» записать в нем все заголовочные файлы, необходимые для работы с таймером (TIM), портами ввода-вывода (GPIO), прямым доступом к памяти (DMA) и ЦАП (DAC) (рис. 5).
Рис. 5. Запись заголовочных файлов
- Открыть файл «dac_user.с» и создать в нем функцию, в которой необходимо включить тактирование периферийных устройств, а также ввести структуры и заполнить их для инициализации портов ввода-вывода, таймера (TIM4), DMA и ЦАП. Содержание файла «dac_user.с» представлено в листинге 1.
Листинг 1. Содержание файла «dac_user.с»
#include "dac_user.h"
void dac_triangle_sin(void)
{
//---Таблица значений синусоиды---//
uint16_t sin[74] = {2225, 2402, 2577, 2747,2912,3070,3221,3363,3494,3615,
3724,3820,3902,3971,4024,4063,4085,4095,4063,4024,3971,3902,3820,3724,
3615,3495,3363,3221,3071,2912,2747,2577,2403,2226,2047,1869,1692,1517,
1347,1182,1024,873,731,600,479,370,274,192,274,124,70,31,31,10,0,10,31,
70,123,192,274,370,479,599,599,731,873,1023,1182,1347,1517,1691,1868,
2047};
//---Тактирование периферийных устройств---//
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_DMA1, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4 | RCC_APB1Periph_DAC, ENABLE);
//---Инициализация 4 вывода GPIO---//
GPIO_InitTypeDef gpio_dacchannel1;
GPIO_StructInit(&gpio_dacchannel1);
gpio_dacchannel1.GPIO_Mode = GPIO_Mode_AF;
gpio_dacchannel1.GPIO_OType = GPIO_OType_PP;
gpio_dacchannel1.GPIO_Pin = GPIO_Pin_4;
gpio_dacchannel1.GPIO_PuPd = GPIO_PuPd_UP;
gpio_dacchannel1.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_dacchannel1);
//---Инициализация 5 вывода GPIO---//
GPIO_InitTypeDef gpio_dacchannel2;
GPIO_StructInit(&gpio_dacchannel2);
gpio_dacchannel2.GPIO_Mode = GPIO_Mode_AF;
gpio_dacchannel2.GPIO_OType = GPIO_OType_PP;
gpio_dacchannel2.GPIO_Pin = GPIO_Pin_5;
gpio_dacchannel2.GPIO_PuPd = GPIO_PuPd_UP;
gpio_dacchannel2.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &gpio_dacchannel2);
//---Инициализация таймера TIM4 в качестве триггера---//
TIM_TimeBaseInitTypeDef timer;
TIM_TimeBaseStructInit(&timer);
timer.TIM_ClockDivision = TIM_CKD_DIV1;
timer.TIM_CounterMode = TIM_CounterMode_Up;
timer.TIM_Period = 20-1;
timer.TIM_Prescaler = 10;
TIM_TimeBaseInit(TIM4, &timer);
TIM_SelectOutputTrigger(TIM4, TIM_TRGOSource_Update);
//---Инициализация альтернативных функций---//
GPIO_PinAFConfig(GPIOA, GPIO_PinSource4, GPIO_AF_TIM4);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_TIM4);
//---Инициализация ЦАП, канал 1---//
DAC_InitTypeDef dac_triangle;
DAC_StructInit(&dac_triangle);
dac_triangle.DAC_Trigger = DAC_Trigger_T4_TRGO;
dac_triangle.DAC_WaveGeneration = DAC_WaveGeneration_Triangle;
dac_triangle.DAC_LFSRUnmask_TriangleAmplitude = DAC_TriangleAmplitude_4095;
dac_triangle.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_1, &dac_triangle);
DAC_Cmd(DAC_Channel_1, ENABLE);
//---Инициализация DMA---//
DMA_InitTypeDef DMA_dac;
DMA_StructInit(&DMA_dac);
DMA_dac.DMA_Channel = DMA_Channel_7;
DMA_dac.DMA_PeripheralBaseAddr = (uint32_t)&(DAC->DHR12R2);
DMA_dac.DMA_Memory0BaseAddr = (uint32_t)sin;
DMA_dac.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_dac.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_dac.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_dac.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_dac.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_dac.DMA_Mode = DMA_Mode_Circular;
DMA_dac.DMA_Priority = DMA_Priority_Medium;
DMA_dac.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_dac.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
DMA_dac.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_dac.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream6, &DMA_dac);
//---Инициализация ЦАП, канал 2---//
DAC_InitTypeDef dac_sin;
DAC_StructInit(&dac_sin);
dac_sin.DAC_Trigger = DAC_Trigger_T4_TRGO;
dac_sin.DAC_WaveGeneration = DAC_WaveGeneration_None;
dac_sin.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DAC_Init(DAC_Channel_2, &dac_sin);
DAC_DMACmd(DAC_Channel_2, ENABLE);
DAC_Cmd(DAC_Channel_2, ENABLE);
DMA_Cmd(DMA1_Stream6, ENABLE);
TIM_Cmd(TIM4, ENABLE);
}
- После этого в файле «dac_user.h» записать прототип функции «dac_triangle_sin()» (рис. 6), а также с помощью директивы «#include<>» подключить заголовочный файл «dac_user.h» в «main.c».
Рис. 6. Запись прототипа функции «dac_triangle_sin()»
- После того как все файлы были заполнены и подключены к «main.c», необходимо записать функцию в основную функцию «main()» (рис. 7). Цикл «while(1)» в данной программе остается пустым.
Рис. 7. Содержание функции «main()»
- После написания кода программы, его необходимо скомпилировать. Для этого в панели инструментов нужно нажать «Build». В случае успешной компиляции в консоли появится надпись «BUILD SUCCESSFUL», а также будет указан размер программы. Если в коде присутствуют ошибки, то в консоли будет указано, где именно находятся эти ошибки, а также появится надпись «BUILD FAILED».
- После завершения компиляции последним этапом станет загрузка рабочей программы в микроконтроллер. Для этого нужно через специальный кабель (удлинитель USB) подключить программатор, расположенный на лабораторном стенде, к компьютеру. После подключения в панели инструментов нажать «Download Code to Flash» и дождаться окончания загрузки. В случае удачной загрузки в консоли появятся надписи: «Erase: Done»; «Program: Done»; «Verify: Done». Если существуют проблемы с подключением платы к компьютеру, то появится надпись «Error: Connect failed, check config and cable connection». Необходимо проверить кабель, к которому подключено устройство.
Результаты программирования синусоидального и пилообразного сигналов с помощью цифро-аналогового преобразователя даны на рис. 8.
Рис. 8. Лабораторный стенд для исследования генерации пилообразного и синусоидального сигналов с помощью ЦАП
Литература:
- Анучин А. С. Системы управления электроприводов: учебник для вузов / А. С. Анучин. – М.: Изд. дом МЭИ, 2015. – 373 с.
- Огородников И. Н. Микропроцессорная техника: введение в Cortex-M3: учеб. пособие / И. Н. Огородников. – Екатеринбург: изд-во Урал. Ун-та, 2015. – 116 с.
- Джозеф Ю. Ядро Cortex-M3 компании ARM. Полное руководство / Ю. Джозеф; пер. с англ. А. В. Евстифеева. – М.: Додэка-XXI, 2012. – 552 с.