Last updated: 28/03/2016
Objectives 1.Read a microcontroller datasheet; 2.Program your board to do something, with as many different programming languages and programming environments as possible;avrdude -c usbtiny -p t44
//importing the necessary libraries (avr/io, avr/delay)
#include < avr/io.h>
#include < avr/delay.h>
int main (void)
{
//Set PORTB to all outputs
DDRB = 0xFF;
//create an infinite loop
while(1)
{
//turns B2 HIGH
PORTB |=(1<<2);
_delay_ms(20);
//turns B2 LOW
PORTB &= ~(1 << 2);
_delay_ms(20);
};
}
The second sketch that I made included both an input and an output setup [2]. The main structural difference with the previous sketch is that, if before I did set up all the PORTB as outputs, this time I only set specific pins. Nothing much changed.
//importing the necessary libraries (avr/io, avr/delay)
#include
#include
int main(void)
{
//Button pin A7 as input
DDRA &= (1 << PA7);
PORTA |= (1 << PA7);
//LED pin B2 as output
DDRB |= (1 << PB2);
PORTB |= (1 << PB2);
//create an infinite loop
while (1)
{
//if the button is not pressed, LED is low
if (PINA & (1 << PA7))
{
PORTB &= ~(1 << PB2);
}
//if the button is pressed, LED is high
else
{
PORTB |= (1 << PB2);
}
}
}
The result is shown in the picture below.
-c usbtiny -p m328p -v -v -v -U flash:w:$(TargetDir)$(TargetName).hex:i
; Simple Blink in ASM
; Editing the work of Fiore Basile - FabAcademy 2014
; Public Domain
2.section with hardware information
; the file tn44def.inc needs to be included within the same project folder
; I have tried to make sense of that file, but I honestly can not understand what goes on there
.include "tn44def.inc"
3.ports and pins definition with symbolic names
; ports are gates from the internal CPU to the external hardware/software
; the amount of ports depends on the type of microcontroller
; ports have a fixed address to establish communication with the CPU
.equ led_pin = PB2; led pin is PB2
.equ led_port = PORTB; comm port
.equ led_dir = DDRB; comm direction
.equ led_pins = PINB; comm pins
4.constants that can be configured
; defining the variable delay
.equ delay_time = 20;
5.registers definition
; registers are storages with 8-bits capacity. In AVR registers go from R0 to R31
; registers can be renamed, which is what happens in the next 6 lines
.def bitcnt = R16; bit counter
.def temp = R17; temporary storage
.def temp1 = R18; temporary storage
.def counter1 = R20;
.def counter2 = R22;
.def counter3 = R21;
6.interrupt service routines
; CSEG and ORG are statements that I did not fully understand.
; However, I figured that the following three lines reset the interrupts handlers
.cseg
.org 0
rjmp reset
7.reset
reset:
;
; set fuse low byte to 0x7E for 20 MHz resonator
; set clock divider to /1
; CLKPR is the clock prescale register, as described on the datasheet at page 31.
ldi temp, (1 << CLKPCE)
ldi temp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0)
; store register I/O location
out CLKPR, temp
out CLKPR, temp1
8.memory definitions
; set stack pointer to top of RAM
;
ldi temp, high(RAMEND)
out SPH, temp
ldi temp, low(RAMEND)
; store register I/O location
out SPL, temp
9.main program init
; clear Bit in I/O Register
sbi led_port, led_pin
sbi led_dir, led_pin
10.program loop
loop:
; the SBI (Set Bit in I/O) instruction can be used to toggle one single bit in a port
sbi led_pins, led_pin ; toggle led pin
rcall delay
; the CBI (Clear Bit in I/O) instruction can be used to toggle one single bit in a port
cbi led_pins, led_pin
rcall delay
rjmp loop
; loads the value in delay_time on register 21
delay: ldi counter3, delay_time
;
delay1: rcall counta
dec counter3
; BRNE is branch if not equal
brne delay1
; RET is retourn from subroutine
ret
; loads the value 0 on register 20
counta: ldi counter1, 0
; the fact that the function calls itself does not make sense to me, just like it happens later with pauseb
pausea: rcall countb
dec counter1
brne pausea
ret
; loads the value 0 on register 22
countb: ldi counter2, 0
pauseb: dec counter2
brne pauseb
ret
When I had a basic understanding of what the code was doing, I proceeded with uploading it to the board. I found this tutorial where an Arduino board is used as programmer. Later I also run into Scott's repository that better helped me. The steps that I followed are:
1.Create a folder where to put the assembler file, together with the set of definitions for the ATtiny44;
2.Install the assembler AVRA
sudo apt-get install avra
3.Open the terminal and go to the directory of the .s file;
4.Simply launch the assembler
avra NAMEFILE.s
5.With the compiler AVRDUDE do the fuses and flash
sudo avrdude -p t44 -P usb -c usbtiny -U lfuse:w:0x5E:m
sudo avrdude -p t44 -P usb -c usbtiny -U flash:w:led.s.hex
Before I got point 5 to work, I failed in making the flashes a couple of times, as shown in the picture below. Appearently it was not necessary to write the full name of the COM where the board was listed.