Manage ports?

Hello I'm new in Arduino, and I have an Arduino UNO so I was testing how to program it, so I started with blinking 1 led... ok it works... so i tried to modify the code to blink 4 leds in sequence... so I thought digitalWrite(0x0F,HIGH) and it will work... also when I write the code pinMode(0x0F,OUTPUT), so I wrote and compiled with no problem... but when I uploaded the program to the Atmel... It doesn't work...

So... I tried to do by steps the full sequence and it works... take a look

int del = 100;

void setup() {                
  pinMode(0, OUTPUT); 'I think that I can reduce this 4 lines whit pinMode(0x0F, OUTPUT);
  pinMode(1, OUTPUT); 
  pinMode(2, OUTPUT); 
  pinMode(3, OUTPUT); 
}

void loop() {
  digitalWrite(0, HIGH); 'I tried to write digitalWrite(0x01,HIGH);
  delay(del);   
  digitalWrite(0, LOW);  
  digitalWrite(1, HIGH); 'digitalWrite(0x02,HIGH);
  delay(del);          
  digitalWrite(1, LOW);    
  digitalWrite(2, HIGH); 
  delay(del);  
  digitalWrite(2, LOW);    
  digitalWrite(3, HIGH);
  delay(del);          
  digitalWrite(3, LOW);
  del=del-10;
  if (del < 20)
  {
    digitalWrite(0,LOW);
    digitalWrite(1,LOW);
    digitalWrite(2,LOW);
    digitalWrite(3,LOW);
    delay(1000);
    digitalWrite(0,HIGH);
    digitalWrite(1,HIGH);
    digitalWrite(2,HIGH);
    digitalWrite(3,HIGH);
    delay(2000);
    del = 1000;
   }
}

If you noticed I had experience programming PIC in C... So i'm looking a way to reduce the amount of lines 'cos with PIC I just use the command PORT#=0X0FF or any value to change the port values but with that command doesn't work, how should do I do to reduce the lines?

It sounds like you are wanting to do direct I/O port manipulation, rather then using the arduino 'abstracted' pin numbers. Here is a reference section on doing that:

http://www.arduino.cc/playground/Learning/PortManipulation

Lefty

pinMode(), digitalRead(), digitalWrite(), analogRead() and analogWrite() work on INDIVIDUAL PINS, not on groups of pins.

pinMode(0x0F, OUTPUT) will set Pin 15 (a.k.a. Analog input 1) as an output.
digitalWrite(0x0F, HIGH) will then set Pin 15 (a.k.a. Analog input 1) to +5v.

You should avoid using Pin 0 and Pin 1 for I/O because those are the hardware serial I/O pins and you won't be able to use Serial.print() debugging messages if you use those pins for other purposes.

You can do direct port manipulation such as PORTD |= 0x3C; to turn on Pins 2,3,4 and 5. PORTD &= ~0x3C; will trurn those four pins off again.

See this spreadsheet for pin to port mapping:

Exactly! now I have another doubt respected this ports, now that I have this commands can I use for example the ADC inputs as digital inputs?

johnwasser:
pinMode(0x0F, OUTPUT) will set Pin 15 (a.k.a. Analog input 1) as an output.
digitalWrite(0x0F, HIGH) will then set Pin 15 (a.k.a. Analog input 1) to +5v.

You should avoid using Pin 0 and Pin 1 for I/O because those are the hardware serial I/O pins and you won't be able to use Serial.print() debugging messages if you use those pins for other purposes.

You can do direct port manipulation such as PORTD |= 0x3C; to turn on Pins 2,3,4 and 5. PORTD &= ~0x3C; will trurn those four pins off again.

Yes I noticed that... thank you for you explaining me how manage directly those ports...

The ADC pins can be used as Digital pins - they are D14-D19 on a 328 based arduino for example.

Thanks to all of you! It's working, I thought that arduino had the same hardware limitations than PICAXE but it doesn't its really cool program this staff XD XD

unsigned int del = 100;

void setup() {                
  pinMode(2, OUTPUT);     
  pinMode(3, OUTPUT); 
  pinMode(4, OUTPUT); 
  pinMode(5, OUTPUT); 
}

void loop() {
  PORTD |= 0X04;
  delay(del);  
  PORTD &= ~0X04; 
  PORTD |= 0X08;
  delay(del); 
  PORTD &= ~0X08;
  PORTD |= 0X10;
  delay(del);
  PORTD &= ~0X10;
  PORTD |= 0X20;
  delay(del);
  PORTD &= ~0X20;  
    del=del-10;
  if (del < 20)
  {
    delay(1000);
    PORTD |= 0X3C;
    delay(2000);
    del = 100;
    PORTD &= ~0X3C;
   }
}

NOW I ADDED AN 7 SEGMENTS DISPLAY

unsigned int del = 100;
unsigned int cuen = 0;

void setup() {                
  pinMode(2, OUTPUT);     
  pinMode(3, OUTPUT); 
  pinMode(4, OUTPUT); 
  pinMode(5, OUTPUT); 
  pinMode(8, OUTPUT);     
  pinMode(9, OUTPUT); 
  pinMode(10, OUTPUT); 
  pinMode(11, OUTPUT);   
}

void loop() {
  switch (cuen){
    case 0: PORTB &= ~0X09; PORTB |=0x00; break;
    case 1: PORTB &= ~0X00; PORTB |=0x01; break;
    case 2: PORTB &= ~0X01; PORTB |=0x02; break;
    case 3: PORTB &= ~0X02; PORTB |=0x03; break;
    case 4: PORTB &= ~0X03; PORTB |=0x04; break;
    case 5: PORTB &= ~0X04; PORTB |=0x05; break;
    case 6: PORTB &= ~0X05; PORTB |=0x06; break;
    case 7: PORTB &= ~0X06; PORTB |=0x07; break;
    case 8: PORTB &= ~0X07; PORTB |=0x08; break;
    case 9: PORTB &= ~0X08; PORTB |=0x09; break;
  }
  PORTD |= 0X04;
  delay(del);  
  PORTD &= ~0X04; 
  PORTD |= 0X08;
  delay(del); 
  PORTD &= ~0X08;
  PORTD |= 0X10;
  delay(del);
  PORTD &= ~0X10;
  PORTD |= 0X20;
  delay(del);
  PORTD &= ~0X20;  
    del=del-10;
  if (del < 20)
  {
    delay(1000);
    PORTD |= 0X3C;
    delay(2000);
    del = 100;
    PORTD &= ~0X3C;
    cuen = cuen +1;
   }
  if (cuen >9 )
  {
    cuen = 0;
   }
}

It's kind of odd inverse the port to change it to another value, but works great!

@jrlc

That is an interesting way to display a 7 segment display. I was looking for an example to use Ports in the Arduino.

Just a few questions here ....

Q1 : PORTD |= 0x04; This mean Port D .. |= OR ? <-- PORTD "OR" Hex value 4

Q2 : PORTD &= ~0x04; This mean Port D .. &= AND ? <--- PORD "AND" NOT Hex value 4

Q3: Why you put those PORTD |= or &= in your program ?

I read http://arduino.cc/en/Reference/BitwiseCompoundOr I understand some of it, but I don't understand in your program using the PORTs. I know PORTD = 0x04; or PORTD = B0100;

The part I understand is : x |= y x= x OR y if PORTD is x , what is the value of PORTD ?

? ? ? ? <--- PORTD
01 0 0 <--- 0x04
------- <--- OR
? 1 ? ? <-- The New PORTD

I am sorry for the questions here, I trying to learn.

On a binary number, the OR operation sets any bit that is a 1 in either one or the other number. The AND operation sets any bit that is 1 in both of them. THe XOR "^" sets any bit that is a 1 in one and a 0 in the other.

Let's assume portD has a state of 00011000. If we OR a 4 (00000100) the result is 00011100) We set the 3rd bitif it wasn't already, but leave all the other bits unchanged. If they are 1's 1 OR 0 = 1. If they are 0's, 0 OR 0 = 0

If we AND the inverse of a 4 (11111011) then we clear the 3rd bit if it wasn't already because this number has a 0 at that bit so the result will.
The rest will remain unchanged. 1 AND 1 = 1, 0 AND 1 = 0.

If we XOR a 4 then that third bit will get toggled. If it was already one, then we have two ones that makes a 0. If it was a 0 it will be a 1 because we have 1 of each. The bits that are XOR'ed against the zero's will be unchanged.

