Skip to content

9. Embedded programming

DDRx - PORTx - PINx

The ports are bi-directional I/O ports with optional internal pull-ups. Each port pin consists of three register bits: DDxn, PORTxn, and PINxn.

According to 10.3 Register Description / ATtiny24A/44A/84A / 8183F–AVR–06/12, I choose ports that I used for my project:

Pin Configurations

  • PA7 as OUTPUT;
  • PA3 as INPUT for button switch;

Otherwise, this week I’ve got some problem with 20MHz Xtal, than I’ve other 2 free pin:

  • PB0 as 2nd OUTPUT;
  • PB1 as 3th OUTPUT.

Note

DDRB or DDRA = DATA DIRECTION REGISTER: it means the direction of this line of data it will be OUTPUT or INPUT

PORTB or PORTA = this is the line of the output data

PINB or PINA = this is the line of the input data

and Letters A / B that associate with the DDR or Port or Pin are just as name.

C for AVR microcontroller

Setting a bit

Let’s set the bit 7 to make the port pin as output. There is no direct bit set or clear instruction in ‘C’ that we can call to do this. Hence lets start with the simple binary number: 0b00000000. Now lets shift it 7 times to get 0b00000010 Now let us write that in the hex notation in a C Statement.

 DDRA = DDRA | (1 << 7);

we can also concatenate the OR operation and write as:

DDRA | =  (1 << 7);

Taking this a little further, you might want to define the number 7 as a constant, so that if LED is connected to some other pin, you may not want to change in all the places you’ve used it. Like so,

#define LED  7
DDRA | =  (1 << LED);

Clearing a bit

Now let us go ahead and clear the bit-7 and also assume this time that the DDRA value is 0b00000010 we need to obtain 0b00000000

Let’s write a this in ‘C’ statements:

#define LED 7
DDRA &= ~(1 << LED);

Checking a bit

Lots of times during programming, you will want check if a bit is set or clear. For example to check if the timer flag is set or let’s say in our example if the switch is pressed or released. Often this is accomplished by checking status of particular bit in a given register.

Lets say we want to check the status of 3th bit of PINA register. Then the status can be obtained by

status =  (PINA & (1<<mySwitch) ! = 0);

Toggling a bit

If we need to toggle the LED connected to PORTA, bit-7 as with our example it can be accomplished by XOR operation as shown. It can be summed up as

#define LED 4
PORTA ^= (1 << LED);
So every time the statement is executed the LED changes it state. This is a good option to toggle the LED on/off but I’ve not use it for my code.

My “C” Code

I’ve spent more time on assume C lenguage for AVR microcontroller and I’ve made more example to understand it. c code

So, you can download all my example files …

Now, this is my Hardware configuration on the board:

  • 1x LED on PA7
  • 1x LED on PB0
  • 1x LED on PB1
  • 1x Button on PA3

#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 8000000
int main (void)
{
    // with OR-operation set bits numbers in DDR register, make it output
    DDRA |= (1 << PA7);         
    DDRB |= (1 << PB0);
    DDRB |= (1 << PB1);

     // clear bit number 3 in DDRA register,  make it input
    DDRA &= ~(1 << PA3);   

    while (1)
    {
        if (PINA & (1 << PINA3)){    // with AND-operation check if bit 3 is set
        PORTA |= (1 << PA7);
        _delay_ms(500);
        PORTB |= (1 << PB0);
        _delay_ms(500);
        PORTB |= (1 << PB1);    // with OR-operation set bit number 2 in PORTB
    } else  {
        PORTB &= ~(1 << PB1);       // else clear bit number
        _delay_ms(500);
        PORTB &= ~(1 << PB0);
        _delay_ms(500);
        PORTA &= ~(1 << PA7);

    }
}
}

Program the board trought my FabISP programmer

This is the whole log of the process; first of all I’ve set lfuse to 0XE2 to set Int. Clock @8Mhz.

ntngr@DESKTOP-SJT4DAT MINGW64 ~/FabAcademy2019/1/5_button_leds (master)
$ make
avr-gcc -mmcu=attiny44 -Wall -Os -DF_CPU=8000000 -I./ -o buttonLeds.out buttonLeds.c
avr-objcopy -O ihex buttonLeds.out buttonLeds.c.hex;\
        avr-size --mcu=attiny44 --format=avr buttonLeds.out
AVR Memory Usage
----------------
Device: attiny44

Program:     144 bytes (3.5% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)



ntngr@DESKTOP-SJT4DAT MINGW64 ~/FabAcademy2019/1/5_button_leds (master)
$ ls
buttonLeds.c  buttonLeds.c.hex  buttonLeds.out  Makefile

ntngr@DESKTOP-SJT4DAT MINGW64 ~/FabAcademy2019/1/5_button_leds (master)
$ make program-usbtiny
avr-objcopy -O ihex buttonLeds.out buttonLeds.c.hex;\
        avr-size --mcu=attiny44 --format=avr buttonLeds.out
AVR Memory Usage
----------------
Device: attiny44

Program:     144 bytes (3.5% Full)
(.text + .data + .bootloader)

Data:          0 bytes (0.0% Full)
(.data + .bss + .noinit)


avrdude -p t44 -P usb -c usbtiny -U flash:w:buttonLeds.c.hex

avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e9207
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: reading input file "buttonLeds.c.hex"
avrdude: input file buttonLeds.c.hex auto detected as Intel Hex
avrdude: writing flash (144 bytes):

Writing | ################################################## | 100% 0.26s

avrdude: 144 bytes of flash written
avrdude: verifying flash memory against buttonLeds.c.hex:
avrdude: load data flash data from input file buttonLeds.c.hex:
avrdude: input file buttonLeds.c.hex auto detected as Intel Hex
avrdude: input file buttonLeds.c.hex contains 144 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 0.13s

avrdude: verifying ...
avrdude: 144 bytes of flash verified

avrdude done.  Thank you.


ntngr@DESKTOP-SJT4DAT MINGW64 ~/FabAcademy2019/1/5_button_leds (master)
$

My “Arduino” Code

I’ve made the same example above, but I wrote it in Arduino IDE. arduino

This is my code:

int ledpin1 = 7;         // the PWM pin the LED is attached to
int ledpin2 = 10;   
int ledpin3 = 9;   
int pushbutton = 3;     // the Analog pin the Button is attached to

// the setup routine runs once when you supply the board trought FTDI cable
void setup ()
{
  pinMode (ledpin1,OUTPUT);    // declare pin 7 to be an output
  pinMode (ledpin2,OUTPUT);    // declare pin 7 to be an output
  pinMode (ledpin3,OUTPUT);    // declare pin 7 to be an output
  pinMode (pushbutton,INPUT); // declare pin 3 to be an input
}
// the loop routine runs over and over again forever
void loop ()
{
  if( digitalRead(pushbutton)==HIGH ) // check if button is pressed
  {
   // than set time by time HIGH the ledpinX
   digitalWrite(ledpin1, HIGH);
   delay (500);
   digitalWrite(ledpin2, HIGH);
   delay (500);
   digitalWrite(ledpin3, HIGH);
   delay (500);
  }
  else if( digitalRead(pushbutton)==LOW ) // check if button is pressed
  {
   // than set time by time LOW the ledpinX
   digitalWrite(ledpin3, LOW);
   delay (500);
   digitalWrite(ledpin2, LOW);
   delay (500);
   digitalWrite(ledpin1, LOW);
   delay (500);
  }

}

Note

Using two different kind of code I can verify that, with same functions:

  1. Compiled in C code is 144 bytes of flash written;
  2. Compiled Arduino code is 956 bytes of flash written.

Test another architecture

To complete my assignment I’ve used Raspberry Pi ZeroW coding a Blinking LED through Python and python-rpi.gpio.

Raspbian Stretch

I assume that you have installed a Raspbian Stretch image on an SD card from your PC. Well, don’t remove the SD card from your computer and open the /boot directory and follow these simple steps to enable WiFi connection and SSH:

  1. in the root you must create an empty file called SSH
  2. create a file in this directory called wpa_supplicant.conf. The file should contain the following details:
    country=US # Your 2-digit country code
    ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
    network={
        ssid="YOUR_NETWORK_NAME"
        psk="YOUR_PASSWORD"
        key_mgmt=WPA-PSK
    }
    
  3. The next step is to put the micro SD card into the Pi, boot, and then try to connect via WiFi.

At this point you are connected to WiFi network and ready to enstablish an SSH connection via PuTTY software.

login as: pi
pi@192.168.2.109's password:
Linux raspberrypi 4.14.98+ #1200 Tue Feb 12 20:11:02 GMT 2019 armv6l

The programs included with the Debian GNU/Linux system are free software
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.

SSH is enabled and the default password for the 'pi' user has not been c
This is a security risk - please login as the 'pi' user and type 'passwd a new password.

Python and GPIO

once connected verify your Python version than install python-rpi.gpio as follows:

pi@raspberrypi:~ $ python --version
Python 2.7.13
pi@raspberrypi:~ $ sudo apt-get install python-rpi.gpio python3-rpi.gpio
and this is the response:
Reading package lists... Done
Building dependency tree
Reading state information... Done
python-rpi.gpio is already the newest version (0.6.5~stretch-1).
The following NEW packages will be installed:
  python3-rpi.gpio
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 23.6 kB of archives.
After this operation, 75.8 kB of additional disk space will be used.
Do you want to continue? [Y/n] y
Get:1 http://archive.raspberrypi.org/debian stretch/main armhf python3-rarmhf 0.6.5~stretch-1 [23.6 kB]
Fetched 23.6 kB in 0s (82.1 kB/s)
Selecting previously unselected package python3-rpi.gpio.
(Reading database ... 34734 files and directories currently installed.)
Preparing to unpack .../python3-rpi.gpio_0.6.5~stretch-1_armhf.deb ...
Unpacking python3-rpi.gpio (0.6.5~stretch-1) ...
Setting up python3-rpi.gpio (0.6.5~stretch-1) ...
pi@raspberrypi:~ $

Now I’ve created a file in the user pi directory called blinkingLED.py.

pi@raspberrypi:~ $ sudo nano blinkingLED.py
The file should contain the following details:
import RPi.GPIO as GPIO # Import Raspberry Pi GPIO library
from time import sleep # Import the sleep function from the time module

GPIO.setwarnings(False) # Ignore warning for now
GPIO.setmode(GPIO.BOARD) # Use physical pin numbering
GPIO.setup(8, GPIO.OUT, initial=GPIO.LOW) # Set pin 8 to be an output pin and set initial value to low (off)

while True: # Run forever
    GPIO.output(8, GPIO.HIGH) # Turn on
    sleep(1) # Sleep for 1 second
        GPIO.output(8, GPIO.LOW) # Turn off
        sleep(1) # Sleep for 1 second

Save and Exit from nano, if you used it.

Now you can test your code but remember to:

  1. Connect the anode of the LED to the pin 8
  2. Connect the cathode of the LED to the GND pin.
  3. RUN the code as mentioned below:
    pi@raspberrypi:~ $ sudo python blinkingLED.py
    
    DOWNLOAD THE PYTHON CODE