atmega16 uart interrupt problem

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

Hello,

Somebody can help me, because I two day tried understand why my code doen't work. Your are last hope for me. I send from atmega8 information eg. "125r" from uart. atmega16 get information and char convert to int number. If I using small code it is work.The code which is work is

#include<avr/io.h>
#include<avr/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#define F_CPU 8000000
#define BAUDRATE 2400
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
volatile unsigned char rx_data=0;
volatile unsigned int new_rx_data=0;
volatile unsigned int skaic[8];
volatile unsigned int sk=0;

void USART_Init(void)
{
    UBRRL=(uint8_t)UBRRVAL;
    UBRRH=(UBRRVAL>>8);
    UCSRC=(1<<URSEL)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);
    UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
}

void USART_simbolis(unsigned char *data)
{
 while((UCSRA&(1<<UDRE)) == 0);
	UDR = data;
}

void USART_siuntimas(unsigned char *data)
{
while(*data!=0)
	{
 while((UCSRA&(1<<UDRE)) == 0);
	UDR = *data;
	data++;
	}
}
ISR(USART_RXC_vect)
{
   rx_data=UDR;
   new_rx_data=1; 

}
void main()
{
 char buffer[8]={000000000};

 int ty;
 USART_Init();
 sei();

while(1)
		{
		if(new_rx_data)
         {
			if(rx_data=='r')
   			{ 

     	  skaic[sk]='m';
	 	  sk=0;
		  ty=0;
		  char *k=&skaic;
   		while(*k!='m')
		 {
 			if((*k>='0')&&(*k<='9'))
			{
			buffer[ty]=*k;
			ty++;
			}
			k++;
		 }
USART_siuntimas(buffer);
DDRB=atoi(buffer);
	 }
else
   {
      skaic[sk]=rx_data;
	  sk=sk+1;
   }
         new_rx_data=0;
      }
		}

}

But If same using another program it is bigger

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>

#define SegDataPort		PORTA
#define SegDataDDR		DDRA

#define SegCntrlPort	PORTC
#define SegCntrlDDR		DDRC

#define F_CPU 8000000
#define BAUDRATE 2400
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)

volatile uint16_t vienetas=0;
volatile uint16_t desimt=0;
volatile uint16_t desimt1=0;
volatile uint16_t simtas=0;
volatile uint16_t simtas1=0;
volatile uint16_t tukstantis=0;
volatile uint16_t tukstantis1=0;
volatile uint16_t desimttuks=0;
volatile uint16_t k=0;
volatile uint32_t i=0;
volatile unsigned int u=0;
volatile unsigned int sk=0;
volatile unsigned int skaic[8];
volatile unsigned char rx_data=0;
volatile unsigned int new_rx_data=0; 

//==========================================================

void USART_Init(void)
{
    UBRRL=(uint8_t)UBRRVAL;
    UBRRH=(UBRRVAL>>8);
    UCSRC=(1<<URSEL)|(0<<UCSZ2)|(1<<UCSZ1)|(1<<UCSZ0);
    UCSRB=(1<<TXEN)|(1<<RXEN)|(1<<RXCIE);
}

void USART_simbolis(unsigned char *data)
{
 while((UCSRA&(1<<UDRE)) == 0);
	UDR = data;
}

void USART_siuntimas(unsigned char *data)
{
while(*data!=0)
	{
 while((UCSRA&(1<<UDRE)) == 0);
	UDR = *data;
	data++;
	}
}
ISR(USART_RXC_vect)
{
   rx_data=UDR;
   new_rx_data=1; 

}

//==========================================================

unsigned char DigitTo7SegEncoder(int digit, int common)
{
	int SegVal;

	switch(digit)
	{
		case 0:	if(common == 1)	SegVal = 0b01111110;
				else			SegVal = ~0b01111110;

				break;
		case 1:	if(common == 1)	SegVal = 0b00011000;
				else	      SegVal = ~0b00011000;

				break;
		case 2:	if(common == 1)	SegVal = 0b01101101;
				else			SegVal = ~0b01101101;
				break;
		case 3:	if(common == 1)	SegVal = 0b00111101;
				else			SegVal = ~0b00111101;
				break;
		case 4:	if(common == 1)	SegVal = 0b000011011;
				else			SegVal = ~0b000011011;
				break;
		case 5:	if(common == 1)	SegVal = 0b00110111;
				else			SegVal = ~0b00110111;
				break;
		case 6:	if(common == 1)	SegVal = 0b01110111;
				else			SegVal = ~0b01110111;
				break;
		case 7:	if(common == 1)	SegVal = 0b00011100;
				else			SegVal = ~0b00011100;
				break;
		case 8:	if(common == 1)	SegVal = 0b01111111;
				else			SegVal = ~0b01111111;
				break;
		case 9:	if(common == 1)	SegVal = 0b00111111;
				else			SegVal = ~0b00111111;
				break;
	}	

	return SegVal;
}

