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

Связка Dma+Dac. Подскажите Где Переполнение Переменной


qwasko1212

Рекомендуемые сообщения

Задача - генерация синуса.

Пробовал выводить синус через главный цикл, всё работает нормально. Но теперь мне нужно освободить АЛУ для других задач.

При использовании ПДП и Таймера происходит переполнение переменной, максимальное значение которое я могу вывести это 255, а мне нужна красивая синусоида построенная с большим (12 битным) разрешением.

Не могу найти в чём причина, перечитал кучу мануала по DMA, но всё же приходится обратится за помощью к свежему глазу, так как мой видимо замылился ))))

#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_tim.h"
#include "stm32f4xx_dma.h"
#include "stm32f4xx_dac.h"
#include "misc.h"
#include "math.h"
uint16_t sinus_4096[360], i, a;
uint8_t sinus_255[]={0,40,80,120,160,200,240,255,240,200,160,120,80,40,};

#define pi 3.14159
void GPIOInit (void )
{
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
GPIO_InitTypeDef DacOut1;
DacOut1.GPIO_Mode = GPIO_Mode_AN;
DacOut1.GPIO_OType = GPIO_OType_PP;
DacOut1.GPIO_Pin = GPIO_Pin_4;
DacOut1.GPIO_PuPd = GPIO_PuPd_NOPULL;
DacOut1.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOA, &DacOut1);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
GPIO_InitTypeDef led;
led.GPIO_Mode = GPIO_Mode_OUT;
led.GPIO_OType = GPIO_OType_PP;
led.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
led.GPIO_PuPd = GPIO_PuPd_NOPULL;
led.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_Init(GPIOD, &led);
}
void DACInit (void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE);
DAC_InitTypeDef DacSinus;
DAC_StructInit(&DacSinus);
DacSinus.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
DacSinus.DAC_Trigger = DAC_Trigger_T6_TRGO;
DacSinus.DAC_WaveGeneration = DAC_WaveGeneration_None;
DAC_Init(DAC_Channel_1, &DacSinus);
DAC_Cmd(DAC_Channel_1, ENABLE);
}
void TIMInit (void)
{
TIM_TimeBaseInitTypeDef x;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE);
x.TIM_CounterMode=TIM_CounterMode_Up;
x.TIM_Period=16000-1;
x.TIM_Prescaler=10-1;
TIM_TimeBaseInit(TIM6,&x);
TIM_SelectOutputTrigger(TIM6, TIM_TRGOSource_Update);
// TIM_DMACmd(TIM6, TIM_DMA_Update, ENABLE);
TIM_Cmd(TIM6,ENABLE);
}
void DMAInit(void)
{
DMA_InitTypeDef x;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1,ENABLE);
DMA_DeInit(DMA1_Stream5);
x.DMA_Channel=DMA_Channel_7;
x.DMA_PeripheralBaseAddr=(uint32_t)(DAC_BASE+0x10);
x.DMA_Memory0BaseAddr=(uint32_t)&sinus_4096;
x.DMA_DIR=DMA_DIR_MemoryToPeripheral;
x.DMA_BufferSize=sizeof(sinus_4096);
x.DMA_PeripheralInc=DMA_PeripheralInc_Disable;
x.DMA_MemoryInc=DMA_MemoryInc_Enable;
x.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;
x.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;
x.DMA_Mode=DMA_Mode_Circular;
x.DMA_Priority=DMA_Priority_High;
// x.DMA_FIFOMode=DMA_FIFOMode_Disable;
// x.DMA_FIFOThreshold=DMA_FIFOThreshold_HalfFull;
x.DMA_MemoryBurst=DMA_MemoryBurst_Single;
x.DMA_PeripheralBurst=DMA_PeripheralBurst_Single;
DMA_Init(DMA1_Stream5,&x);
DMA_Cmd(DMA1_Stream5,ENABLE);
DAC_DMACmd(DAC_Channel_1,ENABLE);
}
void Sinus_calculate()
{
for(i=0; i<360; i++)
{
sinus_4096[i] = (uint16_t) lround((sin(i*(pi/180)) + 1)*4095/2);
}
}
int main(void)
{
Sinus_calculate();
GPIOInit();
TIMInit();
DACInit();
DMAInit();

while(1)
{
// for(a=0; a<360; a++)
// {
// DAC_SetChannel1Data(DAC_Align_12b_R, Sinus[a]);
// }
}
}

Вот файл main.c main.zip.

Фотки с осциллографа.

post-186636-0-70539000-1449936286_thumb.jpg

post-186636-0-55271300-1449936288_thumb.jpg

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

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

  • 3 недели спустя...

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

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

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

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

При использовании ПДП и Таймера происходит переполнение переменной

какой именно переменной?

x.DMA_PeripheralBaseAddr=(uint32_t)(DAC_BASE+0x10);

вроде как у регистра этого конкретное имя есть и можно его без всяких костылей тут указать

sinus_4096 = (uint16_t) lround((sin(i*(pi/180)) + 1)*4095/2);

в каком порядке хранятся данные в этом массиве? Старший/младший? ДМА будет читать по порядку

дальше вопросы уже наводящие - в каком порядке ДМА запишет их в регистр DAC?

Пробовал и DMA_PeripheralDataSize_HalfWord

рекомендую вернуться именно к этой конструкции ибо

x.DMA_PeripheralInc=DMA_PeripheralInc_Disable;

так то все на первый взгляд настроено верно, но сам процесс подготовки и передачи данных вызывает вопросы.

И вообще на тему генерации синуса в сети куча готовых примеров. Велосипед изобретаете ИМХО

Изменено пользователем mail_robot

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

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

Какой именно переменной?

Это мои догадки,какой переменной я не знаю. Сигнал с осциллографа как бы намекает на переполнение. Когда я выводил данные масива c использованием CPU --> DAC, то такой проблемы не наблюдалось, значит можно сказать, что проблема в DMA.

вроде как у регистра этого конкретное имя есть и можно его без всяких костылей тут указать

Буду рад конкретике. :yes:

в каком порядке хранятся данные в этом массиве?

По возростанию начиная с 2048 и до 4095, потом по убыванию до 0 и опять по возрастанию до 2048, т.е мы имеем значения последовательно описывающие один период синуса.

в каком порядке ДМА запишет их в регистр DAC?

Думаю в том порядке в котором они расположены в массиве. Я ещё дописал функцию которая реализует 8 битный синус с максимальным значением в 255, так вот в этом случае выводится "красивый синус", а не его обрубки.

И вообще на тему генерации синуса в сети куча готовых примеров. Велосипед изобретаете ИМХО

Хочу построить частотный модулятор. В интернете примеров хватает, но не совсем того, что мне нужно.

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

когда я говорил про порядок, я имел в виду - будет ли старший байт в массиве соответствовать старшему байту в регистре. Они вполне ведь могут лечь в другом порядке. Или до этого было додуматься сложно даже по указке?

У меня пока все. Ваш кэп.

Изменено пользователем mail_robot

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

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

  • 1 месяц спустя...

x.DMA_PeripheralDataSize=DMA_PeripheralDataSize_Byte;

x.DMA_MemoryDataSize = DMA_PeripheralDataSize_Byte;

Сдается, в этих строчках ошибка...

Здесь имелось ввиду:

x.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

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

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.
Примечание: Ваш пост будет проверен модератором, прежде чем станет видимым.

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

Загрузка...
  • Последние посетители   0 пользователей онлайн

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

    • Да, с этим ИБП не надо так делать. Он не отключает питание платы управления при снижении напряжения аккумулятора ниже допустимого, а "кушает" она 0,1-0,3 А.
    • @Noctiss, корпус усилителя (GND) соединен с корпусом защиты? Минусовая клемма акустики на плате защиты с корпусом не соеденена.
    • Cкорее всего, при 31,5 В на выходе драйвер не выдаст 300 мА.  Хотя, раз заявлено входное от 100 В, то при 230 В может что-то и получится. Но это уже за заявленными пределами работы.  Можно подключить проволочный резистор 100 Ом и померить напряжение, но лучше использовать как заявлено: в диапазоне 12-20 В.  
    • @MisterAnderson , напряжение на выходе светодиодного драйвера зависит от нагрузки, и определяется оно напряжением на светодиодах, а не самим драйвером. Светодиоды имеют характеристику близкую к стабилитрону, напряжение на них от тока зависит мало. Белые светодиоды имеют это напряжение примерно 3...3,4 В. Четыре последовательно включённых - примерно 12...14 В. На подключение таких "трёхвольтовых" белых светодиодов и расчитан ваш драйвер. Драйвер напряжением не управляет, есть только ограничение по максимальному, больше которого он выдать не может. Драйвер светодиодов стабилизирует ток. Ваш драйвер стабилизирует его на уровне 0,3 А. И выдать больше 20 В при этом не может. Измеренные вами 31,5 В на холостом ходу - это напряжение его внутреннего питания. Под нагрузкой 0,3 А напряжение на его выходе тут же "просядет", выше 20 В не поднимется. Мощность на одном трёхвольтовом 300-миллиамперном светодиоде будет (примерно, для светодиодов точность никогда особо не обеспечивают) 0,3 А * 3,3 В = 1 Вт. Трёхвольтовый белый светодиод на ток 300 мА - это и есть одноваттный светодиод. На четырёх будет 4 ватта. Следующие по напряжению в линейке белых осветительных светодиодов - шестивольтовые. У них в одном корпусе последовательно соединённые два светодиодных кристалла. Четыре таких светодиода, включённых последовательно, ваш драйвер не потянет, потому что им нужно минимум 6*4=24 В, а ваш драйвер может выдать не больше 20. Впрочем, можно бы было поставить вместо четырёх трёхвольтовых четыре шестивольтовых на 150 мА, две группы параллельно по два последовательно, но вряд ли справитесь с переделкой платы под светодиоды. Поэтому этот вариант вам и не предлагали. Проще, дешевле и с наименьшими затратами собственного времени, без переделки драйвера, платы и т.п., с которой вы точно не справитесь, поставить четыре одноваттных трёхвольтовых, на которые ваш драйвер расчитан. Тем более, что купить их - проблем нет. Именно этот оптимальнейший совет вам и дали. Всё вам правильно уже много людей много раз разными словами рассказали. Что вас ещё смущает?
    • Предусилители-корректоры на полевых транзисторах. Радио №9,   №10/2010.  А.Гурский.
    • Тоже самое в подсветках фирменных телеках даже 10 летней давности. Ток можно уменьшить на треть без потери качества легко. Потребитель должен потреблять и всё тут.
×
×
  • Создать...