alex1985 0 18 марта, 2018 Опубликовано 18 марта, 2018 (изменено) · Жалоба Добрый день всем участникам форума! Есть задача: выводить на ЦАП массив из 32-х значений данных в произвольное время (скажем в цикле или по нажатию кнопки). ЦАП настраивается на Normal mode, т.е. по задумке он должен один раз отработать массив данных и выключиться. Проблема в том, что данные выводятся только один (первый) раз при инициализации. Делаю так: //====================================================================== __HAL_RCC_DMA1_CLK_ENABLE(); __HAL_RCC_TIM4_CLK_ENABLE(); __HAL_RCC_DAC_CLK_ENABLE(); TIM4->PSC = 0; //Предделитель TIM4->ARR = 83; //Максимальное значение счетного регистра TIM4->CR2 = 0x0020; //MMS = Update TIM4->CR1 |= TIM_CR1_CEN; //Включаем таймер GPIO_InitStruct.Pin = GPIO_PIN_4; GPIO_InitStruct.Mode = GPIO_MODE_ANALOG; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); DAC->CR |= DAC_CR_DMAEN1; //разрешить прием данных канала №1 от ДМА DAC->CR |= DAC_CR_TSEL1_0|DAC_CR_TSEL1_2; //Timer 4 TRGO event DAC->CR |= DAC_CR_TEN1; DAC->CR |= DAC_CR_EN1; //включить канал 1 DMA1_Stream5->PAR = (uint32_t)&DAC1->DHR12R1; DMA1_Stream5->M0AR = (uint32_t)&Wave1[0]; DMA1_Stream5->NDTR = 32; DMA1_Stream5->CR|= DMA_SxCR_CHSEL_0|DMA_SxCR_CHSEL_1|DMA_SxCR_CHSEL_2; //DMA chanel 7 (согласно таблице "DMA1 request mapping" RM) DMA1_Stream5->CR|= DMA_SxCR_MSIZE_0; //Memory data size = Half-word (16 bit) DMA1_Stream5->CR|= DMA_SxCR_PSIZE_0; //Peripheral data size = Half-word (16 bit) DMA1_Stream5->CR|= DMA_SxCR_MINC; //Memory address pointer is incremented after each data transfer //DMA1_Stream5->CR|= DMA_SxCR_CIRC; //Circular mode DMA1_Stream5->CR|= DMA_SxCR_DIR_0; //Направление 01: Memory-to-peripheral DMA1_Stream5->CR|= DMA_SxCR_EN; //Enable DMA //====================================================================== И далее в программе так: while (1) { HAL_Delay(1000); DMA1_Stream5->CR&= ~DMA_SxCR_EN; //Disable DMA DMA1_Stream5->NDTR = 32; DMA1_Stream5->CR|= DMA_SxCR_EN; //Enable DMA } После первой инициализации данные выводятся, в цикле - не работает( Подозреваю, что не сбрасываю какой-то флаг. Заранее спасибо! Изменено 18 марта, 2018 пользователем Sprite Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 18 марта, 2018 Опубликовано 18 марта, 2018 · Жалоба Подозреваю, что не сбрасываю какой-то флаг. Да, неплохо бы перед инициализацией сбрасывать статус DMA, типа DMA2->LIFCR = (1 << DMA_LISR_HTIF0); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 191 18 марта, 2018 Опубликовано 18 марта, 2018 · Жалоба DMA1_Stream5->CR|= DMA_SxCR_CHSEL_0|DMA_SxCR_CHSEL_1|DMA_SxCR_CHSEL_2; //DMA chanel 7 (согласно таблице "DMA1 request mapping" RM) DMA1_Stream5->CR|= DMA_SxCR_MSIZE_0; //Memory data size = Half-word (16 bit) ... А зачем все эти чтения-модификации-записи??? Зачем читаете перед каждой операцией? Какой смысл? Причём ещё в много шагов. Если откроете мануал на МК, то увидите что никакие чтения для регистров CR (ни DMA ни DAC) не нужны. И записать в них всё необходимое можно одной командой записи. Потому и косяки что непонятно что туда пишете. К тому же не сбрасываете флаги состояний перед стартом операции. Вобщем: следует хотя-бы открыть мануал на МК и почитать описание регистров. Всех. #define timDac (&concat(TIMER, nTIM_dac)) #define timMp3 (&concat(TIMER, nTIM_hr)) #define dmaU ((nDMASTR_DAC >> 3) ? &DMA2: &DMA1) #define dmaS (&dmaU->STREAM[nDMASTR_DAC & 7]) ... timDac->DIER = timDac->CNT = timDac->PSC = timDac->CR[0] = 0; timDac->ARR = DAC_DIV - 1; timDac->EGR = B0; timDac->CR[1] = 2 << 4; __DMB(); DAC.CR = 0; DAC.SR = B13 | B29; DAC.CR = (B12 | B13) << concat(DAC_DMASTR, nDMASTR_DAC) * 16 | (B0 | B2 | concat(DAC_TIMER, nTIM_dac, _TRGO) << 3) * (B0 | B16); __DMB(); dmaU->IFCR[nDMASTR_DAC >> 2 & 1] = (B0 | B2 | B3 | B4 | B5) << (nDMASTR_DAC & 3) * 6 << (nDMASTR_DAC & B1) * 2; dmaS->PAR = (u32)&DAC.DHR12LD; dmaS->MAR[1] = dmaS->MAR[0] = (u32)&smplBuf.dummy[0]; dmaS->NDTR = DMA_CHUNK; dmaS->FCR = 3 << DMA_FCR_FTH | 1 << DMA_FCR_DMDIS; dmaS->CR = 1 << DMA_CR_EN | 1 << DMA_CR_TEIE | 1 << DMA_CR_TCIE | 1 << DMA_CR_DIR | 1 << DMA_CR_DBM | DMAPRI_DAC << DMA_CR_PL | 1 << DMA_CR_MINC | 2 << DMA_CR_PSIZE | 2 << DMA_CR_MSIZE | concat(DMAREQ_S, nDMASTR_DAC, _DAC, concat(DAC_DMASTR, nDMASTR_DAC)) << DMA_CR_CHSEL; PinSelN(tPinmuxAoutOn); ENTR_CRT_SECTION(); timMp3->CCR[0] = timMp3->CNT + mcs2clk(DAC_tWAKEUP, HrTimerCLK(H)); //по даташиту ждать после включения ЦАП >= tWAKEUP мкс timMp3->DIER = B1; EXIT_CRT_SECTION(); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
adnega 11 18 марта, 2018 Опубликовано 18 марта, 2018 · Жалоба Какой смысл? И не понятно зачем ТС смешивает работу через HAL и через регистры? Нужно выбрать что-то одно (только HAL). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
x893 40 18 марта, 2018 Опубликовано 18 марта, 2018 · Жалоба Видимо лень посмотреть примеры перед тем как код писать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alex1985 0 19 марта, 2018 Опубликовано 19 марта, 2018 · Жалоба x893 Видимо лень посмотреть примеры перед тем как код писать. И Вам хорошего дня) jcxz А зачем все эти чтения-модификации-записи??? Зачем читаете перед каждой операцией? Какой смысл? Причём ещё в много шагов.Понятно, что код инициализации ДМА можно уложить в 4 строки, записав числа в регистры PAR, M0AR, NDTR и CR. Я специально вынес каждый бит отдельно, чтобы было нагляднее. Тем более что процедура инициализации DMA выполняется один раз при старте, т.е. нет строгих временных требований к выполнению этого кода. следует хотя-бы открыть мануал на МК и почитать описание регистров. Так и сделал, прочитал внимательно пункт 1 10.3.17 Stream configuration procedure: All the stream dedicated bits set in the status register (DMA_LISR and DMA_HISR) from the previous data block DMA transfer should be cleared before the stream can be re-enabled. Стало более менее понятно. adnega, спасибо! Счастье есть) Добавил строчку DMA1->HIFCR|= DMA_HISR_HTIF5|DMA_HISR_TCIF5; и все заработало. В даташите также написано, что нужно после выключения DMA прочитать бит EN, т.е. проверить что он выключился. Ставить while как то "не спортивно") Подскажите как правильно? Надо ли проверять этот бит? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться