RXEN, TXEN... How to access these defines

Hi all,

I want to understand some of the examples of the serial communication, but several examples refer to special constants that name a bit in a reg, like RXEN or TXEN.

I assume that these bits may differ regarding to the used board, so it would be fine to get a safe access to them.

Which include do I have to use to get a valid definition of these constants.

Sorry for asking such a primitive thing, but I searched now two hours without any result. Of course I found some includes but I am not sure if I can use them.

I used #include <avr/io.h> w/o any success.

Thank you for helping a newbie :slight_smile:

Cheers Alexander

First of all, different constants may be defined for different boards. When you include <io.h> here's what happens: Arduino uses a command line switch that tells the compiler which processor to use and the compiler translates this to include something special.

If you tell Arduino that it's working with a "Duemilanove w/ ATmega328" board, the file that gets included from <io.h> is <iom328p.h>

Look in that file and you see register definitions and bit position definitions for the various memory-mapped ports. Compare register names and bit names in that file with I/O terminology in the '328 data sheet.

#include <avr/io.h>

void setup()
{
    Serial.begin(9600);
}

void loop()
{
    char buffer[60];
    sprintf(buffer, "Bit positions: RXEN0 = 0x%02x, TXEN0 = 0x%02x\n", RXEN0, TXEN0);
    Serial.print(buffer);
    delay(5000);
}

Look in the Arduino core file SerialHardware.cpp to see how these are used in initializing Serial class objects and how they are used to check UART status and read and write.

Output:


Bit positions: RXEN0 = 0x04, TXEN0 = 0x03

Regards,

Dave

Thank you Dave,

in most examples is only the constant RXEN (for example) used. You used RXEN0. I assume that the zero refers to a special UART. Did I get that right? But most examples merely use RXEN (for instance).

I looked at the datasheet and defined them myself but it certainly makes sense to use io.h.

Cheers Alexander

Did I get that right?

Look in the file <avr/iom328p> that I mentioned. In fact the '328 has one hardware UART, but ATmel tends to make the code for processors in a given family look similar. Since many '328 folks also use (or graduate to) '1280 devices that have four UARTs, I guess they just made the '328 look like a "subset" of the '1280 and used RXEN0 for the '328 instead of the (more logical) RXEN. (When you compile for the '1280, the compiler includes <avr/iom1280.h>, which includes <avr/iomxx0_1.h>, which actually contains definitions for RXEN0, RXEN1, etc.)

most examples...

Could you give us an example of one of the "most examples" that uses RXEN (and tell us what processor it is using). I mean, the ATmega8 uses RXEN, but the 168 and 328 use RXEN0. The 1280 uses RXEN0, RXEN1, RXEN2, RXEN3.

These little details are hidden from the naive Arduino user who uses libraries supplied in the Arduino distribution (see HardwareSerial.cpp for example). The user is "protected" from knowing what actually goes on behind the curtain in the magical, mystical land of Oz ArduinOz.

For more inquisitive minds, it takes a little detective work, but for some of us it's really (really) worth it to know exactly where the bits come from and where they go.

Regards,

Dave

Thank you,

here is at least one:
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1243894373

I also found others that were not Arduino related.

But your answer gives clarity to me: it has to be RXEN0 and I'll do that. I'm still lerning :slight_smile: Thank you for your patience :slight_smile:

Cheers Alexander

Cheers Alexander

here is at least one:

Well, that thread is before my time (I only started playing with my little Ardweeny five or six weeks ago, before saving up enough to buy a Genuine Duemilanove a month or so ago), but the example, is incorrect for current releases of Arduino. See Footnote.

Bottom line: That example is for some previous version of Arduino (arduino-0016, I think). As for the "code lifted from serial_wiring.h," well, there is no serial_wiring.h in the current release. That functionality is (apparently) now in the HardwareSerial core library.

The problem is that when new guys ask about stuff that has previously been covered on the forum, some of the more senior members (and even some of the not-so-senior ones) castigate the "newbie" for not using the Search feature on the forum. Then, when Good Citizens like yourself find old stuff (it's only a year old, for goodness sake), it gets confusing.

My philosophy: It's always OK to ask. (But maybe that's just me, and I have absolutely no juice around here.)

not Arduino related

If the examples were for earlier versions of avr-gcc/avr-libc, then they might have used other headers that had different definitions. I can't really say...

Regards,

Dave

Footnote:
One of the advantages of being a new guy is that I am starting with arduino-0018, and don't have to worry about porting any legacy code from previous releases or worry about whether I should upgrade to the latest version.

Thank you Dave for your fine reply :slight_smile:

You described perfectly the "Forum Catch 22" ;D

Cheers Alexander

The problem also shows up in some of the user contributed libraries in the Arduino playground section. Some such contributors have moved on and have not updated their code if required to support newer IDE upgrades. Not an easy solution and of course can be a real stumbling block for newcomers.

Lefty

Lefty, so true. But still: if a newbie like me is welcome to ask these questions (which I was pretty reluctant to do) everyting works out in the end.

BTW: Maybe some expert can look over that code: sending works perfect but I'm not able to receive a valid ack from the box:

#include <stdio.h>
#include <avr/io.h>

#define TX_COMPLETE (1<<TXC0)
#define GETCHAR_TIMEOUT_us 500000  // 50ms timeout bei Getchar

int lastJetiAnswer;

void jetiUartInit(void) {
  Serial.begin(9600);          // Set correct baud rate with Arduino Lib
  PORTD=0x03;                  //UART RX->PD0, TX->PD1
  DDRD=0x00;                   // Set all to input
  UCSR0A=0x00;
  UCSR0B=0x1C;
  UCSR0C=B00111110; // 00=asynch, 11=Odd, 1 1Stop, 11 9 Bit , 0 default
  UCSR0B &= ~(1<<TXEN0);  //disable TX   
  // UCSR0B &= ~(1<<RXEN0);  //disable RX   
  UCSR0B |= (1<<RXEN0);   //enable RX 
}

void JetiTransmitByte(unsigned char data, boolean setBit9)
{
  if (setBit9 == true)
    UCSR0B |= (1<<TXB80); // Set Bit 9
  else
    UCSR0B &= ~(1<<TXB80);    //delete 9th Bit
  /* Put data into buffer, sends the data */
  UDR0 = data;
  while ((UCSR0A & TX_COMPLETE)==0); //wait for TX complete
  UCSR0A |= TX_COMPLETE; //clear TXC Flag
}


unsigned char JetiSensor(char line1[17], char line2[17], char alarmCode)
{
  unsigned char ack;
  int i;
  UCSR0B |= (1<<TXEN0);  //enable TX 

  // Send Alarm Code first, if alarmcode <> 0
  if (alarmCode != 0) {
    JetiTransmitByte(0x7E, false);
    JetiTransmitByte(0x92, false);
    JetiTransmitByte(0x23, false);
    JetiTransmitByte(alarmCode, true);
  }
  
  // 34 Byte Data Package
  JetiTransmitByte(0xFE, false);
  for (i=0; i<16; i++) JetiTransmitByte(line1[i], true);
  for (i=0; i<16; i++) JetiTransmitByte(line2[i], true);
  JetiTransmitByte(0xFF, false);    
  JetiTransmitByte(0x00, false);    
  
  UCSR0B &= ~(1<<TXEN0);  //disable TX
//  UCSR0B &= ~(1<<RXEN0);  //disable RX   
//  UCSR0B |= (1<<RXEN0);   //enable RX 

  ack = JetiGetChar();
  if (ack == 14) ack = JetiGetChar();
  return ack;
}

unsigned char JetiGetChar(void)
{
  unsigned long time = micros();
  byte stat, erg;
  /* Wait for data to be received */
  while ( (UCSR0A & (1<<RXC0)) == 0 )
  {
    if (micros()-time >  GETCHAR_TIMEOUT_us) 
      return 12; // return, if timout occures
  }
  /* Get and return received data from buffer */
  stat = UCSR0A;
  erg = UCSR0B; // first bit 9: discard
  erg = UDR0;
  if ( stat & (1<<FE0) ) return 13;
  if ( stat & (1<<DOR0) ) return 14;
  if ( stat & (1<<UPE0) ) return 15;
  
  return erg;
}

void setup(void) {
  jetiUartInit();
  lastJetiAnswer= 99;
}

void loop(void) {
  int i, bytecount;
  char line1[17] = "FLAPS: UP       ";  // 17: allow \0 at the end
  char line2[17] = "GEAR : DOWN     ";
  char alarm1[17] = "ALARM  LINE 1   ";
  char alarm2[17] = "ALARM  LINE 2   ";
  char msg[10] = "     ";
  char tm[10] = "     ";

  sprintf(msg, "%u----", lastJetiAnswer);
  sprintf(tm, "%u-----", millis()/1000);
  for (i=0; i<4; i++) {
    if (tm[i] < 32) tm[i]=32;
    line1[i+12] = tm[i];
  }

  for (i=0; i<4; i++) {
    if (msg[i] < 32) msg[i]=32;
    line2[i+12] = msg[i];
  }

  // Senden
  if (millis()/1000 % 10 != 0)
    lastJetiAnswer = JetiSensor(line1, line2, 0);
  else {
    // lastJetiAnswer = JetiSensor(alarm1, alarm2, 'B');
    // delay(1000); // leave the alarm on the display
  }
  delay(20);

}

This is a connection to a "Jeti Box" which I will use for telemtry in my RC project. This code does nothing else but sending a certain data package over and over again and after sending the package it should read what the box answeres.

The com is a little weird: 9600 9E1. They obviously need the 9th bit as a control bit.

Plus this is a one wire communication: the only serial line is connected to the RX pin 0. Pin 0 to Pin 1 (RX to TX) is shortened with a 100 Ohm resistor to prevent any destructive current.

Sending works perfect. But I don't receive a valid ack. Tried everything. Double and triple checked the registers. No way. I also asked a friend who works on a similiar project (but not with Arduino). He also has no idea.

Any ideas most welcome. Thank you very much for having a look at the code!

Cheers Alexander

Hi all,

I want to understand some of the examples of the serial communication, but several examples refer to special constants that name a bit in a reg, like RXEN or TXEN.

Regarding the last question I finally found the solution: when using Arduino Board that have USB on board such a connection with a commin RX/TX line does not work. The RX/TX on the Arduino are internally connected to the USB.

I now used a Mini Pro 328 that has no USB on board and it works like a charm :slight_smile:

Cheers Alexander