@Delta_G

Thank for your answer.

Let me follow your example : Port B --> 00011000
0x04 --> 00000100
OR --> 00011100

Port B --> 00011000
NOT 0x04 -> 11111011
AND -----> 00011000 So the result will be port B...OK

Techone:
Q2 : PORTD &= ~0x04; This mean Port D .. &= AND ? <--- PORD "AND" NOT Hex value 4

This construct turns bits off. Your example already had them off so that didn't show much. This shows it better:

Port B  --> 00011100
NOT 0x04 -> 11111011
AND  -----> 00011000  We have turned 0x04 off

The ~ operator is really a ones-complement (negation). This is different from twos-complement (minus).

So the ones-complement is a useful way of showing the "inverse" of a number. And if you AND in the inverse of a number, you effectively clear that number (those bits) leaving the other ones untouched.

I have mooched the port manipulation functions from wiring platform. Copy them into "wiring_digital.c" to have built-in port manipulation.

Functions

void portMode(uint8_t port, uint8_t mode)
{
	volatile uint8_t *moderegister;

	moderegister = portModeRegister(port);

	if (moderegister == NOT_A_PORT) return;

	uint8_t oldSREG = SREG;
	cli();

	//*moderegister = mode;
	if (mode == OUTPUT)
		*moderegister = 0xff;
	else
		*moderegister = 0x00;

	SREG = oldSREG;
}

uint8_t portRead(uint8_t port)
{
	volatile uint8_t *inputregister;

	inputregister = portInputRegister(port);

	if (inputregister == NOT_A_PORT) return;

	uint8_t oldSREG = SREG;
	cli();
	uint8_t portValue = *inputregister;
	SREG = oldSREG;
	return portValue;
}

void portWrite(uint8_t port, uint8_t val)
{
	volatile uint8_t *portregister;

	portregister = portOutputRegister(port);

	if (portregister == NOT_A_PORT) return;

	uint8_t oldSREG = SREG;
	cli();
	*portregister = val;
	SREG = oldSREG;
}

Example

void setup() {
  portMode(PD, OUTPUT);
}

void loop() {
  portWrite(PD, B0001000);
  delay(500);
  portWrite(PD, B0000000);
  delay(500);
}

@Nick Gammon

Thank for clearify this programing technique.

@Nadir

Nice example. But I tring to understand you example.

So Nadir,
Can those 3 functions be added to regular code also?

Do understand these correctly:

void portMode(uint8_t port, uint8_t mode)
turns all 8 pins on a port into inputs or outputs, comparable to using this 8 times:
pinMode (pinX, INPUT);
or
pinMode(pinX, OUTPUT);

uint8_t portRead(uint8_t port)
Reads a port's pin and returns a byte of data

void portWrite(uint8_t port, uint8_t val)
Sets the port's pins to the byte val

in the last 2 cases, what does
cli();
do?

@CrossRoads

cli() mean Clear Global Interrupt Flag. It in the datasheet of the ATMegainstruction.pdf from the Atmel web site.
Also in Arduino Playground - AVR

I trying to figure out the assembly language of the ATMega328 so I can apply to my programs.

As I mentioned I saw these functions in Wiring source. After testing them I put them in wiring_digital.c to make them built-in.

They works well in regular code also. But you should add "false" after return of statement "if (inputregister == NOT_A_PORT) return;"
in portRead function.

if (inputregister == NOT_A_PORT) return false;

Like that?

CrossRoads:
in the last 2 cases, what does
cli();
do?

He is protecting the port change from interrupts. So to comment it:

        uint8_t oldSREG = SREG;   // remember interrupt flag (and other flags)
	cli();          // turn interrupts off
	*portregister = val;    // do something, knowing interrupts won't occur
	SREG = oldSREG;     // put interrupt flag back (set it again, if it was set before)

Nadir:
They works well in regular code also. But you should add "false" after return of statement "if (inputregister == NOT_A_PORT) return;"
in portRead function.

You could return 0 (false is a bit misleading), but you can't tell the difference between supplying an invalid port (which returns zero) and reading a valid port, and them all being off (which returns zero).

So what should this line be then?

if (inputregister == NOT_A_PORT) return;