ATSAMD21G18A UART dropping bytes

Go To Last Post
19 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am trying to communicate with HPM particle sensor over UART. All the sensor commands that return A5A5 are working properly, and the sensor stops and starts when I use them therefore I know that that part of communication is working properly. However when I send the "Read Customer Adjustment Coefficient" or "Read Particle Measuring Results" commands the third byte (CMD) in the datasheet is always wrong (the received number is random as far as I can tell) and I don't receive anything after it. Are there any mistakes in the UART setup? Datasheet

#include "sam.h"
#define BAUD_RATE 9600
#define F_CPU 8000000
#define CYCLES_IN_DLYTICKS_FUNC        8
#define MS_TO_DLYTICKS(ms)			   (uint32_t)(F_CPU / 1000 * ms / CYCLES_IN_DLYTICKS_FUNC) // ((float)(F_CPU)) / 1000.0
#define DelayTicks(ticks)              {volatile uint32_t n=ticks; while(n--);}//takes 8 cycles
#define DelayMs(ms)                    DelayTicks(MS_TO_DLYTICKS(ms))//uses 20bytes

static void uart_putc(uint8_t c){
	while (!(SERCOM2->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE));
		SERCOM2->USART.DATA.reg = c; // writting data to the data register, to be read by the sensor...

}

// put data to the data register
static void uart_puts(uint8_t s[], int len){
	int cur = 0;
	while (len--){
		uart_putc(s[cur]);
		cur++;
	}
}

bool uart_has_data(){
	if ((SERCOM2->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC) >> SERCOM_USART_INTFLAG_RXC_Pos) {	// check if there is any response from the sensor
		return true;
	}
	return false;
}

static char uart_getc(){				// if there is a response read the data register
	return SERCOM2->USART.DATA.reg;
}

int main(void){

	SystemInit();
        SYSCTRL->OSC8M.bit.PRESC = 0;
	SERCOM2->USART.CTRLA.reg |= !SERCOM_USART_CTRLA_ENABLE;
	uint64_t br = (uint64_t)65536 * (F_CPU - 16 * BAUD_RATE) / F_CPU;		// baud rate, formula in datasheet page 264
	PORT->Group[0].DIRSET.reg = (1 << 12);									// PORT->Group[0] == PORTA, DIRSET -> set pin as input or output (this set's the TX pin as output)
        PORT->Group[0].PINCFG[12].reg |= PORT_PINCFG_INEN;						// set TX pin config for input enable
	PORT->Group[0].PINCFG[12].reg |= PORT_PINCFG_PMUXEN;					// enable PMUX
	PORT->Group[0].PMUX[12 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_C_Val;			// set the PMUX bit to C value for USART (if pin is odd set PMUXO)

	PORT->Group[0].DIRCLR.reg = (1 << 13);									// set RX pin as input
	PORT->Group[0].PINCFG[13].reg |= PORT_PINCFG_INEN;						// set RX pin for input enable
	PORT->Group[0].PINCFG[13].reg &= ~PORT_PINCFG_PULLEN;					// enable pullup resistor
	PORT->Group[0].PINCFG[13].reg |= PORT_PINCFG_PMUXEN;					// enable PMUX
	PORT->Group[0].PMUX[13 >> 1].bit.PMUXO = PORT_PMUX_PMUXE_C_Val;			// Set the PMUX bit (if pin is even, PMUXE, if odd, PMUXO)

	PM->APBCMASK.reg |= PM_APBCMASK_SERCOM2;																																	// set the PMUX for SERCOM2
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM2_GCLK_ID_CORE) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);																		// Generic clock “SERCOM3_GCLK_ID_CORE” uses GCLK Generator 0 as source (generic clock source can be changed as per the user needs), so the SERCOM3 clock runs at 8MHz from OSC8M
	SERCOM2->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK | SERCOM_USART_CTRLA_RXPO(1/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(0/*PAD0*/);		// DORD = data order(LSB) | using internal clock | corresponding SERCOM PAD[1] will be used for data reception (RX), PAD[0] will be used as Tx pin by setting TXPO bit as 0|
	SERCOM2->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/);														// TXEN bit and RXEN bits are set to enable the Transmitter and receiver | bits size is selected as character size by setting the bit CHSIZE as 0
	SERCOM2->USART.CTRLB.bit.SBMODE = 0;																																		// 0 stop bits
	SERCOM2->USART.CTRLA.bit.FORM = 0;																																			// no parity
	SERCOM2->USART.BAUD.reg = (uint16_t)br;																																		// baud register value corresponds to the device communication baud rate
	SERCOM2->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;																														// SERCOM2 peripheral enabled

	uint8_t read_particle[] = {0x68, 0x01, 0x04, 0x93};
	uint8_t stop_particle[] = {0x68, 0x01, 0x02, 0x95};
	uint8_t start_particle[] = {0x68, 0x01, 0x01, 0x96};
	uint8_t stop_auto[] = {0x68, 0x01, 0x20, 0x77};
	uint8_t cost_adju[] = {0x68, 0x01, 0x10, 0x87};
	// test code for HPM sensor below
	volatile char c;
	uart_puts(stop_auto, 4);
	//DelayMs(1000);
	while (uart_has_data()) {
		c = uart_getc();
		c = 0;
	}
	//DelayMs(1000);
	uart_puts(cost_adju, 4);
	//DelayMs(1000);
	while (uart_has_data()) {
		c = uart_getc();
		c = 0;
	}
	//DelayMs(1000);
        while (1) {
		uart_puts(start_particle, 4);
		//DelayMs(1000);
		while (uart_has_data()) {
			c = uart_getc();
			c = 0;
		}
		//DelayMs(1000);
		uart_puts(read_particle, 4);
		//DelayMs(1000);
		while (uart_has_data()) {
			c = uart_getc();
			c = 0;
		}
		//DelayMs(1000);
		uart_puts(stop_particle, 4);
		//DelayMs(1000);
		while (uart_has_data()) {
			c = uart_getc();
			c = 0;
		}
		//DelayMs(1000);
	}
}

 

