44 lines
2.3 KiB
C
44 lines
2.3 KiB
C
/*
|
||
* HAL-порт генератора STM32G474: DAC1, TIM6 и циклический DMA с 16-битными элементами.
|
||
* Проверяются конфигурация DMA и точная достижимость частоты, ограниченной 50 кГц; остановка
|
||
* выводит нулевой уровень без ожидания следующего триггера.
|
||
*/
|
||
|
||
#include "set_wave_g474.h"
|
||
static void stop(void *context) {
|
||
set_wave_g474 *c=(set_wave_g474 *)context;
|
||
HAL_TIM_Base_Stop(c->timer);
|
||
HAL_DAC_Stop_DMA(c->dac,DAC_CHANNEL_1);
|
||
/* Disable triggering so zero is applied without another timer edge. */
|
||
CLEAR_BIT(c->dac->Instance->CR,DAC_CR_TEN1);
|
||
HAL_DAC_SetValue(c->dac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,0);
|
||
HAL_DAC_Start(c->dac,DAC_CHANNEL_1);
|
||
}
|
||
static int start(void *context,const uint16_t *samples,size_t count,uint32_t rate) {
|
||
set_wave_g474 *c=(set_wave_g474 *)context;
|
||
uint32_t ticks,psc; DMA_HandleTypeDef *dma;
|
||
if(!c||!c->dac||!c->timer||c->dac->Instance!=DAC1||c->timer->Instance!=TIM6
|
||
||!rate||rate>50000||count<2||count>SET_WAVE_MAX||c->timer_hz%rate) return 1;
|
||
dma=c->dac->DMA_Handle1;
|
||
if(!dma||dma->Init.Mode!=DMA_CIRCULAR||dma->Init.MemDataAlignment!=DMA_MDATAALIGN_HALFWORD
|
||
||dma->Init.PeriphDataAlignment!=DMA_PDATAALIGN_HALFWORD
|
||
||dma->Init.Request!=DMA_REQUEST_DAC1_CHANNEL1||dma->Init.MemInc!=DMA_MINC_ENABLE) return 1;
|
||
ticks=c->timer_hz/rate;
|
||
for(psc=1;psc<=65536;++psc) if(ticks%psc==0&&ticks/psc<=65536) break;
|
||
if(psc>65536||ticks<psc) return 1;
|
||
stop(context);
|
||
__HAL_TIM_SET_PRESCALER(c->timer,psc-1);
|
||
__HAL_TIM_SET_AUTORELOAD(c->timer,ticks/psc-1);
|
||
__HAL_TIM_SET_COUNTER(c->timer,0);
|
||
c->timer->Instance->EGR=TIM_EGR_UG;
|
||
__HAL_TIM_CLEAR_FLAG(c->timer,TIM_FLAG_UPDATE);
|
||
MODIFY_REG(c->dac->Instance->CR,DAC_CR_TSEL1|DAC_CR_TEN1,DAC_TRIGGER_T6_TRGO);
|
||
HAL_DAC_SetValue(c->dac,DAC_CHANNEL_1,DAC_ALIGN_12B_R,samples[count-1]);
|
||
if(HAL_DAC_Start_DMA(c->dac,DAC_CHANNEL_1,(uint32_t *)samples,(uint32_t)count,DAC_ALIGN_12B_R)!=HAL_OK) return 1;
|
||
if(HAL_TIM_Base_Start(c->timer)!=HAL_OK) {stop(context);return 1;}
|
||
return 0;
|
||
}
|
||
set_wave_port set_wave_g474_port(set_wave_g474 *context) {
|
||
set_wave_port port={context,start,stop};return port;
|
||
}
|