How would I execute this line of code with direct port Manipulation??
digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin
How would I execute this line of code with direct port Manipulation??
digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin
What are you trying to do ? (explain it with words because your code doesn't make any sense)
Really?? Someone much smarter than me wrote it.. I got it from here
http://letsmakerobots.com/content/arduino-101-timers-and-interrupts
The example code works just fine just I would like to know how to execute that line of code if using direct port manipulation. Its is an XOR operation which changes the pin state of the LED every time it is called.
/* Arduino 101: timer and interrupts
1: Timer1 compare match interrupt example
more infos: http://www.letmakerobots.com/node/28278
created by RobotFreak
*/
#define ledPin 13
void setup()
{
pinMode(ledPin, OUTPUT);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 31250; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
}
ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin
}
void loop()
{
// your program here...
}
& is the symbol for bitwise logical AND
| is the symbol for bitwise logical OR
^ is the symbol for bitwise logical XOR
^ is XOR -- true if the bits are different else false
____0___1
0___0___1
1____1___0
Learn to read hexadecimal and get the bits then learn bit manipulation.
The bitwise XOR operator is written using the caret symbol ^. This operator is very similar to the bitwise OR operator |, only it evaluates to 0 for a given bit position when both of the input bits for that position are 1:
1 1 0 0 operand1
0 1 0 1 operand21 0 0 1 (operand1 ^ operand2) - returned result
Another way to look at bitwise XOR is that each bit in the result is a 1 if the input bits are different, or 0 if they are the same.
Here is a simple code example:
int x = 12; // binary: 1100
int y = 10; // binary: 1010
int z = x ^ y; // binary: 0110, or decimal 6
The ^ operator is often used to toggle (i.e. change from 0 to 1, or 1 to 0) some of the bits in an integer expression while leaving others alone. For example:
y = x ^ 1; // toggle the lowest bit in x, and store the result in y.
I understand (somewhat) the bitwise XOR. Or are you saying that there is an error in the line of code below. Will this not toggle the stat of the pin?
I need to know how to execute this line of code with the digitalread and write functions using direct port manipulation.
digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin
I tried this with not success. LED just stays on.
#define ledPin PA4
void setup(){
DDRA = (1<<ledPin);
// initialize timer1
noInterrupts(); // disable all interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1B = 31250; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1B); // enable timer compare interrupt
interrupts(); // enable all interrupts
}
ISR(TIMER1_COMPB_vect){ // timer compare interrupt service routine
PORTA = (((PINA & (1<<ledPin)) ^ 1) << ledPin);//(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin
}
void loop(){
}
digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin
I tried this with not success. LED just stays on.
That's because there is only 3uS between ON and OFF. I don't think you can see that fast.
(hint: look at it with an Oscope on 2uS/DIV.
PINA = (1 << ledPin);
You can read and write PORTD directly. What you do with the bits in between is up to you but read before write just to preserve bits that you don't want to change. On the UNO in default, no Port has more than 6 bits open ferinstance.
You can mask bits to clear them no matter what using & or set them no matter what using |.
You can shift bits to match a single bit mask to one particular bit.
The result of logical operations returns 0 for false and 1 for true bit for bit on 2 integer variables, at least to int.
That lets you test/process a whole set of T/F operations in 1 cycle if your values are already in the CPU regs, otherwise 2 cycles to fetch each byte at 16 cycles per microsecond. It's very fast either way.
What your code does to generate the T/F bits is up to you.
DDRA = (1<<ledPin);
The chips used on the Arduino board (the ATmega8 and ATmega168) have three ports:
B (digital pin 8 to 13)
C (analog input pins)
D (digital pins 0 to 7)
DDRB - The Port B Data Direction Register - read/write
DDRC - The Port C Data Direction Register - read/write
DDRD - The Port D Data Direction Register - read/write
DDRA ? (THAT DOES NOT COMPUTE)
DDRA ? (THAT DOES NOT COMPUTE)
I am using a MEGA board.
That's because there is only 3uS between ON and OFF. I don't think you can see that fast.
(hint: look at it with an Oscope on 2uS/DIV.
The code blinks the LED at a rate of 2Hz. It is very slow. It is my attempt at direct port manipulation that contains an error.
PINA = (1 << ledPin);
Thank you. I've seen that before and actually used it but did not know that is what the OP was asking for because he described it as the XOR operation (which I'm familiar with because I worked with TTL logic chips for many years but the statement you posted looks like it is just a simple set bit. So why is the OP describing it as an XOR ?
The bitwise XOR operator is written using the caret symbol ^. This operator is very similar to the bitwise OR operator |, only it evaluates to 0 for a given bit position when both of the input bits for that position are 1:
1 1 0 0 operand1
0 1 0 1 operand21 0 0 ** 1** (operand1 ^ operand2) - returned result
Another way to look at bitwise XOR is that each bit in the result is a 1 if the input bits are different, or 0 if they are the same.
Here is a simple code example:
int x = 12; // binary: 1100
int y = 10; // binary: 1010
int z = x ^ y; // binary: 0110, or decimal 6
The ^ operator is often used to toggle (i.e. change from 0 to 1, or 1 to 0) some of the bits in an integer expression while leaving others alone. For example:
y = x ^ 1; // toggle the lowest bit in x, and store the result in y.
raschemmel:
I've seen that before and actually used it but did not know that is what the OP was asking for because he described it as the XOR operation (which I'm familiar with because I worked with TTL logic chips for many years but the statement you posted looks like it is just a simple set bit.
Some (most?) AVR processors support toggling an output by writing a one to the corresponding bit in the PIN register. Writing a zero to a bit in the PIN register has no effect.
So...
PINA = 0b00010000;
...the zeros are ignored the output associated with bit 4 (PA4) is toggled.
So why is the OP describing it as an XOR ?
It is possible to accomplish the same thing (toggling one bit / output) by reading PIN, exclusive-or the value with (1 << ledPin), then writing the result to PORT...
PORTA = (PINA ^ (1 << ledPin));
However, that line of code generates a read-modify-write sequence so it has to be executed with interrupts disabled...
ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
{
PORTA = (PINA ^ (1 << ledPin));
}
So you can write multiple bits to PINn which is far quicker than read, modify, write?
GoForSmoke:
So you can write multiple bits to PINn which is far quicker than read, modify, write?
I suspect I don't understand the question so if my answer does not make sense just try rewording your question...
Writing to PIN takes two machine instructions. One to load an 8 bit value into a register and a second to write the 8 bit value to the I/O port #.
In this case, the read-modify-write takes one to read from PIN, one to read the constant, one to perform the exclusive-or, one to write to PORT # for a total of four machine instructions.
So not "far quicker" but "a skosh quicker".
# Note: the word port is unfortunately overloaded in AVR vernacular. A "port" is not the same as a "PORT". A "port" is something the processor can read/write to manipulate hardware peripherals like timers and I/O pins. A "PORT" is a "port" used to change the output state of an I/O pin. Got that?
If you XOR a 1 with the current value, this has the effect of toggling the current value. That is what the original digitalWrite() function call which the OP was asking about, does.
I was thinking just write preset masked data to PIN to reverse the outputs long enough for a data pulse then write the same mask to PIN again to toggle the pins back. If all the pins you use start HIGH and a 1 pulse is LOW then HIGH, every complete 2-step pulse returns the pin to HIGH. Writing data to PIN sends data in 1 inverted logic pulse. It's less prone to interference that way.
So the bits that might be set have state 0 = HIGH for every pin at the start of every data pulse. Then some pins may change to LOW by being toggled and back HIGH when toggled again. Writing to PIN just uses the toggles on a known constant value, the used pins of that port that the data should be pre-filtered for.
If you want to get full 8 bit ports relatively cheap, look into building a 1284P-duino on a breadboard. If you already have a breadboard, wires and bits then a 1284P bread-duino costs less than $10. Otherwise board and parts add up and extra $5 or more, a USB-serial programmer can run $15 if you want/like support.
The 1284P has 40 pins, IIRC 3 full 8 bit ports open for use, 16K RAM, moar flash & eeprom, and 2 serial ports.
Both serial ports are capable of master-mode hardware SPI (according to ATMEL docs) allowing dedicated-device SPI for SD/mass storage. SD has to open and initialize every time it is selected. On a shared bus doing data transfer that's once per buffer. See the bottleneck? That can kill a benchmark, big time.
Writing 1s to PINx will flip those bits.
If you want more control, than this kind of aproach will let you control the state of the bits more thoroughly (in case a got flipped elsewhere):
PORTA = PORTA & 0b10111011; // clear bits 6 & 2
PORTA = PORTA | 0b0010010; // set bits 5 & 1
Where is this PORTA ? I don't see it here::