This topic has a solution.
Last Edited: Fri. Jul 23, 2021 - 08:42 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

You are not saving the response bytes so how are you testing this? If the answer is "using the debugger with a break point looking at 'c'" then that will not work (for more than two bytes).

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am saving bytes now, however I have the same problem the first two bytes are correct but the third is not. Is it ok if I use the debugger to check the array values after reading the response or does it cause the same problem? Also do you know why the debugger is limited to such a small amount of bytes, just curious. I posted just the updated code the rest is the same as before. Is there any other way of checking it that doesn't include the debugger? The only thing I can think of is saving values to a EEPROM

    volatile uint8_t response[100] = {0};
    // test code for HPM sensor below
    volatile char c;
    uart_puts(stop_auto, 4);
    for(int i = 0; i < 200000; ++i);
	//DelayMs(1000);
	while (uart_has_data()) {
		c = uart_getc();
		c = 0;
	}
	for(int i = 0; i < 200000; ++i);
	//DelayMs(1000);
	uart_puts(cost_adju, 4);
	for(int i = 0; i < 200000; ++i);
	//DelayMs(1000);
	int cur = 0;
	while (uart_has_data()) {
	    c = uart_getc();
	    response[cur] = c;
	    cur++;
	    c = 0;
	}
	//DelayMs(1000);
    while (1) {
      /*uart_puts(start_particle, 4);
      //DelayMs(1000);
	while (uart_has_data()) {
	    c = uart_getc();
	    c = 0;
	}
	//DelayMs(1000);
	uart_puts(read_particle, 4);
	//DelayMs(1000);
	while (uart_has_data()) {
	    c = uart_getc();
	    c = 0;
	}
	//DelayMs(1000);*/
	uart_puts(stop_particle, 4);
	//DelayMs(1000);
	while (uart_has_data()) {
	    c = uart_getc();
	    c = 0;
	}
	//DelayMs(1000);
    }

 

Last Edited: Wed. Jul 21, 2021 - 10:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

arduinOMEGALUL wrote:
I am trying to communicate with HPM particle sensor over UART.

before getting into all the unknowns of 3rd-party equipment, have you first tested this against a simple terminal?

 

arduinOMEGALUL wrote:

bool uart_has_data(){
	if ((SERCOM2->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC) >> SERCOM_USART_INTFLAG_RXC_Pos) {	// check if there is any response from the sensor
		return true;
	}
	return false;
}

You don't need that shift: having masked the value,  the result is either zero (false) or not (true) - so you can use that direct.

 

