TransWikia.com

Why does my sine wave signal look like this with a 20kHz sampling rate?

Electrical Engineering Asked on November 17, 2021

its been a while. Back at it again with another question.

My ADC sampling rate is set to 20kHZ. I took pictures of the ouput DAC at three different frequencies

  1. at 770Hz * 2 = 1540Hz (Nyquist Frequency)
  2. at 10Hz * 2 = 20Hz (Nyquist Frequency)
  3. at 58Hz * 2 = 116Hz (Nyquist Frequency)

I am sampling at 20kHz, thats higher than all these nyquist frequency but yet anything higher than 10Hz gives me some sort of aliasing or distortion, I have no idea. I am using the STM32L432KC has the MCU if that matters

Yellow is the DAC output.

Any ideas what might be going on?

enter image description here
Frequency = 770Hz

Amplitude = 1.00Vpp

Offset = 1.00V
enter image description here
Frequency = 10Hz

Amplitude = 1.00Vpp

Offset = 1.00V
enter image description here
Frequency = 58Hz

Amplitude = 1.00Vpp

Offset = 1.00V

enter image description here
Essentially, I have it that every rising edge output 10000 samples. Thats why I zoomed in so you can see the wave that outputs within 0.5ms.

Code:

    #include "main.h"
#include <stdint.h>

void init_Interrupt(void);
void init_Clock(void);
void init_Interrupt(void);
void init_DAC(void);
void init_ADC(void);
void init_GPIO_Test(void);
void init_Debug(void);
void print_ADC(short);

char buffer[20] = "ADC Value:     nr";

typedef struct PLL{
    uint8_t PLLN;
    uint8_t PLLR;
    uint8_t PLLM;
    uint8_t PLLSAI1N;
    uint8_t PLLSAI1R;
} PLL;

PLL find_PLL(uint32_t, uint32_t);
PLL CFGR;

uint8_t escape = 0;
uint8_t half_transfer_complete = 0;
uint8_t transfer_complete = 0;
uint32_t PLLN_MAX = 86;
uint32_t PLLSAI1N_MAX = 86;
uint32_t PLLR_MAX = 8;
uint32_t PLLSAI1R_MAX = 8;
uint32_t PLLM_MAX = 8;
uint32_t CPU_Speed = 80000000;
uint32_t ADC_Speed = 13000000;
uint16_t ADC_Value[20000]; // Samples

void DMA2_Channel3_IRQHandler(void){

    if (((DMA2->ISR) & (DMA_ISR_HTIF3)) != 0){
        half_transfer_complete = 1;
        DMA2->IFCR |= DMA_IFCR_CHTIF3;
    } else if (((DMA2->ISR) & (DMA_ISR_TCIF3)) != 0){
        transfer_complete = 1;
        DMA2->IFCR |= DMA_IFCR_CTCIF3;
    }
}

int main(void) {

  init_Clock();
  //init_Debug();
  init_ADC();
  init_DAC();
  init_GPIO_Test();
  init_Interrupt();

    while (1) {

            if (half_transfer_complete == 1){
                GPIOA->BSRR |= GPIO_BSRR_BS0;
                for (int i = 0; i < 10000; i++){
                    DAC1->DHR12R1 = ADC_Value[i];
                }

                half_transfer_complete = 0;
            }

            if (transfer_complete == 1){
                GPIOA->BSRR |= GPIO_BSRR_BR0;

                transfer_complete = 0;
            }
    };
}

