Go Down

### Topic: I need some code translated for me. (Read 1 time)previous topic - next topic

##### Dec 16, 2011, 08:39 pm
This code was posted 2 or 3 years ago from AVR freaks and the user is probably moved on. Therefore, I have been trying to understand what is going on line by line. I know that the user is pulsing the TX pin high and low for specific delay times but, I am having trouble understanding the lines that look like bit shifting and compounding. Basically, anywhere there are things that look like "bitwise" code, I get confused.

If someone would have time to do something like...///"this line he is compound x and y to get x(y)"
Or other wise say TX_PORT &= ~_BV(TX_BIT);  ///"this line means this".

I would be grateful for any help or direction to help me understand what this code is doing.

Thanks,
Mark

Code: [Select]
Sure, here is the init function. I just send address 0x33 and
my Accord's ECU responded correctly. I didn't bother using the UART
for such a slow baud, just software bit toggling.

Code:

uint8_t i;
uint8_t temp;

/* idle high */
TX_PORT |= _BV(TX_BIT);
TX_DDR  |= _BV(TX_BIT);

/* required idle delay w0 (2ms), be safe with 4ms */
_delay_ms(4);

/* start bit */
TX_PORT &= ~_BV(TX_BIT);
/* this is at 5bps */
_delay_ms(200);

/* send byte */
for (i = 0; i < 8; i++) {
temp = (addr >> i) & 0x01;
if (((TX_PORT & _BV(TX_BIT)) >> TX_BIT) == temp) {
/* already at the correct level, do nothing */
} else {
if (0 != temp) {
TX_PORT |= _BV(TX_BIT);
} else {
TX_PORT &= ~_BV(TX_BIT);
}
}
_delay_ms(200);
}

TX_PORT |= _BV(TX_BIT);
_delay_ms(200);

/* already idling high on TX */

return;
}
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

#### Jack Christensen

#1
##### Dec 16, 2011, 10:51 pm
From the avr-libc user manual (get it here):

Quote
11.6 What is all this _BV() stuff about?
When performing low-level output work, which is a very central point in microcontroller
programming, it is quite common that a particular bit needs to be set or cleared
in some IO register. While the device documentation provides mnemonic names for
the various bits in the IO registers, and the AVR device-specific IO definitions reflect
these names in definitions for numerical constants, a way is needed to convert a bit
number (usually within a byte register) into a byte value that can be assigned directly
to the register. However, sometimes the direct bit numbers are needed as well (e. g. in
an SBI() instruction), so the definitions cannot usefully be made as byte values in the
first place.

So in order to access a particular bit number as a byte value, use the _BV() macro.
Of course, the implementation of this macro is just the usual bit shift (which is done
by the compiler anyway, thus doesn't impose any run-time penalty), so the following
applies:
_BV(3) => 1 << 3 => 0x08

However, using the macro often makes the program better readable.
"BV" stands for "bit value", in case someone might ask you. :-)

Example: clock timer 2 with full IO clock (CS2x = 0b001), toggle OC2 output on
compare match (COM2x = 0b01), and clear timer on compare match (CTC2 = 1). Make
OC2 (PD7) an output.
TCCR2 = _BV(COM20)|_BV(CTC2)|_BV(CS20);
DDRD = _BV(PD7);

So, the following statement clears the TX_BIT in the TX_PORT register. Refer to the datasheet to understand the register and bit mnemonics. Not sure which datasheet to refer you to, as TX_PORT and TX_BIT aren't in the few AVR datasheets that I'm familiar with.
Code: [Select]
TX_PORT &= ~_BV(TX_BIT)

#### AWOL

#2
##### Dec 16, 2011, 11:22 pm
TX_PORT could be any port register, I'm guessing, because it looks like the code is just, doing bit-banging.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

#3
##### Dec 17, 2011, 02:19 am

Thank you Jack Christensen! You have solved the BV mystery that I was hung up in! I followed your link for the manual and found the quote for BV on page 77. I am that much wiser now.

@Awol, I think you are correct about the TX_PORT being a general define for a port register. I wasn't sure about it but, when it would not compile I suspected it as a variable that needed defined somewhere.

Thanks you guys have gotten me closer to understanding how to put this to use.
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

#### Jack Christensen

#4
##### Dec 17, 2011, 03:44 am
Glad to help. I was puzzled by the _BV thing at first too. Now I find I use it...

#### WizenedEE

#5
##### Dec 17, 2011, 10:29 pm
Code: [Select]

uint8_t i;
uint8_t temp;

/* idle high */
TX_PORT |= _BV(TX_BIT); // digitalWrite(TX_BIT on TX_PORT, HIGH);
TX_DDR  |= _BV(TX_BIT); // pinMode(TX_BIT on TX_PORT, OUTPUT);

/* required idle delay w0 (2ms), be safe with 4ms */
_delay_ms(4); //delay(4);

/* start bit */
TX_PORT &= ~_BV(TX_BIT); // digitalWrite(TX_BIT on TX_PORT, LOW);
/* this is at 5bps */
_delay_ms(200); // delay(200);

/* send byte */
for (i = 0; i < 8; i++) { // go 8 times
temp = (addr >> i) & 0x01;  //temp is the i-th bit of addr
if (((TX_PORT & _BV(TX_BIT)) >> TX_BIT) == temp) { // if (digitalRead(TX_BIT) == temp)
/* already at the correct level, do nothing */
} else {
if (0 != temp) { // if temp isn't 0
TX_PORT |= _BV(TX_BIT); //digitalWrite(TX_BIT, HIGH);
} else {
TX_PORT &= ~_BV(TX_BIT); //digitalWrite(TX_BIT, LOW);
}
}
_delay_ms(200); //delay(200);
}

TX_PORT |= _BV(TX_BIT); //digitalWrite(TX_BIT, HIGH);
_delay_ms(200);  //delay(200);

/* already idling high on TX */

return;
}

The entire thing is essentially a copy of shiftOut()

#### AWOL

#6
##### Dec 17, 2011, 10:52 pm
...but without the clock.

The start and stop bits are something of a give away.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

#### WizenedEE

#7
##### Dec 17, 2011, 10:57 pm

...but without the clock.

The start and stop bits are something of a give away.

Code: [Select]

#8
##### Dec 18, 2011, 02:21 am

Thank you WizenedEE for taking the time to comment every part of that code! I looked up shiftOut() and I can see the similarity.
I am going to take parts of the code and do some tests with an led and see if I can see it in action.

@Awol thanks for pointing out the "without the clock" part, I found what you mean in the shift() tutorial.

I will try to make good use of this new knowledge, thanks again!
General Arduion tutorials = http://tronixstuff.wordpress.com
http://www.gammon.com.au/forum/bbshowpost.php?bbtopic_id=123

Go Up

Please enter a valid email to subscribe