https://www.avrfreaks.net/forum/tut-c-bit-manipulation-aka-programming-101

 

arduinOMEGALUL wrote:

 

static char uart_getc(){ // if there is a response read the data register
    return SERCOM2->USART.DATA.reg; }return false;
}

Not that the comment is misleading - function just returns the data register content regardless or whether there's anything there

 

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Wed. Jul 21, 2021 - 10:15 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I have tried to test it with a terminal by following the official tutorial but I got stuck at step 7 I don't have the Virtual COM port option, if there is another way of setting it up I would appreciate it if you can point me in the right direction. Ty for pointing out the bitshift and for the tutorial, and for pointing out the misleading comment, I will change those.  

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1
	uart_puts(cost_adju, 4);
	for(int i = 0; i < 200000; ++i);
	//DelayMs(1000);
	int cur = 0;
	while (uart_has_data()) {
	    c = uart_getc();
	    response[cur] = c;
	    cur++;
	    c = 0;
	}

If this is the test in question I have problems with:

* the wait loop after uart_puts (should not be needed, if it delays too long you will miss reading response bytes).
* The while loop that terminates as soon as there is currently no additional data. The code that saves the incoming response has to be faster than the incoming stream (or you would get gaps in the saved input). Hence there will be times when uart_has_data() is false even when the full response has not been received.

You will have to implement some other way to stop collecting data (number of bytes, a timeout  or both). Debugging using a break point based on that new condition will be ok.

 

The two byte limit btw is the SERCOM hardware buffering (i.e., not directly relating to debugging except that your program, when stopped by a break point, is not reading out anything from the buffer).

/Lars

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Lajon wrote:

If this is the test in question I have problems with:* the wait loop after uart_puts (should not be needed, if it delays too long you will miss reading response bytes).

I always try with and without delay just in case xd, my bad for not saying that it was definitely misleading.

Lajon wrote:

The while loop that terminates as soon as there is currently no additional data. The code that saves the incoming response has to be faster than the incoming stream (or you would get gaps in the saved input). Hence there will be times when uart_has_data() is false even when the full response has not been received.

You will have to implement some other way to stop collecting data (number of bytes, a timeout  or both). Debugging using a break point based on that new condition will be ok.

Ok this is a huge mistake indeed, I will try to wait for the correct amount of bytes, since that is easier to implement, so I won't make any more mistakes. 

And thanks for clarifying how SERCOM buffering works.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

arduinOMEGALUL wrote:
I have tried to test it with a terminal by following the official tutorial but I got stuck at step 7 I don't have the Virtual COM port

You mean you're not using an Xplained-Pro board?

 

I would strongly suggest that you do use an Xplained-Pro board to gain experience with the tools & the product, and get the basics working first.

 

 if there is another way of setting it up I would appreciate it if you can point me in the right direction

Just use a standard USB-to-UART converter or cable.  (be sure to use one that uses the correct logic levels for your SAM)

 

https://learn.sparkfun.com/tutorials/terminal-basics/all#connecting-to-your-device

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Lajon wrote:
You will have to implement some other way to stop collecting data (number of bytes, a timeout  or both).

Another option is to have a termination character at the end of the 'message' ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

You mean you're not using an Xplained-Pro board?

I am not, but I will try to get my hands on one to help me with the basics.  

awneil wrote:

Just use a standard USB-to-UART converter or cable.  (be sure to use one that uses the correct logic levels for your SAM)

 

I will definitely look in to this, ty for the tutorial I appreciate it.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

arduinOMEGALUL wrote:
I will definitely look in to this,

I suggest that you get at least 3:

 

  • One for the actual comms
  • One to monitor the 'Tx' side
  • One to monitor the 'Rx' side

 

See: https://www.avrfreaks.net/commen...

 

Using 2 terminals to monitor both sides of the conversation: https://www.avrfreaks.net/commen...

 

extended explanation: https://www.avrfreaks.net/commen...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Once again ty for helping me set it up, if you or Lajon have any more suggestions I will ofc try them. For now I removed delays and am running without debugger, and I am waiting to receive all 32 bytes (since that is the response in the datasheet), however I still receive only 3 and nothing after that, so if you have any ideas and thing I can try in the meantime before setting up the terminals let me know. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Again, have you tried it in a terminal?

 

That would be an easy way to see if it's a logic issue in your code, or a timing issue

 

(you manually typing will be a lot slower than the actual device)

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I managed to connect sam21 to the PC and display things on terminal with YP-05 as the middleman (I only have one so I can't do what you recommended earlier). When I send data to the terminal it's always correct, I never got an error, however when I send data from the terminal to the board I get some weird results (I'm not sure if this can cause any problems but to see what data I received I first read data that was sent and then I send it back to the terminal). The terminal I used is the one built  in arduino IDE, and I set it to 9600 BAUD which should be the same as in my code. If you take a look at the main function at the end, I wrote a comment explaining the weird results (tldr; if I send 1234567890 with delay in main I receive 120, and if I don't use delay I receive all the numbers but one by one in other words they don't get buffered). 
 

#include "sam.h"
#define BAUD_RATE 9600
#define F_CPU 8000000
#define CYCLES_IN_DLYTICKS_FUNC         8
#define MS_TO_DLYTICKS(ms)      	(uint32_t)(F_CPU / 1000 * ms / CYCLES_IN_DLYTICKS_FUNC) // ((float)(F_CPU)) / 1000.0
#define DelayTicks(ticks)               {volatile uint32_t n=ticks; while(n--);}		//takes 8 cycles
#define DelayMs(ms)                     DelayTicks(MS_TO_DLYTICKS(ms))				//uses 20bytes

static void uart_putc(char c){
	while (!(SERCOM2->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_DRE));
		SERCOM2->USART.DATA.reg = c; // writting data to the data register, to be read by the sensor...

}

// put data to the data register
static void uart_puts(char s[], int len){
	int cur = 0;
	while (len--){
		uart_putc(s[cur]);
		cur++;
	}
}

bool uart_has_data(){
	if (SERCOM2->USART.INTFLAG.reg & SERCOM_USART_INTFLAG_RXC) {	// check if there is any response from the sensor
		return true;
	}
	return false;
}

static char uart_getc(){						// read the data register
	return SERCOM2->USART.DATA.reg;
}

int main(void){

	SystemInit();
	SERCOM2->USART.CTRLA.reg |= !SERCOM_USART_CTRLA_ENABLE;
	uint64_t br = (uint64_t)65536 * (F_CPU - 16 * BAUD_RATE) / F_CPU;		// baud rate, formula in datasheet page 264
	PORT->Group[0].DIRSET.reg = (1 << 12);						// PORT->Group[0] == PORTA, DIRSET -> set pin as input or output (this set's the TX pin as output)
    PORT->Group[0].PINCFG[12].reg |= PORT_PINCFG_INEN;					// set TX pin config for input enable
	PORT->Group[0].PINCFG[12].reg |= PORT_PINCFG_PMUXEN;				// enable PMUX
	PORT->Group[0].PMUX[12 >> 1].bit.PMUXE = PORT_PMUX_PMUXE_C_Val;			// set the PMUX bit to C value for USART (if pin is odd set PMUXO)

	PORT->Group[0].DIRCLR.reg = (1 << 13);						// set RX pin as input
	PORT->Group[0].PINCFG[13].reg |= PORT_PINCFG_INEN;				// set RX pin for input enable
	PORT->Group[0].PINCFG[13].reg &= ~PORT_PINCFG_PULLEN;				// enable pullup resistor
	PORT->Group[0].PINCFG[13].reg |= PORT_PINCFG_PMUXEN;				// enable PMUX
	PORT->Group[0].PMUX[13 >> 1].bit.PMUXO = PORT_PMUX_PMUXE_C_Val;			// Set the PMUX bit (if pin is even, PMUXE, if odd, PMUXO)

	PM->APBCMASK.reg |= PM_APBCMASK_SERCOM2;																																	// set the PMUX for SERCOM2
	GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID(SERCOM2_GCLK_ID_CORE) | GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN(0);																		// Generic clock “SERCOM3_GCLK_ID_CORE” uses GCLK Generator 0 as source (generic clock source can be changed as per the user needs), so the SERCOM3 clock runs at 8MHz from OSC8M
	SERCOM2->USART.CTRLA.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE_USART_INT_CLK | SERCOM_USART_CTRLA_RXPO(1/*PAD1*/) | SERCOM_USART_CTRLA_TXPO(0/*PAD0*/);		// DORD = data order(LSB) | using internal clock | corresponding SERCOM PAD[1] will be used for data reception (RX), PAD[0] will be used as Tx pin by setting TXPO bit as 0|
	SERCOM2->USART.CTRLB.reg = SERCOM_USART_CTRLB_RXEN | SERCOM_USART_CTRLB_TXEN | SERCOM_USART_CTRLB_CHSIZE(0/*8 bits*/);														// TXEN bit and RXEN bits are set to enable the Transmitter and receiver | bits size is selected as character size by setting the bit CHSIZE as 0
	SERCOM2->USART.CTRLB.bit.SBMODE = 0;																																		// 0 stop bits
	SERCOM2->USART.CTRLA.bit.FORM = 0;																																			// no parity
	SERCOM2->USART.BAUD.reg = (uint16_t)br;																																		// baud register value corresponds to the device communication baud rate
	SERCOM2->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;																														// SERCOM2 peripheral enabled

	char stop_particle[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', '\n'};
	char response[64] = {0};
	// test code for HPM sensor below
	volatile char c;

    while (1) {
		int cur = 0;
		while(uart_has_data()){
			response[cur] = uart_getc();
			++cur;
			//DelayMs(10); // this delay has the same effect as the one below
		}
		response[cur] = '\n';
		if(cur != 0){
			uart_puts(response, cur + 1);
		}
		//DelayMs(1000);
		/*
			with delay: if I send 1234567890 I receive 120
			without:
				1
				2
				3
				4
				56
				78
				0
		*/
	}
}

 

Last Edited: Thu. Jul 22, 2021 - 02:38 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 2

arduinOMEGALUL wrote:
Ok this is a huge mistake indeed, I will try to wait for the correct amount of bytes, since that is easier to implement,

You have not implemented this, so your results with that 

while(uart_has_data()){

makes perfect sense,

/Lars

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

arduinOMEGALUL wrote:
if I send 1234567890 with delay in main I receive 120,

which would be as expected

 

Lajon has already explained that the UART can buffer 2 characters; so you will get the first two - 12.

 

During the delay, you are not handling the UART at all - so you will miss everything that is sent during that delay

 

By the time you get back to checking the UART again, only the final character is still there - 0.

 

If you checked the Data Overrun error flag, it would be set.

 

If you want to be able to receive characters while doing other stuff, you will need to use interrupts ...

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I'm sorry to the both of you, while I was tinkering with the terminal I removed the buffering part, if I wait for all 10 bytes (or how ever many I want to receive) everything works fine. At the moment it's implemented like this: 

number_of_bytes = 0;

while(number_of_bytes < 10){
     if(uart_has_data()){
        response[cur] = uart_getc();
        ++number_of_bytes;
    }
} 

I'm interested if there is a more "proper" way of doing it, should I implement interrupts or is this ok (assuming that the number of bytes is always known, of course if I have "end character" I can wait for that so it would work for variable lengths). Should I implement a circular buffer or something similar or is that an overkill if I know that I will always get a fixed amount of data?  

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

arduinOMEGALUL wrote:
 should I implement interrupts or is this ok

That depends entirely on the needs of your application - only you can answer that.

 

The fundamental thing with polled operation is that you must always be polling fast enough to be able to read and handle one byte and be ready for the next one before it's gone.

 

If, for whatever reason, you can't do that - they you'll need interrupts.

 

Using interrupts allows you to "disconnect" the "reading" from the "handling"

 

If the timing is really tight, you might also need DMA.

 

Should I implement a circular buffer

that would be the conventional approach when using interrupts.

 

The advantage is that it's entirely general; so , once you've done it, you can keep re-using it - whereas anything hard-coded to some particular feature  of the message will be inflexible.

 

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
Last Edited: Fri. Jul 23, 2021 - 08:32 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

awneil wrote:

If, for whatever reason, you can't do that - they you'll need interrupts.

 

Thank you for further explaining, I guess I'll see if there is the need when I add more things to the project. 

awneil wrote:

The advantage is that it's entirely general; so , once you've done it, you can keep re-using it - whereas anything hard-coded to some particular feature  of the message will be inflexible.

Good point I'll try to implement it since it can't hurt. 

 

Thank you for all the advice. 

 

P.S. The terminal was a really good idea.