PLL find_PLL(uint32_t CPU_Speed, uint32_t ADC_Speed) {

    PLL settings;

     for (int PLLN = 8; PLLN <= PLLN_MAX; PLLN ++){
        if (escape == 1){
            break;
        }
         for (int PLLM = 1; PLLM <= PLLM_MAX; PLLM ++){
             if (escape == 1){
                 break;
             }
            for (int PLLR = 2; PLLR <= PLLR_MAX ; PLLR +=2){
                if ((((4000000/PLLM) * PLLN) >= 64000000) & (((4000000/PLLM) * PLLN) <= 344000000)){
                    if (((4000000/PLLM) >= 4000000) & ((4000000/PLLM) <= 16000000)) {
                        if (((((4000000/PLLM)*PLLN)/PLLR) >= 8000000) & ((((4000000/PLLM)*PLLN)/PLLR) <= 80000000)){
                           uint32_t PLL_CALC = (((4000000/PLLM)*PLLN)/PLLR);
                            if (PLL_CALC == CPU_Speed){
                              settings.PLLM = PLLM;
                              settings.PLLR = PLLR;
                              settings.PLLN = PLLN;
                              escape = 1;
                              break;
                            }
                        }
                    }
                }

                }
            }
        }

        escape = 0;

        for (int PLLSAI1N = 8; PLLSAI1N <= PLLSAI1N_MAX; PLLSAI1N ++){
            if (escape == 1){
                 break;
        }
            for (int PLLSAI1R = 2; PLLSAI1R <= PLLSAI1R_MAX; PLLSAI1R += 2){
                if ((((4000000/settings.PLLM) * PLLSAI1N) >= 64000000) & (((4000000/settings.PLLM) * PLLSAI1N) <= 344000000)){
                   if (((((4000000/settings.PLLM)*PLLSAI1N)/PLLSAI1R) >= 8000000) & ((((4000000/settings.PLLM)*PLLSAI1N)/PLLSAI1R) <= 80000000)){
                       uint32_t PLLSAI1_CALC = (((4000000/settings.PLLM)*PLLSAI1N)/PLLSAI1R);
                       if (PLLSAI1_CALC == ADC_Speed){
                        settings.PLLSAI1R = PLLSAI1R;
                        settings.PLLSAI1N = PLLSAI1N;
                        escape = 1;
                        break;
                    }
                   }

                }
            }
          }
                return settings;
        }

void init_ADC(){

        RCC -> AHB2ENR |= RCC_AHB2ENR_GPIOAEN | RCC_AHB2ENR_ADCEN;
        RCC -> AHB1ENR |= RCC_AHB1ENR_DMA2EN;
        RCC -> CCIPR |= RCC_CCIPR_ADCSEL_1;

        GPIOA -> MODER &= ~GPIO_MODER_MODE7;
        GPIOA -> MODER |=  GPIO_MODER_MODE7_Analog; //PIN A6

        // |------------------- ADC VALUE ----------------------|
        // 16-bit @ 44.1kHZ
        // 16-bit = 2 byte * 20khz =  40 kB
        DMA2_Channel3 -> CCR |= (DMA_CCR_PSIZE_16_Bit) |
                              (DMA_CCR_MSIZE_16_Bit)   |
                              (DMA_CCR_MINC)           |
                              (DMA_CCR_CIRC)           |
                              (DMA_CCR_TCIE)           |
                              (DMA_CCR_HTIE)           |
                              (DMA_CCR_PL_Very_High);
        DMA2_CSELR -> CSELR &= ~DMA_CSELR_C3S;
        DMA2_Channel3 -> CNDTR |= 0x4E20;
        DMA2_Channel3 -> CMAR = (uint32_t)ADC_Value; //Memory Address
        DMA2_Channel3 -> CPAR = (uint32_t)&ADC1->DR; //Peripheral Addres
        DMA2_Channel3 -> CCR |= DMA_CCR_EN;

        ADC1 -> CR &= ~ADC_CR_DEEPPWD;
        ADC1 -> CR |= ADC_CR_ADVREGEN;
        ADC1 -> CR &= ~ADC_CR_ADCALDIF;
        ADC1 -> CR |= ADC_CR_ADCAL;
        while((ADC1->CR & ADC_CR_ADCAL) != 0) //Wait for Calibration to be done
        ;

        ADC1 -> CFGR |= ADC_CFGR_CONT | ADC_CFGR_DMACFG;
        ADC1 -> CFGR &= ~ADC_CFGR_ALIGN_RIGHT | ADC_CFGR_RES_12_Bit;
        ADC1 -> SMPR2 |= ADC_SMPR2_SMP12_640_ADC_CYCLES;
        ADC1 -> SQR1 |= ADC_SQR1_SQ1_12;

        ADC1 -> ISR |= ADC_ISR_ADRDY;
        ADC1 -> CR |= ADC_CR_ADEN; //Enable: ADC

        while((ADC1->ISR & ADC_ISR_ADRDY) == 0) //Wait for the ADC to be ready
        ;

        ADC1 -> ISR |= ADC_ISR_ADRDY; //Clear the ARDYFlAG
        ADC1 -> CR |= ADC_CR_ADSTART; //Start the ADC
        ADC1 -> CFGR |= ADC_CFGR_DMAEN;

}

