uart only sends first two bytes

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

after getting my debug problem solved and things back up and working i have had time now to start debugging my uart Tx line. my code posted below is sending a a 4byte static(currently) value with 3 bits as a sync, address and crc framing the packet. eg [sync][address][data][]data][data][data][crc]

when executing the code real time only the first two bytes are sent when tx_packet is called. if the first two bytes are commented out then it will be the following two bytes that will send. When stepping through the code in debug mode all 7 bytes will send when executed step by step.

Below is my code. Any help is as usual much appreciated!

#include 

#include "avr/interrupt.h"

#include "stdint.h"

#include "util/delay.h"



#define F_CPU 8000000UL



//define receive parameters

#define SYNC 0XAA // synchro signal

#define RADDR 0x44



volatile unsigned char torque_h, torque_l, rpm_h, rpm_l;



void init_uart() {

	//set baud rate 9600bps

	UBRR0 = 51;

	//enable Tx

	UCSR0B = 0b00001000;

	//set frame format 8,n,1

	UCSR0C = 0b00001110;

return;

}



void tx_byte(unsigned char sendbyte) {



	//wait for empty Tx buffer and reset flag if set

	if(UCSR0A & (1<<TXC0))

	{

		UCSR0A |= (1<<TXC0);

	}

	

	while ((UCSR0A & (1<<UDRE0)) !=0)

	{

		// Put data into buffer, sends the data

		UDR0 = sendbyte;

		break;

	}

return(0);

}



void tx_packet(unsigned char address) {

	unsigned char crc;

	crc =0;

	crc = torque_h + torque_l + rpm_h + rpm_l;

	//send on sync byte to initialize wireless

	tx_byte(SYNC);

	//transmit adress

	tx_byte(address);

	//send data

	tx_byte(torque_h);

	tx_byte(torque_l);

	tx_byte(rpm_h);

	tx_byte(rpm_l);



	return(0);

}





void init_ADC0() {



//ADMUX - ADC MUltiplexer Selection Register

ADMUX |= (0<<REFS1) | (1<<REFS0); //AVcc as Vref, with external capacitor at aref pin

ADMUX |= (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (0<<MUX0); //ADC0 single ended iunput



//ADCSRA - ADC Control and Status Register A

ADCSRA |= (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); //enable adc, 128 prescale

//ADCSRB - ADC Control and Status Register B

// used for auto trigger of adc, not needed for this initial test purpose

}



unsigned int read_ADC0(unsigned char average) {//average 1-63 



unsigned int reading;

unsigned char count;



reading = 0;

count = 0;



	for (count; count <= average; count++) 

	{

		ADCSRA |= (1<<ADIF); //write 1 to ADICF to clear done flag

		ADCSRA |= (1<<ADSC); //start conversion



		while (ADCSRA == (1<<ADIF));

		{

			reading += ADCL | (ADCH<<8);

		}

	}

return(reading/average);

}





 main() {



 unsigned char test2, i;



//DDRD |= (1<<PD1);// | (1<<PB1); //enable as output as RF Vcc pin



//ORTD |= (1<<PB2); // turn on teh RF chip



//Initialize ADC0

init_ADC0();

init_uart();



sei();



	torque_h = 0xFA;

	torque_l = 0x13;

	rpm_h = 0x10;

	rpm_l = 0xFF;



while(1){

	

//	test2 =0xAA;

//	tx_byte(test2);

	tx_packet(RADDR);

	

	_delay_loop_2(30000);

	

	}



return;

}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   if(UCSR0A & (1<<TXC0)) 

   { 

      UCSR0A |= (1<<TXC0); 

   } 

    

   while ((UCSR0A & (1<<UDRE0)) !=0) 

   { 

      // Put data into buffer, sends the data 

      UDR0 = sendbyte; 

      break; 

   } 

This is doing things the hard way. You don't need to look at TXC0 at all, just use UDRE0. Loop waiting for it (UDRE0) to go to 1, then write your data byte and return. I don't know if that's your problem, but try changing your tx_byte routine and see if things get better.

Mike

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

Quote:
You don't need to look at TXC0 at all
Unless you are working with half duplex comms like RS485.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly

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

js wrote:
Quote:
You don't need to look at TXC0 at all
Unless you are working with half duplex comms like RS485.

Right, I should have said "in your application".

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

about the TX0, i have that in there as i figured id try it. the operation of the uC only sending 2 butes still persists with out the TXC0 code and with slightly different variations of the code that waits until UDR0 is empty.

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

garboui wrote:
about the TX0, i have that in there as i figured id try it. the operation of the uC only sending 2 butes still persists with out the TXC0 code and with slightly different variations of the code that waits until UDR0 is empty.

Try making your baud rate 2x faster or 2x slower and see what happens. That will tell you if it's time-related.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
   while ((UCSR0A & (1<<UDRE0)) !=0)

   {

      // Put data into buffer, sends the data

      UDR0 = sendbyte;

      break;

   }

With this code, you are simply 'skipping' the data tx if the buffer is full. You need to wait when the buffer is full-

   while ((UCSR0A & (1<<UDRE0))==0); //wait here
   // buffer is ready, now send the data
   UDR0 = sendbyte;

Guess how many bytes are 'buffered' in hardware.

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

curtvm thanks for the pointers i got it going now. i was trying to skin the cat another way but now i see where it errs in the logic.

thanks

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

As an advice from a newbie who has gone through this drill, I suggest reading the tutorials before you attempt anything new. It will save you hours,days even months of time.