void main()
{
 char buffer[8]={000000000};
 int ty;
  	SegDataDDR = 0xFF;
	SegCntrlDDR = 0xFF;
	SegCntrlPort = 0xFF;
    USART_Init();
	sei();

while(1)
	{
if(new_rx_data)
        {
			if(rx_data=='r')
   			{ 

     	  skaic[sk]='m';
	 	  sk=0;
		  ty=0;
		  char *k=&skaic;
   		while(*k!='m')
		 {
 			if((*k>='0')&&(*k<='9'))
			{
			buffer[ty]=*k;
			ty++;
			}
			k++;
		 }
USART_siuntimas(buffer);
DDRB=atoi(buffer);
	 }
else
   {
      skaic[sk]=rx_data;
	  sk++;
   }
         new_rx_data=0;
      }
		SegDataPort=0;
		SegCntrlPort = 0x00;
		_delay_us(500);
		SegDataPort = DigitTo7SegEncoder(i%10,1);
		SegCntrlPort = 0x01;
		_delay_us(3000);
		SegDataPort=0;
		SegCntrlPort = 0x00;
		_delay_us(500);
	if(i<100)
		{desimt=i/10;}
		if(i>=100)
		{desimt1=i%100;
		desimt=desimt1/10;
		}
		SegDataPort = DigitTo7SegEncoder(desimt,1);
			SegCntrlPort = 0x02;
		_delay_us(3000);
		SegDataPort=0;
		SegCntrlPort = 0x00;
		_delay_us(500);
		if((i>=100)&&(i<1000))
		{simtas=i/100;}
		if(i>=1000)
		{
		simtas1=i/100;
		simtas=simtas1%10;
		}
		SegDataPort = DigitTo7SegEncoder(simtas,1);
		SegCntrlPort = 0x04;
		_delay_us(3000);
		SegDataPort=0;
		SegCntrlPort = 0x00;
		_delay_us(500);
			if((i>=1000)&&(i<10000))
		{tukstantis=i/1000;}
		if(i>=10000)
		{
		tukstantis1=i/1000;
		tukstantis=tukstantis1%10;
		}
		SegDataPort = DigitTo7SegEncoder(tukstantis,1);
		SegCntrlPort = 0x08;
		_delay_us(3000);
		SegDataPort=0;
		SegCntrlPort = 0x00;
		_delay_us(500);
		SegDataPort = DigitTo7SegEncoder(i/10000,1);
		SegCntrlPort = 0x10;
		_delay_us(3000);
}

return 0;
}

I from atmega8 send "128r", but got terrible number I attached picture below

 

Maybe can somebody explain for me why I get that? Or give to me advice how solve this problem. Thank you in advance

 

Last Edited: Wed. Nov 1, 2017 - 07:17 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You have this:

#define F_CPU 8000000

in both programs, but are you sure your cpu is running at 8MHz, how have you proven that?  Show us your fuse settings on both.

Also, what is your clock source?  Serial comms need an accurate and stable clock source, such as a xtal, the internal RC is neither of those!

 

Jim

 

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

I am using this fuse settings on both some. Using internal RC Osc

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

This is no (direct) suggestion to a solution of your problem:, but...: You need to make your code readable. In this case it's about making indentation reflect the structure of your program. Indentation is used to reflect what code is part of a larger block and/or is ddependent on some control statement (if, while, for etc).

 

You should do this for two reasons:

  • Because you need to understand what you yourself has written. Code structure is vital when you return to something you wrote earlier (be that 15 minutes or three years ago).
  • Because you ask others to read your code, and they (i.e. we) all rely on this conventional way of structuring code.

 

There are several indentation styles commonly used. Google "code indentation", possibly in combination with one of these: "kernighan ritchie", "gnu", "linux-style", "1tbs"

 

Below are examples of  good indentations of your two programs above.

 

First program:

#include<avr/io.h>
#include<avr/delay.h>
#include <avr/interrupt.h>
#include <string.h>
#define F_CPU 8000000
#define BAUDRATE 2400
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)
volatile unsigned char rx_data = 0;
volatile unsigned int new_rx_data = 0;
volatile unsigned int skaic[8];
volatile unsigned int sk = 0;