void init_Clock() {

    CFGR = find_PLL(CPU_Speed, ADC_Speed);

        // |----------------------------------- WAIT STATE: 0 -----------------------------------|
        if (CPU_Speed <= 16000000) {

            FLASH -> ACR &= ~FLASH_ACR_LATENCY_Msk;
            FLASH -> ACR |= FLASH_ACR_LATENCY_0WS;

            if ((FLASH -> ACR & FLASH_ACR_LATENCY_0WS) != FLASH_ACR_LATENCY_0WS){
                //ERROR: System didn't change wait states properly
            } else{
                //Success
            }

        // |----------------------------------- WAIT STATE: 1 -----------------------------------|
        } else if (CPU_Speed <= 32000000){

            FLASH -> ACR &= ~FLASH_ACR_LATENCY_Msk;
            FLASH -> ACR |= FLASH_ACR_LATENCY_1WS;

            if ((FLASH -> ACR & FLASH_ACR_LATENCY_1WS) != FLASH_ACR_LATENCY_1WS){
                //ERROR: System didn't change wait states properly
            } else{
                //Success
        }


        // |----------------------------------- WAIT STATE: 2 -----------------------------------|
        } else if (CPU_Speed <= 48000000){

            FLASH -> ACR &= ~FLASH_ACR_LATENCY_Msk;
            FLASH -> ACR |= FLASH_ACR_LATENCY_2WS;

            if ((FLASH -> ACR & FLASH_ACR_LATENCY_2WS) != FLASH_ACR_LATENCY_2WS){
                //ERROR: System didn't change wait states properly
            } else{
                //Success
            }


        // |----------------------------------- WAIT STATE: 3 -----------------------------------|
        } else if (CPU_Speed <= 64000000){

            FLASH -> ACR &= ~FLASH_ACR_LATENCY_Msk;
            FLASH -> ACR |= FLASH_ACR_LATENCY_3WS;

            if ((FLASH -> ACR & FLASH_ACR_LATENCY_3WS) != FLASH_ACR_LATENCY_3WS){
                //ERROR: System didn't change wait states properly
            } else{
                //Success
            }


        // |----------------------------------- WAIT STATE: 4 -----------------------------------|
        } else if (CPU_Speed <= 80000000){

            FLASH -> ACR &= ~FLASH_ACR_LATENCY_Msk;
            FLASH -> ACR |= FLASH_ACR_LATENCY_4WS;

            if ((FLASH -> ACR & FLASH_ACR_LATENCY_4WS) != FLASH_ACR_LATENCY_4WS){
                //ERROR: System didn't change wait states properly
            } else{
                //Success
            }

        } else{
            //Error: Clock Speed too high
        }

        RCC -> CFGR |= RCC_CFGR_SW_PLL;
        PWR -> CR1 &= ~PWR_CR1_VOS_Msk;
        PWR -> CR1 |= PWR_CR1_VOS_0;
        RCC -> CR |= RCC_CR_MSIRGSEL | RCC_CR_MSIRANGE_6;

        // |----------------------------------- PLLCFGR: R -----------------------------------|
        if (CFGR.PLLR == 2){
            RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLLR_Msk;
            RCC -> PLLCFGR |= RCC_PLLCFGR_PLLR_2;
        } else if (CFGR.PLLR == 4){
            RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLLR_Msk;
            RCC -> PLLCFGR |= RCC_PLLCFGR_PLLR_4;
        } else if (CFGR.PLLR == 6){
            RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLLR_Msk;
            RCC -> PLLCFGR |= RCC_PLLCFGR_PLLR_6;
        } else if (CFGR.PLLR == 8){
            RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLLR_Msk;
            RCC -> PLLCFGR |= RCC_PLLCFGR_PLLR_8;
        }

        // |----------------------------------- PLLCFGR: M -----------------------------------|
        if (CFGR.PLLM == 1){
            RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLLM_Msk;
        } else {
            RCC -> PLLCFGR &= ~RCC_PLLCFGR_PLLM_Msk;
            RCC -> PLLCFGR |= (CFGR.PLLM-1) << RCC_PLLCFGR_PLLM_Pos;
        }

        // |----------------------------------- PLLCFGR: N -----------------------------------|
        RCC -> PLLCFGR &= ~(RCC_PLLCFGR_PLLN_Msk);
        RCC -> PLLCFGR |= ((CFGR.PLLN) << RCC_PLLCFGR_PLLN_Pos) | (RCC_PLLCFGR_PLLREN) | (RCC_PLLCFGR_PLLSRC_MSI);

        // |----------------------------------- PLLSAI1CFGR: R -----------------------------------|
        if (CFGR.PLLSAI1R == 2){
            RCC -> PLLSAI1CFGR &= ~RCC_PLLSAI1CFGR_PLLSAI1R_Msk;
            RCC -> PLLSAI1CFGR |= RCC_PLLSAI1CFGR_PLLSAI1R_2;
        } else if (CFGR.PLLSAI1R == 4){
            RCC -> PLLSAI1CFGR &= ~RCC_PLLSAI1CFGR_PLLSAI1R_Msk;
            RCC -> PLLSAI1CFGR |= RCC_PLLSAI1CFGR_PLLSAI1R_4;
        } else if (CFGR.PLLSAI1R == 6){
            RCC -> PLLSAI1CFGR &= ~RCC_PLLSAI1CFGR_PLLSAI1R_Msk;
            RCC -> PLLSAI1CFGR |= RCC_PLLSAI1CFGR_PLLSAI1R_6;
        } else if (CFGR.PLLSAI1R == 8){
            RCC->PLLSAI1CFGR &= ~RCC_PLLSAI1CFGR_PLLSAI1R_Msk;
            RCC->PLLSAI1CFGR |= RCC_PLLSAI1CFGR_PLLSAI1R_8;
        }

        // |----------------------------------- PLLSAI1CFGR: N -----------------------------------|
        RCC -> PLLSAI1CFGR &= ~(RCC_PLLSAI1CFGR_PLLSAI1N_Msk);
        RCC -> PLLSAI1CFGR |= RCC_PLLSAI1CFGR_PLLSAI1REN | (CFGR.PLLSAI1N << RCC_PLLSAI1CFGR_PLLSAI1N_Pos);

        RCC -> CR |= RCC_CR_PLLON;
        while ((RCC->CR & RCC_CR_PLLRDY) == 0)
        ;
        RCC -> CR |= RCC_CR_PLLSAI1ON;
        while ((RCC -> CR & RCC_CR_PLLSAI1RDY) == 0)
        ;
        if ((RCC -> CFGR & RCC_CFGR_SWS_PLL) != RCC_CFGR_SWS_PLL ) {
            //Error: Clock Didn't switch
        }
}

