STM Урок 30. HAL. DAC. Sinus. DMA



Урок 30

DAC. Sinus. DMA

 

Сегодня мы попробуем также посредством технологии DMA создать колебания синусоидальной формы также из данных, заранее подготовленных в массиве в виду того, что синусоидальные колебания вообще не предусмотрены аппаратно в МК. Также по многочисленным просьбам в различных уроках мы попытаемся измерить частоту колебаний и период в тактах полного синусоидального колебания. Для вывода данных на экран также используем LCD 20х4, который мы подключим через переходник I2C.

Проект создаём из проекта DAC_TRIANGLE2. Назовем его DAC_SIN. Запустим проект в Cube и включим там I2C1

 

image00

 

В Configuration оставим пока всё как было.

Сгенерируем, запустим и соберём проект. Настроим программатор. Скопируем файлы lcd.c и lcd.h из проекта I2CLCD80. Подключим файл lcd.c в проект, а также файл lcd.h подключим в файле main.h

 

#include «stm32f4xx.h»

#include «lcd.h»

 

Заменим массив uint16_t buf_tr[64] на вот такой

 

uint16_t buf_sin[60]={

11,45,100,177,274,391,526,678,

844,1024,1215,1415,1622,1834,2048,2262,

2474,2681,2881,3072,3252,3418,3570,3705,

3822,3919,3996,4051,4085,4095,4085,4051,

3996,3919,3822,3705,3570,3418,3252,3072,

2881,2681,2474,2262,2048,1834,1622,1415,

1215,1024,844,678,526,391,274,177,

100,45,11,0

};

 

 

Соответственно здесь также произведем некоторые изменения

 

        HAL_TIM_Base_Start(&htim6);

        HAL_DAC_Start_DMA (&hdac, DAC_CHANNEL_1,(uint32_t*)buf_sin,60,DAC_ALIGN_12B_R);

  /* USER CODE END 2 */

 

Также нам потребуется счётчик и строковая переменная

 

/* Private variables ———————————————————*/

uint32_t clk_counter=0;

char str[20];

uint16_t buf_sin[60]={

 

Также для организации счёта тактов МК нам потребуется определенный код в main.c тут

 

#include «main.h»

#define    DWT_CYCCNT    *(volatile unsigned long *)0xE0001004

#define    DWT_CONTROL   *(volatile unsigned long *)0xE0001000

#define    SCB_DEMCR     *(volatile unsigned long *)0xE000EDFC

/* USER CODE END Includes */

и тут

  /* USER CODE BEGIN 2 */

  uint32_t frq = HAL_RCC_GetHCLKFreq();

  SCB_DEMCR |= 0x01000000;

  DWT_CONTROL|= 1;

  DWT_CYCCNT  = 0;

  HAL_TIM_Base_Start(&htim6);

 

Также внесем определенные изменения в файл stm32f4xx_it.c, практически повторив там всё из файла main.c за некоторым исключением (extern)

 

/* USER CODE BEGIN 0 */

#define    DWT_CYCCNT    *(volatile unsigned long *)0xE0001004

#define    DWT_CONTROL   *(volatile unsigned long *)0xE0001000

#define    SCB_DEMCR     *(volatile unsigned long *)0xE000EDFC

extern uint32_t clk_counter;

/* USER CODE END 0 */

 

 

В обработчике прерывания от DMA в этом же файле мы сосчитаем такты

 

void DMA1_Stream5_IRQHandler(void)

{

  /* USER CODE BEGIN DMA1_Stream5_IRQn 0 */

        clk_counter=DWT_CYCCNT;

        DWT_CYCCNT=0;

  /* USER CODE END DMA1_Stream5_IRQn 0 */

 

Инициализируем дисплей в файле main.c

 

        HAL_DAC_Start_DMA (&hdac, DAC_CHANNEL_1,(uint32_t*)buf_sin,60,DAC_ALIGN_12B_R);

        LCD_ini();

        LCD_Clear();

 

А в бесконечном цикле отобразим то, что мы сосчитали

 

  while (1)

  {

                sprintf((char*)str,»%u»,clk_counter);//количество тактов на период

                LCD_SetPos(0, 0);

                LCD_String(str);

                sprintf((char*)str,»%u»,(clk_counter*1000)/(frq/1000));//время периода в микросекундах

                LCD_SetPos(0, 1);

                LCD_String(str);

                sprintf((char*)str,»%u»,frq/clk_counter);//частота в герцах

                LCD_SetPos(0, 2);

                LCD_String(str);

                HAL_Delay(1000);

                /* USER CODE END WHILE */

 

Соберем код, прошьем контроллер и посмотрим результат.

Попробуем поиграться с таймером

Поставим сначала такие данные

 

image01

 

Уменьшим период вдвое до 50

Пока можно всё это проделать в Keil.

Соберем, прошьем и посмотрим.

Попробуем уменьшить ещё вдвое до 25

Соберем, прошьем и посмотрим.

Убавим до 12

Соберем, прошьем и посмотрим.

 

 

Предыдущий урок Программирование МК STM32 Следующий урок

 

Исходный код

 

 

Купить отладочную плату можно здесь STM32F4-DISCOVERY

 

 

Смотреть ВИДЕОУРОК

STM HAL. DAC. Sinus. DMA

6 комментариев на “STM Урок 30. HAL. DAC. Sinus. DMA
  1. Artem:

    Добрый день! А как можно при помощи того же дма быстро вкл.выкл. генерацию на выходе ЦАП?
    Я так понимаю что нужно только раз запускать дма командой? :
    HAL_DAC_Start_DMA (&hdac, DAC_CHANNEL_1,(uint32_t*)buf_sin,60,DAC_ALIGN_12B_R);

    И потом раз останавливать командой:
    HAL_DAC_Stop_DMA(***);

    • Artem:

      Как это правильно сделать?

      И ещё вопросик:
      Как регулировать амплитуду того же синуса на выходе? Математически , введя буфер в ОЗУ таким же размером как буфер синуса и пересчитывать синусоиду потом динамически в цикле?

  2. Сергей Р.:

    Подскажите, пожалуйста, почему значения счётчика получаются больше на 53-54 такта (6053, 3053, 1553,…), чем казалось бы должно быть: 6000 = 100*60, 3000 = 50*60 и т.д.
    Где происходит добавление тактов?

  3. W4d1m:

    Интересно, если в строке вывода времени периода всё умножить на 2, а в строке вывода частоты разделить всё на 2, то это уже будет больше соответствовать действительности. Сигнал смотрел на осциллографе.

  4. megger380:

    Добрый день! А возможно вообще переменный выход организовать с отрицательной полуволной?

  5. Нормальный:

    Здравствуйте, если бы Вы замерили данный синусоидальный сигнал на обычном осциллографе, то увидели бы что частота синусоиды не 26,7 кГц, а 13,33кГц. Реализованный вами счетчик clk_counter почему-то считает такты на частоте HCKL/2, при условии если у вас тоже HCLK=84МГц.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

*