Suart receive NEEDs help

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

Hi, 

Iam working on a 8 bits uP, AT328p in the Atmel studio, and try to make a software Uart receive for debugging staff. it doesnt work for me:( 

 

I use the external interrupt INT0 as receive pin, and timer0 to count bit length. My problem is that (PIND&PIND2) is always getting high, i cant figure out why:(

Iam running at 16Mhz, prescaler 64, and using a external device send data at 9600N1.

 

Here is the code, pls spot the errors for me, thx in advanced.

int main( void )
{
	char c = 0;
	DDRD &= ~(1<<2);

	TCCR0A |= (1<<WGM01);
	TCCR0B = (1<<CS00)|(1<<CS01);

	EICRA |= (1<<ISC01);
	EIFR |= (1<<INTF0);
	EIMSK |= (1<<INT0);

	sei( );

	for( ; ; )
	{
		c = SwUartRXData;
	}
}

ISR(INT0_vect) {

	EIMSK &= ~(1<<INT0);			// Disable external interrupt
	TIMSK0 &= ~(1<<OCIE0A);
	TCNT0 = 0x00;
	OCR0A  = 39;  					// set timer reload value (to 1.5 bit length)
	SwUartRXBitCount = 0;
	TIFR0  |= (1<<OCF0A);		   	// clear timer compare flag
	TIMSK0 |= (1<<OCIE0A);		   		// enable timer compare interrupt
}

ISR(TIMER0_COMPA_vect)
{
	OCR0A = 26;
	//char c = 0;
		if( SwUartRXBitCount < 8 )
		{
			SwUartRXBitCount++;
			SwUartRXData = (SwUartRXData>>1);   // Shift due to receiving LSB first.
			if(PIND & PIND2)
			{
				SwUartRXData |= 0x80;           // If a logical 1 is read, let the data mirror this.
			}
		}
	else
	{
		TIMSK0 &= ~( 1<< OCIE0A );
		EIFR |= (1<<INTF0);
		EIMSK |= (1<<INT0);
	}

}

 

Last Edited: Tue. Dec 15, 2015 - 12:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

Without more explicit information (compiler, libraries & etc) I am hesitant, but being an obnoxious fellow I will proceed anyway.

 

You are shifting in a '0' at every bit period, and then changing that to a '1' if PIND2 is 'true'.

 

PIND2, being defined, will always be true.

 

 

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

This is the XMEGA forum.  The ATmega328P is NOT an XMEGA.  You should have posted this in the megaAVR and tinyAVR forum.

 

Put your code in a code block.  It makes it much easier to read:

int main( void )
{
    char c = 0;
    DDRD &= ~(1<<2);
    
    TCCR0A |= (1<<WGM01);
    TCCR0B = (1<<CS00)|(1<<CS01);
    
    EICRA |= (1<<ISC01);
    EIFR |= (1<<INTF0);
    EIMSK |= (1<<INT0);
    
    sei( );

    for( ; ; )
    {
        c = SwUartRXData;
    }
}

ISR(INT0_vect) {
    
    EIMSK &= ~(1<<INT0);            // Disable external interrupt
    TIMSK0 &= ~(1<<OCIE0A);
    TCNT0 = 0x00;
    OCR0A  = 39;                           // set timer reload value (to 1.5 bit length)
    SwUartRXBitCount = 0;
    TIFR0  |= (1<<OCF0A);            // clear timer compare flag
    TIMSK0 |= (1<<OCIE0A);         // enable timer compare interrupt
}

ISR(TIMER0_COMPA_vect) 
{
    OCR0A = 26;                            // one bit length
    //char c = 0;
        if( SwUartRXBitCount < 8 )
        {
            SwUartRXBitCount++;
            SwUartRXData = (SwUartRXData>>1);   // Shift due to receiving LSB first.
            if(PIND2)
            {
                SwUartRXData |= 0x80;           // If a logical 1 is read, let the data mirror this.
            }
        }
    else
    {
        TIMSK0 &= ~( 1<< OCIE0A );
        EIFR |= (1<<INTF0);
        EIMSK |= (1<<INT0);
    }
    
}

  

 

Greg Muth

Portland, OR, US

Xplained/Pro/Mini Boards mostly

 

Make Xmega Great Again!

 

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

obs, pls remove the post, i will re-post in the right place.

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

Hi, 

Iam working on a 8 bits uP, AT328p, and try to make a software Uart receive for debugging staff. it doesnt work for me:( 

 

I use the external interrupt INT0 as receive pin, and timer0 to count bit length. My problem is that PIND2 is always getting high, i cant figure out why:(

Iam running at 16Mhz, prescaler 8, and using a external device send data at 9600N1.

 

Here is the code, pls spot the errors for me, thx in advanced.

int main( void )
{
    char c = 0;
    DDRD &= ~(1<<2);
    
    TCCR0A |= (1<<WGM01);
    TCCR0B = (1<<CS00)|(1<<CS01);
    
    EICRA |= (1<<ISC01);
    EIFR |= (1<<INTF0);
    EIMSK |= (1<<INT0);
    
    sei( );

    for( ; ; )
    {
        c = SwUartRXData;
    }
}

ISR(INT0_vect) {
    
    EIMSK &= ~(1<<INT0);            // Disable external interrupt
    TIMSK0 &= ~(1<<OCIE0A);
    TCNT0 = 0x00;
    OCR0A  = 39;                           // set timer reload value (to 1.5 bit length)
    SwUartRXBitCount = 0;
    TIFR0  |= (1<<OCF0A);            // clear timer compare flag
    TIMSK0 |= (1<<OCIE0A);         // enable timer compare interrupt
}

ISR(TIMER0_COMPA_vect) 
{
    OCR0A = 26;                            // one bit length
    //char c = 0;
        if( SwUartRXBitCount < 8 )
        {
            SwUartRXBitCount++;
            SwUartRXData = (SwUartRXData>>1);   // Shift due to receiving LSB first.
            if(PIND2)
            {
                SwUartRXData |= 0x80;           // If a logical 1 is read, let the data mirror this.
            }
        }
    else
    {
        TIMSK0 &= ~( 1<< OCIE0A );
        EIFR |= (1<<INTF0);
        EIMSK |= (1<<INT0);
    }
    
}

  

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

As pointed out in #2, PIND2 is a constant. You need to read the PIND register then mask for bit 2
If (PIND &(1<<PIND2))
......

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

Crikey it worked!!!

 

Anyway just to note that because it already had some replies I just merged the mis-placed thread in "Xmega" with this one. That does mean the question appears twice but "hey ho".

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

I did mask for bit 2, as you said (PIND&(1<<PIND2)), but it still read "high" all the time. :(

 

NOTE: I am sure the external device that sends data at 9600N1 is OK, I can receive it by the hardware UART. So it must be some errors in that code, pls help me out, kinda of getting headache from this :(

Last Edited: Tue. Dec 15, 2015 - 01:07 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Did it work for U? REALLY?

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

I did mask for bit 2, as you said (PIND&(1<<PIND2)), but it still read "high" all the time. :(

What does your voltmeter, logic probe, logic analyser or oscilloscope have to say about that?