void init_DAC(){

    RCC -> APB1ENR1 |= RCC_APB1ENR1_DAC1EN;
    RCC -> AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
    GPIOA -> MODER &= ~GPIO_MODER_MODE4;
    GPIOA -> MODER |= GPIO_MODER_MODE4_Analog;
    DAC1 -> CR |= DAC_CR_EN1;
}

void init_Interrupt(){

    NVIC_EnableIRQ(DMA2_Channel3_IRQn);
    NVIC_SetPriority(DMA2_Channel3_IRQn,0);
}

void init_GPIO_Test(){

    RCC -> AHB2ENR |= RCC_AHB2ENR_GPIOAEN;
    GPIOA -> MODER &= ~GPIO_MODER_MODE0;
    GPIOA -> MODER |= GPIO_MODER_MODE0_Gen_Purpose;
}

void print_ADC(short adcValue){

    short counter = 0;

    while (adcValue > 0){
        buffer[14-counter] = (adcValue % 10) + '0';
        adcValue = adcValue / 10;
        counter++;
    }

    if (counter == 0){

        buffer[14] = adcValue + '0';
        buffer[13] = ' ';
        buffer[12] = ' ';
        buffer[11] = ' ';

    } else if (counter == 1){
         buffer[13] = ' ';
         buffer[12] = ' ';
         buffer[11] = ' ';

    } else if (counter == 2){
         buffer[12] = ' ';
         buffer[11] = ' ';

    } else if (counter == 3){
         buffer[11] = ' ';
  }

    counter = 0;
}