void
USART_Init (void)
{
  UBRRL = (uint8_t) UBRRVAL;
  UBRRH = (UBRRVAL >> 8);
  UCSRC = (1 << URSEL) | (0 << UCSZ2) | (1 << UCSZ1) | (1 << UCSZ0);
  UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);
}

void
USART_simbolis (unsigned char *data)
{
  while ((UCSRA & (1 << UDRE)) == 0);
  UDR = data;
}

void
USART_siuntimas (unsigned char *data)
{
  while (*data != 0)
    {
      while ((UCSRA & (1 << UDRE)) == 0);
      UDR = *data;
      data++;
    }
}

ISR (USART_RXC_vect)
{
  rx_data = UDR;
  new_rx_data = 1;

}

void
main ()
{
  char buffer[8] = { 000000000 };

  int ty;
  USART_Init ();
  sei ();

  while (1)
    {
      if (new_rx_data)
        {
          if (rx_data == 'r')
            {

              skaic[sk] = 'm';
              sk = 0;
              ty = 0;
              char *k = &skaic;
              while (*k != 'm')
                {
                  if ((*k >= '0') && (*k <= '9'))
                    {
                      buffer[ty] = *k;
                      ty++;
                    }
                  k++;
                }
              USART_siuntimas (buffer);
              DDRB = atoi (buffer);
            }
          else
            {
              skaic[sk] = rx_data;
              sk = sk + 1;
            }
          new_rx_data = 0;
        }
    }

}

Second program:

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>

#define SegDataPort		PORTA
#define SegDataDDR		DDRA

#define SegCntrlPort	PORTC
#define SegCntrlDDR		DDRC

#define F_CPU 8000000
#define BAUDRATE 2400
#define UBRRVAL ((F_CPU/(BAUDRATE*16UL))-1)

volatile uint16_t vienetas = 0;
volatile uint16_t desimt = 0;
volatile uint16_t desimt1 = 0;
volatile uint16_t simtas = 0;
volatile uint16_t simtas1 = 0;
volatile uint16_t tukstantis = 0;
volatile uint16_t tukstantis1 = 0;
volatile uint16_t desimttuks = 0;
volatile uint16_t k = 0;
volatile uint32_t i = 0;
volatile unsigned int u = 0;
volatile unsigned int sk = 0;
volatile unsigned int skaic[8];
volatile unsigned char rx_data = 0;
volatile unsigned int new_rx_data = 0;

//==========================================================

void
USART_Init (void)
{
  UBRRL = (uint8_t) UBRRVAL;
  UBRRH = (UBRRVAL >> 8);
  UCSRC = (1 << URSEL) | (0 << UCSZ2) | (1 << UCSZ1) | (1 << UCSZ0);
  UCSRB = (1 << TXEN) | (1 << RXEN) | (1 << RXCIE);
}

void
USART_simbolis (unsigned char *data)
{
  while ((UCSRA & (1 << UDRE)) == 0);
  UDR = data;
}

void
USART_siuntimas (unsigned char *data)
{
  while (*data != 0)
    {
      while ((UCSRA & (1 << UDRE)) == 0);
      UDR = *data;
      data++;
    }
}

ISR (USART_RXC_vect)
{
  rx_data = UDR;
  new_rx_data = 1;

}

//==========================================================

unsigned char
DigitTo7SegEncoder (int digit, int common)
{
  int SegVal;

  switch (digit)
    {
    case 0:
      if (common == 1)
        SegVal = 0 b01111110;
      else
        SegVal = ~0 b01111110;

      break;
    case 1:
      if (common == 1)
        SegVal = 0 b00011000;
      else
        SegVal = ~0 b00011000;

      break;
    case 2:
      if (common == 1)
        SegVal = 0 b01101101;
      else
        SegVal = ~0 b01101101;
      break;
    case 3:
      if (common == 1)
        SegVal = 0 b00111101;
      else
        SegVal = ~0 b00111101;
      break;
    case 4:
      if (common == 1)
        SegVal = 0 b000011011;
      else
        SegVal = ~0 b000011011;
      break;
    case 5:
      if (common == 1)
        SegVal = 0 b00110111;
      else
        SegVal = ~0 b00110111;
      break;
    case 6:
      if (common == 1)
        SegVal = 0 b01110111;
      else
        SegVal = ~0 b01110111;
      break;
    case 7:
      if (common == 1)
        SegVal = 0 b00011100;
      else
        SegVal = ~0 b00011100;
      break;
    case 8:
      if (common == 1)
        SegVal = 0 b01111111;
      else
        SegVal = ~0 b01111111;
      break;
    case 9:
      if (common == 1)
        SegVal = 0 b00111111;
      else
        SegVal = ~0 b00111111;
      break;
    }

  return SegVal;
}

void
main ()
{
  char buffer[8] = { 000000000 };
  int ty;
  SegDataDDR = 0xFF;
  SegCntrlDDR = 0xFF;
  SegCntrlPort = 0xFF;
  USART_Init ();
  sei ();

  while (1)
    {
      if (new_rx_data)
        {
          if (rx_data == 'r')
            {

              skaic[sk] = 'm';
              sk = 0;
              ty = 0;
              char *k = &skaic;
              while (*k != 'm')
                {
                  if ((*k >= '0') && (*k <= '9'))
                    {
                      buffer[ty] = *k;
                      ty++;
                    }
                  k++;
                }
              USART_siuntimas (buffer);
              DDRB = atoi (buffer);
            }
          else
            {
              skaic[sk] = rx_data;
              sk++;
            }
          new_rx_data = 0;
        }
      SegDataPort = 0;
      SegCntrlPort = 0x00;
      _delay_us (500);
      SegDataPort = DigitTo7SegEncoder (i % 10, 1);
      SegCntrlPort = 0x01;
      _delay_us (3000);
      SegDataPort = 0;
      SegCntrlPort = 0x00;
      _delay_us (500);
      if (i < 100)
        {
          desimt = i / 10;
        }
      if (i >= 100)
        {
          desimt1 = i % 100;
          desimt = desimt1 / 10;
        }
      SegDataPort = DigitTo7SegEncoder (desimt, 1);
      SegCntrlPort = 0x02;
      _delay_us (3000);
      SegDataPort = 0;
      SegCntrlPort = 0x00;
      _delay_us (500);
      if ((i >= 100) && (i < 1000))
        {
          simtas = i / 100;
        }
      if (i >= 1000)
        {
          simtas1 = i / 100;
          simtas = simtas1 % 10;
        }
      SegDataPort = DigitTo7SegEncoder (simtas, 1);
      SegCntrlPort = 0x04;
      _delay_us (3000);
      SegDataPort = 0;
      SegCntrlPort = 0x00;
      _delay_us (500);
      if ((i >= 1000) && (i < 10000))
        {
          tukstantis = i / 1000;
        }
      if (i >= 10000)
        {
          tukstantis1 = i / 1000;
          tukstantis = tukstantis1 % 10;
        }
      SegDataPort = DigitTo7SegEncoder (tukstantis, 1);
      SegCntrlPort = 0x08;
      _delay_us (3000);
      SegDataPort = 0;
      SegCntrlPort = 0x00;
      _delay_us (500);
      SegDataPort = DigitTo7SegEncoder (i / 10000, 1);
      SegCntrlPort = 0x10;
      _delay_us (3000);
    }

  return 0;
}

 

I hope you can see how much more readable the code is with this indentation.

 

EDIT: Note: I do not argue that the style I used above is the best. There is no best style, but there are a number of good styles. The important thing is to select one and be consistent with it throughout as project.

 

I used an automatic tool to fix the structure in your two programs. Things it did that I did not like, but was too lazy to find the correct options to avoid are e.g.:

- Function return types on separate lines

- Space between function name and parameter list parenthesis in function calls

- "Double indentation", i.e. "gullwings" are indented, and then the statements inside the gullwing blocks are indented.

The point is that it is consistent, and one of the universally recognized indentation styles.

 

No, I will not reveal my preferred indentation style.

 

No, do not ask which style is the best - it will only lead to an endless argument between people (a.k.a "indentation war").

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Wed. Nov 1, 2017 - 08:02 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Your program processes one incoming character per main loop iteration. But in your bigger program a main loop iteration takes MUCH more time (especially because of all the delays). The characters are arriving way faster than your program can process them.

Stefan Ernst

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

What do you think the rxc interrupt gives you? Unfortunately it does very little for you as you only hold one character. Your main loop has large delays, so your receive characters will disappear as you don’t read the incoming characters fast enough.
You need a circular buffer to store a number of incoming characters. There’s a tutorial for that in the tutorials section.

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

maybe you could give to me link where I can find this tutorial. Thank

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

ki0bk wrote:
Serial comms need an accurate and stable clock source, such as a xtal, the internal RC is neither of those!

Let me make that bold so you will notice it!

You have now been warned.

 

Good luck with your project.

 

Jim

 

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

pcwortex wrote:

maybe you could give to me link where I can find this tutorial. Thank


