Skip to main content
Explorer II
December 11, 2024
Question

Can the array DAC DMA for signals be controlled?

  • December 11, 2024
  • 2 replies
  • 670 views

I generated a sinusoidal signal through the DAC using DMA. I understand that DMA performs looping since I use circular mode. In short, I want to control the numbers generated by the DMA. So, when the signal changes to DC (the array contains only 2048 or hold_samples and hold_samples2), it will immediately be detected by my program using the function:

 

 

deteksisinyal(void)

 

 

 However, I have NOT yet figured out how to control the numbers/results/shape of the generated signal in terms of code. I want to control the signal changes, namely from peak - flat - valley - flat. I will use the flat part for another function, specifically to detect changes in a device. Please, I need help from experts with examples or guidance on what I should do. I will include my code below. Please provide feedback or ask questions about my code.

 

 

// DAC SIGNAL GENERATOR	
#define VALUE_SIZE 557
uint16_t value[VALUE_SIZE] = {};
uint16_t hold_samples = 30; 
uint16_t hold_samples2 = 400;
	
uint16_t firstHalf[] = {
2100, 2249, 2450, 2646, 2834, 3018, 3188, 3351, 3503, 3636, 3755, 3860, 3944, 4012, 4095, 
4058, 4012, 3944, 3860, 3755, 3636, 3503, 3351, 3188, 3018, 2834, 2646, 2450, 2249, 2100
}; 	

uint16_t secondHalf[] = {
1997, 1847, 1702, 1562, 1427, 1297, 1172, 1052, 900, 722, 622, 527, 437, 352, 272, 197, 100, 
0, 100, 197, 272, 352, 437, 527, 622, 722, 900, 1052, 1172, 1297, 1427, 1562, 1700, 1850, 2000
}; 	

// ADC SIGNAL GENERATOR
uint16_t totalSize;
uint16_t sum_signal = 0;
uint16_t filtered_input; //ngantuk bgt ya lord
void generate_signal() {
	uint16_t index = 0;
	for (uint16_t i = 0; i < sizeof(firstHalf) / sizeof(firstHalf[0]); i++) {
			value[index++] = firstHalf[i];
	}
 for (uint16_t i = 0; i < hold_samples; i++) {
			value[index++] = 2048;
	}
	for (uint16_t i = 0; i < sizeof(secondHalf) / sizeof(secondHalf[0]); i++) {
			value[index++] = secondHalf[i];
	}
	for (uint16_t i = 0; i < hold_samples2; i++) {
			value[index++] = 2048;
	}
	totalSize = (sizeof(firstHalf) / sizeof(firstHalf[0])) + hold_samples + (sizeof(secondHalf) / sizeof(secondHalf[0]))+ hold_samples2;
	HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)value, totalSize, DAC_ALIGN_12B_R);
}

uint32_t cnt=0;
uint16_t input_start = 0; 
uint32_t input_end = 4095; 
uint16_t output_start = 25;
uint16_t output_end = 3900;
uint16_t newArray = 2048;
uint16_t input;
uint16_t hasil;
uint16_t i;
uint16_t y;
uint16_t x;
uint16_t newArray;

void signal_function(){
	
		input = adc_buffer[1];
		cnt++;
		if (cnt > 15)
		{
			filtered_input = sum_signal / 15;
			sum_signal=0;
			cnt=0;
			
			hasil = output_start + ((output_end - output_start) * (filtered_input - input_start)) / (input_end - input_start); 
			__HAL_TIM_SET_AUTORELOAD(&htim4, hasil);
			__HAL_TIM_SET_COMPARE(&htim4, TIM_CHANNEL_1, hasil);
			y = hasil;
			x = input;
		}
		else 
			sum_signal += input;
}

void deteksisinyal(void){
//how to detect the DC signallllll
}

 

 

and the shape of the signal is as follows: and the shape of the signal is as follows:and the shape of the signal is as follows:

Is it possible? I need your help.

@TDK @ST_Employee_AME 

    This topic has been closed for replies.

    2 replies

    Graduate II
    December 11, 2024

    Hi you with DMA require add and use complete callbacks interrupts. Then after half buff is complete you change first half ... or double buffer or more with prepare and switch on full complete...

    macam1Author
    Explorer II
    December 11, 2024

    thakn u so much for your response but i have any question:

     

    Can I see when my DC signal starts to form using that method?
    I know which array index it starts to become DC, but I can’t control it because I’m confused. Could you explain further?

    Graduate II
    December 11, 2024

    Enable IRQ and some on your stream used... only example code

    void DMA1_Stream5_IRQHandler(void)
    {
    /* Test on DMA Stream Half Transfer interrupt */
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_HTIF5)) {
    /* Clear DMA Stream Half Transfer interrupt pending bit */
    DMA_ClearITPendingBit(DMA1_Stream5, DMA_IT_HTIF5);
    /* Add code to process First Half of Buffer */
    }
    
    /* Test on DMA Stream Transfer Complete interrupt */
    if (DMA_GetITStatus(DMA1_Stream5, DMA_IT_TCIF5)) {
    /* Clear DMA Stream Transfer Complete interrupt
    * pending bit */
    DMA_ClearITPendingBit(DMA1_Stream5,DMA_IT_TCIF5);
    /* Add code to process Second Half of Buffer
    * */
    }
    Super User
    December 12, 2024

    Use a single array to store all values. Splitting it up into a first half + hold + second half + hold isn't congruent with how DMA operates. All values need to be in contiguous memory (ignoring double buffer mode, which is out of scope here).