void init_Debug(){

    RCC -> APB1ENR1 |= RCC_APB1ENR1_USART2EN;
    RCC -> AHB1ENR  |= RCC_AHB1ENR_DMA1EN;
    RCC -> AHB2ENR  |= RCC_AHB2ENR_GPIOAEN;
    RCC -> CCIPR    |= RCC_CCIPR_USART2SEL_System_Clock;

    GPIOA -> MODER  &= ~GPIO_MODER_MODE2;
    GPIOA -> MODER  |= GPIO_MODER_MODE2_Alt_Function;
    GPIOA -> AFR[0] |= GPIO_AFRL_AFSEL2_USART2;

    DMA1_Channel7 -> CCR  |= DMA_CCR_PL_High     |
                             DMA_CCR_MSIZE_8_Bit |
                             DMA_CCR_PSIZE_8_Bit |
                             DMA_CCR_MINC        |
                             DMA_CCR_CIRC        |
                             DMA_CCR_DIR;
    DMA1_CSELR    -> CSELR |= DMA_CSELR_C7S_USART2;
    DMA1_Channel7 -> CNDTR  = 0x14; // 20
    DMA1_Channel7 -> CMAR   = (uint32_t)buffer;
    DMA1_Channel7 -> CPAR   = (uint32_t)&USART2 -> TDR;
    DMA1_Channel7 -> CCR  |= DMA_CCR_EN;

    USART2 -> CR1 &= ~USART_CR1_M1 | ~USART_CR1_OVER16;
    USART2 -> CR1 |= USART_CR1_TE;
    USART2 -> CR3 |= USART_CR3_DMAT;
    USART2 -> BRR = 0x208D;
    USART2 -> CR1 |= USART_CR1_UE;
}

One Answer

Okay, so the issue was the oscilloscope and not the MCU. I realized as mentioned above was the zooming and how it affected the scope's sampling rate. As you zoom out the sample rate goes down and vice versa when zooming in.

How I obtain those pictures was I pressed the Run/Stopped button and zoomed in the still image. Since it was stopped at such a low sampling rate it make sense why my wave looks like that.

The work around is now I use a trigger. The trigger allows the scope to sample close to the maximum sample rate. Trigger is the key on a rising edge on input 1 (Yellow). I zoom in and acquire the sampling rate I want, start the trigger and wait for it. It will then display the wave form on the rising edge with the maximum sampling rate.

Answered by Leoc on November 17, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP