16.03.2022, 14:09
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.12.2007
Сообщений: 1,198
Сказал спасибо: 70
Сказали Спасибо 80 раз(а) в 69 сообщении(ях)
|
Сообщение от andries5
|
Но ведь можно источник указать не имя регистра, а его адрес в памяти.
#define ADC1_DR_ADDRESS 0x50000040
|
Надо попробовать.
В общем вот какая проблема. Когда объявляю функцию
HAL_ADC_Start_DMA(&hadc1, buf_adc, 0);
работа в основном цикле программы while(1) вообще зависает.
Код:
|
#include "main.h"
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
TIM_HandleTypeDef htim3;
DMA_HandleTypeDef hdma_tim3_ch1_trig;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM3_Init(void);
uint32_t buf_adc[1];
uint32_t buf_tim3[1]={100};
uint8_t pin_pc4;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_TIM3_Init();
HAL_ADC_Start_DMA(&hadc1, buf_adc, 0);
HAL_TIM_PWM_Start_DMA(&htim3, TIM_CHANNEL_1, buf_tim3,0);
while (1)
{
buf_tim3[0]++;
HAL_Delay(1);
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, pin_pc4=~pin_pc4);
} |
если не объявлять HAL_ADC_Start_DMA(&hadc1, buf_adc, 0); то регистр в TIM3 через DMA и переменную buf_tim3[0]++; работает, так же смотрю работу программы по выводу порта B.
Последний раз редактировалось mike-y-k; 16.03.2022 в 14:26.
Причина: 6.6
|
|
|
|
16.03.2022, 14:22
|
|
Супер-модератор
Регистрация: 15.10.2007
Сообщений: 3,529
Сказал спасибо: 172
Сказали Спасибо 1,560 раз(а) в 810 сообщении(ях)
|
Re: DMA в STM32F4 из ADC в PWM.
Сообщение от andries5
|
Но ведь можно источник указать не имя регистра, а его адрес в памяти.
|
Вы что думаете в регистры адресов источник-назначение ДМА имена записываются? Там в любом случае адрес. Просто в ручном режиме я думаю будет работать, а вот в автоматическом, когда периферия управляет транзакцией ДМА нет, так как в режиме память-память только ручное управление. Видите там в таблице для режима память-память в столбце Flow Control написано DMA only.
|
|
|
|
16.03.2022, 14:25
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.12.2007
Сообщений: 1,198
Сказал спасибо: 70
Сказали Спасибо 80 раз(а) в 69 сообщении(ях)
|
Re: DMA в STM32F4 из ADC в PWM.
Сообщение от andries5
|
Но ведь можно источник указать не имя регистра, а его адрес в памяти.
#define ADC1_DR_ADDRESS 0x50000040
|
Наверное нужно в кубеке выбрать память -› память
и уже из адреса в адрес проганять данные через DMA. Правельно я думаю?
|
|
|
|
16.03.2022, 14:28
|
|
Супер-модератор
Регистрация: 15.10.2007
Сообщений: 3,529
Сказал спасибо: 172
Сказали Спасибо 1,560 раз(а) в 810 сообщении(ях)
|
Re: DMA в STM32F4 из ADC в PWM.
vavan1983, вы так и не ответили. Что вы хотите. Как я понял вам нужно сделать следующее, по окончании преобразования АЦП дает сигнал ДМА на перенос данных в общую переменную, а таймер по своему событию дает сигнал ДМА на перенос из общей переменной в регистр скважности ШИМ? Все это идет без участия процессора.
|
|
|
|
16.03.2022, 15:04
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.12.2007
Сообщений: 1,198
Сказал спасибо: 70
Сказали Спасибо 80 раз(а) в 69 сообщении(ях)
|
Нужно результаты преобразования АЦП передать через ДМА в регистр скважности TIM3 без участия АЦП. Как то так.
Как только срабатывает преобразование АЦП по таймеру тут же МК зависает. Если запустить преобразования АЦП без ДМА то не зависает.
Последний раз редактировалось mike-y-k; 16.03.2022 в 15:34.
Причина: 6.6
|
|
|
|
16.03.2022, 16:32
|
|
Супер-модератор
Регистрация: 15.10.2007
Сообщений: 3,529
Сказал спасибо: 172
Сказали Спасибо 1,560 раз(а) в 810 сообщении(ях)
|
Re: DMA в STM32F4 из ADC в PWM.
Сообщение от vavan1983
|
Нужно результаты преобразования АЦП передать через ДМА в регистр скважности TIM3 без участия АЦП.
|
Без участия АЦП это как?
У вас что-то настроено неправильно.
В общем то, что я писал выше прекрасно работает без участия процессора.
Цитата:
|
по окончании преобразования АЦП дает сигнал ДМА на перенос данных в общую переменную, а таймер по своему событию дает сигнал ДМА на перенос из общей переменной в регистр скважности ШИМ
|
|
|
|
|
16.03.2022, 16:40
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.12.2007
Сообщений: 1,198
Сказал спасибо: 70
Сказали Спасибо 80 раз(а) в 69 сообщении(ях)
|
Re: DMA в STM32F4 из ADC в PWM.
Без участия процессора. Запутался в формулировках.
|
|
|
|
16.03.2022, 16:56
|
|
Супер-модератор
Регистрация: 15.10.2007
Сообщений: 3,529
Сказал спасибо: 172
Сказали Спасибо 1,560 раз(а) в 810 сообщении(ях)
|
andries5, вы правы. ДМА может напрямую результат АЦП в регистр таймера переносить.
vavan1983, где у вас настройки ДМА и АЦП? У АЦП должно быть включен режим работы ДМА(регистр CR2 бит DMA) и он должен быть настроен на постоянное преобразование. У ДМА источник адрес регистра DR АЦП, адрес назначения регистр CCR1, режим периферия-›память, без инкремента, без ФИФО и включен режим управления периферией(в регистре DMA_SxCR бит PFCTRL: Peripheral flow controller).
Последний раз редактировалось realid; 16.03.2022 в 17:02.
|
|
|
|
16.03.2022, 19:28
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.12.2007
Сообщений: 1,198
Сказал спасибо: 70
Сказали Спасибо 80 раз(а) в 69 сообщении(ях)
|
Re: DMA в STM32F4 из ADC в PWM.
Извеняйте не предупредил. Пишу в STM32cubeIDE, данный код что выше урезал так как если вываливать весь то там столько шелухи до не приличия.
Я только начал осваивать данный продукт так что не пинайте.
Последний раз редактировалось mike-y-k; 17.03.2022 в 20:08.
Причина: 7.15
|
|
|
|
17.03.2022, 22:14
|
|
Почётный гражданин KAZUS.RU
Регистрация: 26.12.2007
Сообщений: 1,198
Сказал спасибо: 70
Сказали Спасибо 80 раз(а) в 69 сообщении(ях)
|
Re: DMA в STM32F4 из ADC в PWM.
В общем можно спокойно использовать одну переменную для TIM3 и ADC. Получается прям прямой проброс данных из АЦП в регистр таймера без за действия АЛУ.
Классная штука эта DMA да ещё и FIFO есть, теперь АЛУ можно отдать работу только над вычислениями.
Код:
|
#include "main.h"
ADC_HandleTypeDef hadc1;
DMA_HandleTypeDef hdma_adc1;
TIM_HandleTypeDef htim3;
DMA_HandleTypeDef hdma_tim3_ch1_trig;
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM3_Init(void);
uint16_t pwm[1]={500};
uint16_t adc[1];
uint8_t i=0;
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
if(hadc-›Instance == ADC1) //check if the interrupt comes from ACD1
{
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc,1);
}
}
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_ADC1_Init();
MX_TIM3_Init();
HAL_TIM_PWM_Start_DMA(&htim3,TIM_CHANNEL_1,(uint32_t*)pwm,1);
HAL_ADC_Start_DMA(&hadc1,(uint32_t*)adc,1);
while (1)
{
pwm[0]=adc[0];
}
}
void SystemClock_Config(void)
{
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
__HAL_RCC_PWR_CLK_ENABLE();
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLT AGE_SCALE1);
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 50;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 4;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV4;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
}
static void MX_ADC1_Init(void)
{
ADC_AnalogWDGConfTypeDef AnalogWDGConfig = {0};
ADC_ChannelConfTypeDef sConfig = {0};
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = DISABLE;
hadc1.Init.ContinuousConvMode = DISABLE;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISINGFALLING;
hadc1.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_T3_TRGO;
hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc1.Init.NbrOfConversion = 1;
hadc1.Init.DMAContinuousRequests = DISABLE;
hadc1.Init.EOCSelection = ADC_EOC_SEQ_CONV;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the analog watchdog
*/
AnalogWDGConfig.WatchdogMode = ADC_ANALOGWATCHDOG_SINGLE_REG;
AnalogWDGConfig.HighThreshold = 0;
AnalogWDGConfig.LowThreshold = 0;
AnalogWDGConfig.Channel = ADC_CHANNEL_0;
AnalogWDGConfig.ITMode = DISABLE;
if (HAL_ADC_AnalogWDGConfig(&hadc1, &AnalogWDGConfig) != HAL_OK)
{
Error_Handler();
}
/** Configure for the selected ADC regular channel its corresponding rank in the sequencer and its sample time.
*/
sConfig.Channel = ADC_CHANNEL_0;
sConfig.Rank = 1;
sConfig.SamplingTime = ADC_SAMPLETIME_3CYCLES;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
static void MX_TIM3_Init(void)
{
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 4095;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
{
Error_Handler();
}
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
{
Error_Handler();
}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
{
Error_Handler();
}
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 1;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN TIM3_Init 2 */
/* USER CODE END TIM3_Init 2 */
HAL_TIM_MspPostInit(&htim3);
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Stream4_IRQn);
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
}
static void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
__HAL_RCC_GPIOC_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);
/*Configure GPIO pin : PC13 */
GPIO_InitStruct.Pin = GPIO_PIN_13;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
None
*/
void Error_Handler(void)
{
__disable_irq();
while (1)
{
}
}
#ifdef USE_FULL_ASSERT
void assert_failed(uint8_t *file, uint32_t line)
{
}
#endif /* USE_FULL_ASSERT */ |
Вот только не пойму как ЦП синхронизируется с DMA автоматически что ли?
|
|
|
|
Ваши права в разделе
|
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения
HTML код Выкл.
|
|
|
Часовой пояс GMT +4, время: 22:11.
|
|