AVR Input and Output
The Penguino is powered by an ATMega32A AVR Micro-controller. This is an overview of how to achieve digital input and output on the Penguino AVR.
Ports and Pins
The Penguino has 8 pins per port and four ports. Each pin on each port can be connected internally in various ways, depending on how certain registers are configured in the micro-controller software.
All pins on all ports can function as either general purpose digital I/O or have their own special purpose(s).
The available pins and ports and their extra functionality on the Penguino are as follows:
Port |
Pin |
Special Purpose |
A |
0 to 7 |
Analog to Digital Conversion (ADC) |
B |
7 |
SPI bus serial clock (SCK) |
6 |
SPI bus Master Input/Slave Output (MOSI) |
|
5 |
SPI bus Master Output/Slave Input (MISO) |
|
4 |
SPI bus Slave Select Input (SS, inverted) |
|
3 |
Analog Comparator - Negative Input (AIN1), Timer/Counter 0 Output Compare Match Output (OC0) |
|
2 |
Analog Comparator - Positive Input (AIN0), External Interrupt 2 Input (INT2) |
|
1 |
Timer/Counter1 External Counter Input (T1) |
|
0 |
Timer/Counter0 External Counter Input (T0) |
|
D* |
7 |
Timer/Counter2 Output Compare Match Output (OC2) |
6 |
Timer/Counter1 Input Capture Pin (ICP1) |
|
5 |
Timer/Counter1 Output Compare A Match Output (OC1A) |
|
4 |
Timer/Counter1 Output Compare B Match Output (OC1B) |
|
3 |
External Interrupt 1 Input (INT1) |
|
2 |
External Interrupt 0 Input (INT0) |
|
C* |
1 |
Two-wire Serial Bus Data Input/Output Line (SDA) |
0 |
Two-wire Serial Bus Clock Line (SCL) |
- *Special purpose pins from ports C and D are used internally for JTAG and UART over USB. Ports C and D can be combined to make a full third port.
Configuring pins for their special purpose is not covered on this page.
General Purpose I/O Registers
Each pin on each port can be configured to act as a general-purpose digital I/O pin. Each port has three registers used to configure its digital I/O functionality in software. Each register holds an 8-bit number with each bit of this number corresponding to a pin on the port. e.g. bit 0 of the number in the PORTA register refers to the first pin on the physical port A of the device.
The registers are (where x denotes the port letter A to D):
- DDRx
- Data Direction Register: which pins on this port are inputs or outputs? (pin bit set to 0 for input, 1 for output)
- PORTx
- If an output: which pins on this port are set to high (1, true), which pins are set to low (0, false)
- If an input: which pins on this port are pulled up to Vcc via a resistor, and which pins are floating inputs (more on this later)
- PINx
- Input value of the port: which pins on this port are reading as high, which are reading as low
Examples
C-code (avr-gcc) for setting ports:
DDRA = 0xFF; // Configure all pins on port A as output (all bits set to 1) PORTA = 0xFF; // Set all pins on port A to be a sourcing voltage (set to high) PORTA = 0x00; // Set all pins on port A to be grounded (set to low) PORTA = PORTA | 4; // Set pin 2 (the third pin, as 4 in binary is 100) to high DDRB = 0xF0; // Configure the first 4 pins as input, the last 4 pins as output PORTB = 0x00; // Make the first 4 pins floating (as they're inputs), the last 4 pins set to low int x = PINB & 4; // x will be 1 if the third pin (4 in binary is 100) is sensed as high
PORTx Register for Inputs
When a pin is set as an input (in the DDRx register), it can be operating in two input modes:
- bit is set to 0: floating, 'tri-state', or 'high impedance'
- bit is set to 1: pull-up resistor enabled
floating inputs:
If the pin's bit in the PORTx register is 0, then the pin won't be connected anywhere except to the sensing/reading internal circuitry. If the pin is not connected to anything in the external circuitry, this pin's value (PINx register) will fluctuate randomly from environmental noise. If it is grounded, the pin will have the value 0, if it's connected to the operating voltage, it will have the value 1.
pulled-up inputs:
If the pins bit in the PORTx register is 1, then the pin will be connected to Vcc (the operating voltage) via an internal resistor (pull-up resistor). This means that the default value for the pin, when not connected to anything is high (1). In order to change the value, the pin must be grounded to set the value low (0). This is especially convenient for connecting to switching devices (push-buttons, etc.).
In Summary
Output bit n on port x:
- DDRx bit n set to 1
- Write value to bit n of PORTx
Floating input bit n on port x:
- DDRx bit n set to 0
- PORTx bit n set to 0
- Read value from bit n of PINx
Pull-up input bit n on port x:
- DDRx bit n set to 0
- PORTx bit n set to 1
- Read value from bit n of PINx
Example Program
Imagine LEDs connected to pin 0 and 1 of port B, and a button on pin 2
leds will start with one off, one on and will alternate, until the button is pressed when they will synchronise and flash together.
1 #include <avr/io.h>
2 #include <util/delay.h>
3
4 #define PIN0 1
5 #define PIN1 2
6 #define PIN2 4
7
8 int main(void) {
9 DDRB &= ~PIN2; // set pin 2 to be an input
10 DDRB |= PIN0 | PIN1; // set pin 0 and 1 to be outputs
11
12
13 PORTB = PIN2; // set pin 2 to be a pull-up, set everything else to 0 (outputs are low)
14
15 PORTB |= PIN1; // set pin 1 to high (turn led on)
16
17 // while pin 2 of port B is high (button hasn't been pressed)
18 while ( PINB & PIN2 ) {
19 PORTB ^= PIN0 | PIN1; // flip the bits (toggle leds on/off)
20 _delay_ms( 500 ); // busy wait for a bit
21 }
22
23 // button pressed
24 PORTB |= PIN0 | PIN1; // turn both leds on
25
26 // forever
27 while ( 1 ) {
28 PORTB ^= PIN0 | PIN1; // flip the bits (toggle leds on/off)
29 _delay_ms( 500 ); // busy wait for a bit
30 }
31
32 return 0;
33 }
![icy [labs]](/moin_static171/common/wikilogo.png)