Миландр

Ключевым подразделением нашей компании является Центр Проектирования интегральных микросхем
Текущее время: 2018-янв-22 13:32

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 2 ] 
Автор Сообщение
 Заголовок сообщения: DMA и ADC
СообщениеДобавлено: 2017-ноя-28 20:29 
Не в сети

Зарегистрирован: 2016-ноя-27 13:56
Сообщения: 10
На форуме уже создано несколько таких тем, но ни в одной, мне так и не получилось найти ответа. Поэтому задам свой вопрос здесь. Пытаюсь настроить DMA, что бы можно было захватывать данные с 7 канала ADC1.(В последующем, надо будет расширить до 4 каналов, но сейчас бы с одним справится). Вот реализация функций и проект целиком.

Настройка таймера:
Код:
void Initialize_Timers (void)
{
    /* TIMER1 Configuration -------------------------------------------------  */
    RST_CLK_PCLKcmd(RST_CLK_PCLK_TIMER1, ENABLE);
    TIMER_DeInit(MDR_TIMER1);                                               // Deinitializes the TIMERx peripheral registers to their default reset values.
    TIMER_CntStructInit(&TIMER_CntInitStructure);                           // Fills each TIMER_CntInitStruct member with its default value.
    TIMER_CntInitStructure.TIMER_Prescaler = 0;
    TIMER_CntInitStructure.TIMER_Period = 148;                              // 56Mhz/12.5kbps/2 halfwave/3 chan/5 samples = 149,333
    TIMER_CntInit(MDR_TIMER1, &TIMER_CntInitStructure);                     // Initializes the TIMERx Counter peripheral according to the specified parameters in the TIMER_CntInitStruct.

    TIMER_BRGInit(MDR_TIMER1,TIMER_HCLKdiv1);                               /* Enable TIMER1 clock */
    TIMER_Cmd(MDR_TIMER1, ENABLE);                                          // Enables or disables the specified TIMER peripheral.

    TIMER_DMACmd(MDR_TIMER1, TIMER_STATUS_CNT_ARR, ENABLE);
}


Настройка АЦП:
Код:
void Initialize_ADC (void)
{
    /* ADC Configuration */
    RST_CLK_PCLKcmd(RST_CLK_PCLK_ADC,ENABLE);
    /* Reset all ADC settings */
    ADC_DeInit();
    ADC_StructInit(&sADC);

    sADC.ADC_SynchronousMode      = ADC_SyncMode_Independent;
    sADC.ADC_StartDelay           = 0;
    sADC.ADC_IntVRefConversion    = ADC_VREF_CONVERSION_Disable;
    sADC.ADC_IntVRefTrimming      = 1;
    ADC_Init (&sADC);

    /* ADC1 Configuration */
    ADCx_StructInit (&sADCx);
    sADCx.ADC_ClockSource      = ADC_CLOCK_SOURCE_CPU;
    sADCx.ADC_SamplingMode     = ADC_SAMPLING_MODE_SINGLE_CONV;
    sADCx.ADC_ChannelSwitching = ADC_CH_SWITCHING_Enable;
    sADCx.ADC_Channels         = ADC_CH_ADC7_MSK/*ADC_CH_ADC0_MSK | ADC_CH_ADC1_MSK | ADC_CH_ADC2_MSK*/;
    sADCx.ADC_LevelControl     = ADC_LEVEL_CONTROL_Disable;
    sADCx.ADC_LowLevel         = 0;
    sADCx.ADC_HighLevel        = 0;
    sADCx.ADC_VRefSource       = ADC_VREF_SOURCE_INTERNAL;
    sADCx.ADC_IntVRefSource    = ADC_INT_VREF_SOURCE_INEXACT;
    sADCx.ADC_Prescaler        = ADC_CLK_div_4;
    sADCx.ADC_DelayGo          = 6;
    ADC1_Init (&sADCx);

    /* Enable ADC1 EOCIF and AWOIFEN interupts */
    ADC1_ITConfig((ADCx_IT_END_OF_CONVERSION  | ADCx_IT_OUT_OF_RANGE), DISABLE);

    /* ADC1 enable */
    ADC1_Cmd (ENABLE);
}


