Go Down

Topic: Sending data buffer through serial, some values get shifted (Read 569 times) previous topic - next topic

dberezin


I'm working on a project were I have to send data through serial and I figured out filling a buffer was the best option. So far, I'm puting the values of a lookup table I'm using to output a wave through the DAC and sending those values through serial. The problem is that a few wave periods get sent correctly but then some others get shifted (each value gets multiplied by 256) and then the problem fixes itself. But of course, I need the data to be sent trustfully.

Code: [Select]

const PROGMEM short sintab[3][512] = ... //lookup tables

int wave = 1;
int i = 0;
int k = 1;


short* buff;

const int buflen = 1048;



void setup(void) {
  buff =  new short(buflen);
  Serial3.begin(57600, SERIAL_8E2);
}

void loop(void) {
    i+= k;
    j++;
    if (i>511){
      i-=512;     
      }
    if (j>buflen){
      byte* bytePointer =(byte*)buff;
      for (int l=0; l<buflen; l++){
        Serial3.write(bytePointer[l]);
        Serial3.flush();
        }
      j = 0;
      delete(buff);
      buff =  new short(buflen);
      }
}




There are the relevant chunks of code. The lookup tables go from 0 to 4095, hence I use short (most significant bit should always be zero). But on the other side, checking with a serial monitor, higher values get received. I tried puting down the baudrate, adding parity and stop bits and allocating memory with the new command (before I was just declaring the buffer as an array). The whole code is attached. Any ideas on how to send the right values and no other is well received.

ard_newbie

To print a 2 dimension buffer, you can do that:

Code: [Select]

const uint16_t bufsize = 512;
uint16_t buf[4][bufsize];

void setup() {
  Serial.begin(250000);
  // Fill buf[][]
}

void loop() {

  static uint8_t bufn;
  printArray(buf[bufn]);
  bufn = (bufn + 1) % 4;

}

void printArray(uint16_t x[])
{

  for (int i = 0; i < bufsize; i++) {
    Serial.println (x[i]);
  }
}


For ADC sampling and DAC output, here is an example sketch:
Code: [Select]

/*******************************************************************************************/
/*                  ADC and DAC in FREE Running Mode and PDC DMA                           */
/*******************************************************************************************/

volatile uint32_t Timestamp, Oldmicros;
volatile boolean Flag, Flag_dac;
volatile uint8_t bufn, bufn_dac;
const uint16_t bufsize = 128;            // size must be a power of 2
const uint8_t bufnumber = 4;             // bufnumber > 2, better be a power of 2
const uint8_t _bufnumber = bufnumber - 1;
uint16_t buf[bufnumber][bufsize];        // bufnumber buffers of bufsize samples,

void setup()
{
  Serial.begin(250000);
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(12, OUTPUT);
  adc_setup();
  dac_setup();
  Oldmicros = micros();
}

void loop()
{
  if (Flag) {
    Flag = false;
    Serial.println(Timestamp);
  }
}

/*************  Configure adc_setup function  *******************/
void adc_setup() {

  PMC->PMC_PCER1 |= PMC_PCER1_PID37;                    // ADC power ON

  ADC->ADC_CR = ADC_CR_SWRST;                           // Reset ADC
  ADC->ADC_MR |=  ADC_MR_TRGEN_DIS                      // Free Running Mode selected
                  | ADC_MR_FREERUN
                  | ADC_MR_PRESCAL(1);                  // Or PRESCAL (1) to reduce ADC frequency to 21 MHz

  ADC->ADC_ACR = ADC_ACR_IBCTL(0b01);                   // For frequencies > 500 KHz

  ADC->ADC_IER = ADC_IER_ENDRX;                         // End Of Conversion interrupt enable for channel 7
  NVIC_EnableIRQ(ADC_IRQn);                             // Enable ADC interrupt
  ADC->ADC_CHER = ADC_CHER_CH7;                         // Enable Channel 7 = A0

  /*********  code for PDC/DMA  buffer filling sequence **********/
  ADC->ADC_RPR = (uint32_t)buf[1];                      // DMA buffer - First one will be buf[1]
  ADC->ADC_RCR = bufsize;
  ADC->ADC_RNPR = (uint32_t)buf[2];                     // next DMA buffer
  ADC->ADC_RNCR = bufsize;
  bufn = 2;
  ADC->ADC_PTCR |= ADC_PTCR_RXTEN;                      // Enable PDC Receiver channel request
  ADC->ADC_CR = ADC_CR_START;
}

/*********  Call back function for ADC and DACC PDC/DMA **************/
void ADC_Handler () {

  bufn = (bufn + 1) & _bufnumber;
  ADC->ADC_RNPR = (uint32_t)buf[bufn];
  ADC->ADC_RNCR = bufsize;
  Flag_dac = true;

  bufn_dac = (bufn_dac + 1) & _bufnumber;
  DACC->DACC_TNPR = (uint32_t)buf[bufn_dac];
  DACC->DACC_TNCR = bufsize;

  // For debugging only
  static uint32_t Count;
  if (Count++ == 7812) { //1000000/128 ~7812
    Timestamp = micros() - Oldmicros;
    Oldmicros = micros();
    Flag = true;
    Count = 0;
    PIOB->PIO_ODSR ^= PIO_ODSR_P27;  // Toggle LED_BUILTIN every 1 Hz
  }

}

/*************  Configure adc_setup function  *******************/
void dac_setup ()
{

  PMC->PMC_PCER1 = PMC_PCER1_PID38;                   // DACC power ON

  DACC->DACC_CR = DACC_CR_SWRST ;                     // Reset DACC
  DACC->DACC_MR = DACC_MR_TRGEN_DIS                   // Free Running Mode selected
                  | DACC_MR_USER_SEL_CHANNEL1         // select channel 1
                  | DACC_MR_REFRESH (1)
                  | DACC_MR_STARTUP_8
                  | DACC_MR_MAXS;

  DACC->DACC_ACR = DACC_ACR_IBCTLCH0(0b10)
                   | DACC_ACR_IBCTLCH1(0b10)
                   | DACC_ACR_IBCTLDACCORE(0b01);

  DACC->DACC_IER = DACC_IER_ENDTX;
  NVIC_EnableIRQ(DACC_IRQn);                          // Enable DACC interrupt
  DACC->DACC_CHER = DACC_CHER_CH1;                    // enable channel 1 = DAC1

  /*************   configure PDC/DMA  for DAC *******************/
  DACC->DACC_TPR  = (uint32_t)buf[0];                 // DMA buffer
  DACC->DACC_TCR  = bufsize;
  DACC->DACC_TNPR = (uint32_t)buf[1];                 // next DMA buffer
  DACC->DACC_TNCR =  bufsize;
  bufn_dac = 1;
  DACC->DACC_PTCR = DACC_PTCR_TXTEN;                  // Enable PDC Transmit channel request

}

void DACC_Handler() {

  if (Flag_dac) {

    Flag_dac = false;

    static uint32_t Count;
    if (Count++ == 7812) { //1000000/128 ~7812
      Count = 0;
      PIOD->PIO_ODSR ^= PIO_ODSR_P8;  // Toggle pin 12 every 1 Hz
    }
  }

}





Go Up