Google avr uart circular buffer
Guess what the first hit is. Most of us will use specific ‘keywords’ so if you don’t understand them, use Google. Add AVR or Arduino to narrow down the hits. The AVR has been around nearly 20 years now, so just about all the questions have been asked.

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

pcwortex wrote:

maybe you could give to me link where I can find this tutorial. Thank

 

Did you at all try to locate it yourself? Probably not. 

 

I will spoil you with the link, but be aware that having the "feed me" attitude  will eventually give you a less-than-good reputation. Taking 15 minutes to sift  through the listing of tutorials will give you an impression of what is available, and will serve you well in the future.

 

Actually, several links:

http://www.avrfreaks.net/forum/t...

http://www.avrfreaks.net/forum/t...

 

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Wed. Nov 1, 2017 - 09:48 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

"He used to carry his guitar in a gunny sack, or sit beneath the tree by the railroad track. Oh the engineers would see him sitting in the shade, Strumming with the rhythm that the drivers made. People passing by, they would stop and say, "Oh, my, what that little country boy could play!" [Chuck Berry]

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

ki0bk wrote:
Serial comms need an accurate and stable clock source, such as a xtal, the internal RC is neither of those!

I have used the internal RC 8MHz clock on several of my ATmega328P projects and I have no trouble talking to my laptop with a UART-USB FTDI breakout board at 9600 baud.  I use PuTTY.  I don't know about at higher data rates.  Am I just being lucky?

Last Edited: Wed. Nov 1, 2017 - 11:52 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Am I just being lucky?

In principle, the accuracy of the internal RC oscillator on most AVR is +/-10%.  This is not generally good enough for serial coms.  However, in practice, the real accuracy is often closer to +/-2%, particularly when not straying too far from the temperature and voltage at which the RC was calibrated at the factory.  This is usualy 25°C, and usually (but not always... see each device's datasheet) 5V.  Two percent is generally good enough for serial coms.

 

So yes, you were lucky ;-)

 

I often do the same, but I do get the occasional outlier and I have to calibrate to get reliable coms.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Also, your laptop will be using a proper crystal to set its baud rate - so your MCU will have the whole error margin to play with.

 

If you were talking to another MCU, also relying upon its RC, your luck could run out much sooner ...

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

joeymorin wrote:
 I have to calibrate to get reliable coms

How do you recalibrate?  Do you read the OSCCAL register and then tweak the CALn values using a frequency counter on the CKOUT pin to get the frequency you want?  The data sheet says a preprogrammed value is written to the OSCCAL register on startup, so do you have to rewrite the value from software each time you restart?  I guess that would make sense.  I guess you could store it in EEPROM.

 

Interesting.

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

That's one way.  Many others.  Depends, as usual.

 

In some cases I 'calibrate' in the app by auto-sensing the baud rate from the other end, and then match that with UBRR.  In others, I'll do the same auto-sensing but then tweak OSCCAL to null the error.  Depends on the range of baud rates I'll want to support, the clock speed I want to run at, etc.

 

A common way of calibrating is against an external low-frequency crystal on TOSC1/2, if your device supports it.  This can be done once after reset, or periodically if your device will be operating under varying conditions of temperature and Vcc.

 

There are a number of application notes on the subject of calibrating the RC oscillator:

http://www.atmel.com/products/microcontrollers/avr/default.aspx?tab=documents&Asset_Type=020%20Application%20Note

Just CTRL-F for 'calibrat'

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I've previously used the width of the start bit to calibrate but that requires that the received character as 1 in the lowest bit. Enter (0x0D) has that property so the user types Enter until START has been measured then OSCCAL is set and normal comms may then continue

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

Some of my auto-sense code relies on the MSB of the first 8N1 frame being zero, with a short (say, 30 ms) pause between frames.  This ensures that the falling edge of the start bit, and the rising edge of the first stop bit are 9 bit times apart.  I wait for the falling edge of the start bit, then start a timer.  Then I wait for rising edges, or a timeout.  If a rising edge arrives before the timeout, I save the timestamp of that rising edge.  If a timeout occurs, we're done, and the last rising edge is that of the stop bit.   I divide its timestamp by 9, and that's the bit time.  This is useful for any ASCII character from 0x00 through 0x7F, and can be a bit more precise than measuring a single bit.

 

This is useful for man-machine interfaces.  For machine-machine interfaces, where you have control of each machine, you can send whatever you like along the serial link and time that.

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"Read a lot.  Write a lot."

"We see a lot of arses on handlebars around here." - [J Ekdahl]