Настройка DMA:
Код:
void DMA_Init1(void)
{
    RST_CLK_PCLKcmd((RST_CLK_PCLK_RST_CLK | RST_CLK_PCLK_DMA | RST_CLK_PCLK_ADC),ENABLE);
    RST_CLK_PCLKcmd((RST_CLK_PCLK_SSP1 | RST_CLK_PCLK_SSP2),ENABLE);

    NVIC_ClearPendingIRQ(DMA_IRQn);

    /* Disable all interrupt */
    NVIC->ICPR[0] = 0xFFFFFFFF;
    NVIC->ICER[0] = 0xFFFFFFFF;

    /* DMA ADC1 */
    DMA_StructInit(&DMA_InitStr);
    /* Set Primary Control Data */
    DMA_PriCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&(MDR_ADC->ADC1_RESULT));
    DMA_PriCtrlStr.DMA_DestBaseAddr = (uint32_t)&ADCConvertedValue[0];
    DMA_PriCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo;
    DMA_PriCtrlStr.DMA_DestIncSize = /*DMA_DestIncHalfword*/DMA_DestIncNo;
    DMA_PriCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_PriCtrlStr.DMA_Mode = DMA_Mode_PingPong;
    DMA_PriCtrlStr.DMA_CycleSize = ADC_BUFFER/2;
    DMA_PriCtrlStr.DMA_NumContinuous = DMA_Transfers_1;
    DMA_PriCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged;
    DMA_PriCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged;

    /* Set Alternate Control Data */
    DMA_AltCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&(MDR_ADC->ADC1_RESULT));
    DMA_AltCtrlStr.DMA_DestBaseAddr   = (uint32_t)&ADCConvertedValue[ADC_BUFFER/2];
    DMA_AltCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo;
    DMA_AltCtrlStr.DMA_DestIncSize = /*DMA_DestIncHalfword*/DMA_DestIncNo;
    DMA_AltCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_AltCtrlStr.DMA_Mode = DMA_Mode_PingPong;
    DMA_AltCtrlStr.DMA_CycleSize = ADC_BUFFER/2;
    DMA_AltCtrlStr.DMA_NumContinuous = DMA_Transfers_1;
    DMA_AltCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged;
    DMA_AltCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged;

    /* Set Channel Structure */
    DMA_InitStr.DMA_PriCtrlData = &DMA_PriCtrlStr;
    DMA_InitStr.DMA_AltCtrlData = &DMA_AltCtrlStr;
    DMA_InitStr.DMA_Priority = DMA_Priority_Default;
    DMA_InitStr.DMA_UseBurst = DMA_BurstClear;
    DMA_InitStr.DMA_SelectDataStructure = DMA_CTRL_DATA_PRIMARY;

    /* Init DMA channel ADC1 */
    DMA_Init(DMA_Channel_ADC1, &DMA_InitStr);

    /* Enable dma_req or dma_sreq to generate DMA request */
    MDR_DMA->CHNL_REQ_MASK_CLR = (1<<DMA_Channel_ADC1);
    MDR_DMA->CHNL_USEBURST_CLR = (1<<DMA_Channel_ADC1);

    /* Enable DMA channel ADC1 */
    DMA_Cmd(DMA_Channel_ADC1, ENABLE);

    /* DMA Timer1 */
    /* Set Primary Control Data */
    DMA_PriCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&ADC_Go);
    DMA_PriCtrlStr.DMA_DestBaseAddr = (uint32_t)(&(MDR_ADC->ADC1_CFG));
    DMA_PriCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo;
    DMA_PriCtrlStr.DMA_DestIncSize = DMA_DestIncNo;
    DMA_PriCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    DMA_PriCtrlStr.DMA_Mode = DMA_Mode_PingPong;
    DMA_PriCtrlStr.DMA_CycleSize = ADC_BUFFER/2;
    DMA_PriCtrlStr.DMA_NumContinuous = DMA_Transfers_1;
    DMA_PriCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged;
    DMA_PriCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged;

    /* Set Alternate Control Data */
    DMA_AltCtrlStr.DMA_SourceBaseAddr = (uint32_t)(&ADC_Go);
    DMA_AltCtrlStr.DMA_DestBaseAddr   = (uint32_t)(&(MDR_ADC->ADC1_CFG));
    DMA_AltCtrlStr.DMA_SourceIncSize = DMA_SourceIncNo;
    DMA_AltCtrlStr.DMA_DestIncSize = DMA_DestIncNo;
    DMA_AltCtrlStr.DMA_MemoryDataSize = DMA_MemoryDataSize_Word;
    DMA_AltCtrlStr.DMA_Mode = DMA_Mode_PingPong;
    DMA_AltCtrlStr.DMA_CycleSize = ADC_BUFFER/2;
    DMA_AltCtrlStr.DMA_NumContinuous = DMA_Transfers_1;
    DMA_AltCtrlStr.DMA_SourceProtCtrl = DMA_SourcePrivileged;
    DMA_AltCtrlStr.DMA_DestProtCtrl = DMA_DestPrivileged;

    /* Set Channel Structure */
    DMA_InitStr.DMA_PriCtrlData = &DMA_PriCtrlStr;
    DMA_InitStr.DMA_AltCtrlData = &DMA_AltCtrlStr;
    DMA_InitStr.DMA_Priority = DMA_Priority_Default;
    DMA_InitStr.DMA_UseBurst = DMA_BurstClear;
    DMA_InitStr.DMA_SelectDataStructure = DMA_CTRL_DATA_PRIMARY;

    /* Init DMA channel Timer1 */
    DMA_Init(DMA_Channel_TIM1, &DMA_InitStr);

    /* Enable dma_req or dma_sreq to generate DMA request */
    MDR_DMA->CHNL_REQ_MASK_CLR = (1<<DMA_Channel_TIM1);
    MDR_DMA->CHNL_USEBURST_CLR = (1<<DMA_Channel_TIM1);

    /* Enable DMA channel Timer1 */
    DMA_Cmd(DMA_Channel_TIM1, ENABLE);

    // Задать приоритет аппаратного прерывания от DMA
    NVIC_SetPriority (DMA_IRQn, 3);

    // Разрешить прерывания от DMA
    NVIC_EnableIRQ(DMA_IRQn);

    Initialize_Timers();
    Initialize_ADC();

    /**/
    MDR_DMA->CHNL_REQ_MASK_SET |= 0xFFFF;
    MDR_DMA->CHNL_ENABLE_SET  |= 0xFFFF;
    MDR_DMA->CHNL_REQ_MASK_CLR |= 0x07;
}


Обработчик DMA:
Код:
void DMA_IRQHandler(void)
{
    NVIC_ClearPendingIRQ(DMA_IRQn);
    if((MDR_DMA->CHNL_PRI_ALT_SET & (1<<DMA_Channel_ADC1)) == (0<<DMA_Channel_ADC1))
    {
        DMA_ControlTable[DMA_Channel_ADC1+32].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong;
        DMA_ControlTable[DMA_Channel_TIM1+32].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong;


    }
    else if((MDR_DMA->CHNL_PRI_ALT_SET & (1<<DMA_Channel_ADC1)) == (1<<DMA_Channel_ADC1))
    {
        DMA_ControlTable[DMA_Channel_ADC1].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong;
        DMA_ControlTable[DMA_Channel_TIM1].DMA_Control |= ((ADC_BUFFER/2 - 1) << 4) | DMA_Mode_PingPong;

    }
}


После запуска программы, постоянно крутится в обработчике. В чем дело ума не приложу. Бьюсь уже 2-ую неделю. Очень рассчитываю на вашу помощь. Камень - 1986ВЕ94Т. Среда - CodeMasterArm.


Вложения:
DMA_ADC.rar [277 КБ]
Скачиваний: 10
Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: DMA и ADC
СообщениеДобавлено: 2018-янв-16 14:06 
Не в сети

Зарегистрирован: 2016-мар-17 13:22
Сообщения: 6
Возможно, поможет код обработки прерывания DMA, взятый на стр.101 из книги А.В.Благодарова " Программирование микроконтроллеров семейства 1986ВЕ9Х компании Миландр". "В контакте" на страничке автора была ссылка на книгу.
Код:
//Обработчик для прерываний от DMA
void DMA_IRQHandler (void)
{
// Подготовить к работе новый цикл преобразований
DMA_InitStructure.DMA_CycleSize = U_ADC_BUFFER_SIZE;
DMA_Init (DMA_Channel_ADC1,
                 &DMA_Channel_InitStructure);
// Запретить дальнейшую работу канала DMA c ADC
DMA_Cmd (DMA_Channel_ADC1, DISABLE);
// Установить событие об окончании цикла
// аналого-цифровых преобразований
isr_evt_set (EVENT_ADC_EOC, U_ADC_Tack_ID);
}


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 2 ] 

Часовой пояс: UTC + 3 часа


Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 4


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Перейти:  
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB