<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ca">
	<id>http://wiki.joanillo.org/index.php?action=history&amp;feed=atom&amp;title=Programaci%C3%B3_dels_microcontroladors_AVR%3A_avr-gcc</id>
	<title>Programació dels microcontroladors AVR: avr-gcc - Historial de revisió</title>
	<link rel="self" type="application/atom+xml" href="http://wiki.joanillo.org/index.php?action=history&amp;feed=atom&amp;title=Programaci%C3%B3_dels_microcontroladors_AVR%3A_avr-gcc"/>
	<link rel="alternate" type="text/html" href="http://wiki.joanillo.org/index.php?title=Programaci%C3%B3_dels_microcontroladors_AVR:_avr-gcc&amp;action=history"/>
	<updated>2026-08-30T08:44:30Z</updated>
	<subtitle>Historial de revisió per a aquesta pàgina del wiki</subtitle>
	<generator>MediaWiki 1.34.2</generator>
	<entry>
		<id>http://wiki.joanillo.org/index.php?title=Programaci%C3%B3_dels_microcontroladors_AVR:_avr-gcc&amp;diff=253443&amp;oldid=prev</id>
		<title>Joan: /* Lesson 1: A blinking LED */</title>
		<link rel="alternate" type="text/html" href="http://wiki.joanillo.org/index.php?title=Programaci%C3%B3_dels_microcontroladors_AVR:_avr-gcc&amp;diff=253443&amp;oldid=prev"/>
		<updated>2015-06-03T07:51:46Z</updated>

		<summary type="html">&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Lesson 1: A blinking LED&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Pàgina nova&lt;/b&gt;&lt;/p&gt;&lt;div&gt;=Referències=&lt;br /&gt;
A Brief Tutorial on Programming the AVR without Arduino&lt;br /&gt;
*https://www.mainframe.cx/~ckuethe/avr-c-tutorial/&lt;br /&gt;
&lt;br /&gt;
Programming the AVR microcontroller with GCC, libc 1.0.4&lt;br /&gt;
*http://tuxgraphics.org/electronics/200411/article352.shtml&lt;br /&gt;
&lt;br /&gt;
AVR Microcontrollers in Linux HOWTO&lt;br /&gt;
*http://www.tldp.org/HOWTO/Avr-Microcontrollers-in-Linux-Howto/x207.html&lt;br /&gt;
&lt;br /&gt;
Segueixo el primer manual.&lt;br /&gt;
&lt;br /&gt;
Quick explanation per entendre la programació dels xips:&lt;br /&gt;
*http://stackoverflow.com/questions/20993661/c-avr-simple-portb-ddrb-pinb-explanation&lt;br /&gt;
&lt;br /&gt;
=Tutorial=&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo apt-get install gcc-avr&lt;br /&gt;
$ sudo apt-get install avr-libc&lt;br /&gt;
$ sudo apt-get install avrdude&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
==Lesson 1: A blinking LED==&lt;br /&gt;
[[Fitxer:IMG 20150602 133122805.jpg | thumbnail]]&lt;br /&gt;
'''NOTA''': en la foto s'ha utilitzat el port D.&lt;br /&gt;
&lt;br /&gt;
'''NOTA'''. També he seguit aquet tutorial, que ha funcionat, i que per fer el ''delay'' el codi és una mica diferent:&lt;br /&gt;
*http://www.micahcarrick.com/tutorials/avr-microcontroller-tutorial/getting-started.html&lt;br /&gt;
&lt;br /&gt;
'''NOTA''': també s'ha fet proves de fer pampallugues a un LED a: [[Atmel_ISP_MCU_programmer_ATmega._Programador_AVR_USBasp#Blink_LED]]&lt;br /&gt;
&lt;br /&gt;
El meu xip és el Atmega168 de 28 pins:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1    PC6 - PCINT14, Reset [RESET]&lt;br /&gt;
2    PD0 - PCINT16, RXD [PIN0]&lt;br /&gt;
3    PD1 - PCINT17, TXD [PIN1]&lt;br /&gt;
4    PD2 - PCINT18, INT0 [PIN2]&lt;br /&gt;
5    PD3 - PCINT19, INT1, OC2B [PIN3]&lt;br /&gt;
6    PD4 - PCINT20, XCK, T0 [PIN4]&lt;br /&gt;
7    VCC&lt;br /&gt;
8    GND&lt;br /&gt;
9    PB6 - PCINT6, XTAL1, TOSC1&lt;br /&gt;
10    PB7 - PCINT7, XTAL2, TOSC2&lt;br /&gt;
11    PD5 - PCINT21, OC0B, T1 [PIN5/PWM]&lt;br /&gt;
12    PD6 - PCINT22, OC0A, AIN0 [PIN6/PWM]&lt;br /&gt;
13    PD7 - PCINT23, AIN1 [PIN7]&lt;br /&gt;
14    PB0 - PCINT0, CLKO, ICP1 [PIN8]&lt;br /&gt;
15    PB1 - PCINT1, OC1A [PIN9/PWM]&lt;br /&gt;
16    PB2 - PCINT2, OC1B, SS [PIN10/PWM]&lt;br /&gt;
17    PB3 - PCINT3, OC2A, MOSI [PIN11/PWM]&lt;br /&gt;
18    PB4 - PCINT4, MISO [PIN12]&lt;br /&gt;
19    PB5 - PCINT5, SCK [PIN13] LED&lt;br /&gt;
20    AVCC&lt;br /&gt;
21    AREF&lt;br /&gt;
22    GND&lt;br /&gt;
23    PC0 - PCINT8, ADC0 [ANALOG0]&lt;br /&gt;
24    PC1 - PCINT9, ADC1 [ANALOG1]&lt;br /&gt;
25    PC2 - PCINT10, ADC2 [ANALOG2]&lt;br /&gt;
26    PC3 - PCINT11, ADC3 [ANALOG3]&lt;br /&gt;
27    PC4 - PCINT12, ADC4, SDA [ANALOG4]&lt;br /&gt;
28    PC5 - PCINT13, ADC5, SCL [ANALOG5]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''lesson1.c''':&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Assumptions:&lt;br /&gt;
 * 	- LED connected to PORTB&lt;br /&gt;
 * 	- F_CPU is defined to be your cpu speed (preprocessor define)&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
int main (void)&lt;br /&gt;
{&lt;br /&gt;
	/* set PORTB for output*/&lt;br /&gt;
	DDRB = 0xFF;&lt;br /&gt;
&lt;br /&gt;
	while (1) {&lt;br /&gt;
		/* set PORTB high */&lt;br /&gt;
		PORTB = 0xFF;&lt;br /&gt;
		_delay_ms(500);&lt;br /&gt;
&lt;br /&gt;
		/* set PORTB low */&lt;br /&gt;
		PORTB = 0x00;&lt;br /&gt;
		_delay_ms(500);&lt;br /&gt;
	}&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
'''NOTA''': DDRB significa ''Data Direction Register for port B''&lt;br /&gt;
&lt;br /&gt;
Ja puc compilar el codi:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ avr-gcc -g -mmcu=atmega168 -c lesson1.c -Wa,-alh,-L -o lesson1.o &amp;gt; lesson1.asm&lt;br /&gt;
In file included from lesson1.c:11:0:&lt;br /&gt;
/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h:90:3: warning: #warning &amp;quot;F_CPU not defined for &amp;lt;util/delay.h&amp;gt;&amp;quot;&lt;br /&gt;
/usr/lib/gcc/avr/4.5.3/../../../avr/include/util/delay.h:95:3: warning: #warning &amp;quot;Compiler optimizations disabled; functions from &amp;lt;util/delay.h&amp;gt; won't work as designed&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es generen els fitxers de sortida, però amb warnings.&lt;br /&gt;
&lt;br /&gt;
És lògic que doni el primer warning: protesta perquè no sap a quina freqüència treballarà el uC, i per tant no sap calcular el delay. Falta ficar dalt de tot, abans dels include:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
   #define F_CPU 8000000UL     &lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
(comprovar quin és el valor correcte per al Atmega168).&lt;br /&gt;
Veure una discussió a:&lt;br /&gt;
*http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=88000&lt;br /&gt;
&lt;br /&gt;
El segon warning es soluciona ficant l'opció -Os:&lt;br /&gt;
*http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=70042&lt;br /&gt;
&lt;br /&gt;
Continuo amb la compilació:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ avr-gcc -g -mmcu=atmega168 -Wl,-Map,lesson1.map -o lesson1.elf lesson1.o&lt;br /&gt;
$ avr-objdump -h -S lesson1.elf &amp;gt; lesson1.lst&lt;br /&gt;
$ avr-objcopy -j .text -j .data -O ihex lesson1.elf lesson1.hex&lt;br /&gt;
$ avr-size lesson1.elf&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
S'ha generat el ftixer hex, que ja puc gravar al xip amb el programador que tinc:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ cat lesson1.hex&lt;br /&gt;
:100000000C9434000C9449000C9449000C94490061&lt;br /&gt;
:100010000C9449000C9449000C9449000C9449003C&lt;br /&gt;
:100020000C9449000C9449000C9449000C9449002C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo avrdude -b19200 -P usb -c usbasp -p m168 -U flash:w:lesson1.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Jugant amb els fuses. Càlcul correcte de la freqüència==&lt;br /&gt;
Resumint, per compilar el meu codi les comandes són:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avr-gcc -g -mmcu=atmega168 -Os -c lesson1.c -Wa,-alh,-L -o lesson1.o &amp;gt; lesson1.asm&lt;br /&gt;
avr-gcc -g -mmcu=atmega168 -Wl,-Map,lesson1.map -o lesson1.elf lesson1.o&lt;br /&gt;
avr-objdump -h -S lesson1.elf &amp;gt; lesson1.lst&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex lesson1.elf lesson1.hex&lt;br /&gt;
avr-size lesson1.elf&lt;br /&gt;
&lt;br /&gt;
sudo avrdude -p m168 -P usb -c usbasp -Uflash:w:lesson1.hex -B 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===use intern i que divideixi per 8===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-U lfuse:w:0x62:m -U hfuse:w:0xdf:m&lt;br /&gt;
$ sudo avrdude -p m168 -P usb -c usbasp -U lfuse:w:0x62:m -U hfuse:w:0xdf:m&lt;br /&gt;
RC Osc 8MHz&lt;br /&gt;
Divide clock by 8 internally; [CKDIV8=0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
per tant el resultat és 1 MHz&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
   #define F_CPU 1000000UL     &lt;br /&gt;
#endif &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
va bé, 1 blink cada segon&lt;br /&gt;
&lt;br /&gt;
===Fuse intern i que divideixi per 8===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
   #define F_CPU 8000000UL     &lt;br /&gt;
#endif &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
va molt lent, el led intermitent. 10 blinks, 78 segons. Ara la freq ha de quedar dividit per 8: 1 blink cada 8 segons. Amb 70 segons són 78*1/8 = 9,75 blinks&lt;br /&gt;
&lt;br /&gt;
===Fuse intern i que no divideixi per 8===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-U lfuse:w:0xe2:m -U hfuse:w:0xdf:m&lt;br /&gt;
$ sudo avrdude -p m168 -P usb -c usbasp -U lfuse:w:0xe2:m -U hfuse:w:0xdf:m&lt;br /&gt;
&lt;br /&gt;
RC Osc 8MHz&lt;br /&gt;
NOT Divide clock by 8 internally; [CKDIV8=0]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
per tant treballa a 8MHz, i en el programa li dic que el uC està treballant a 8MHz:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
   #define F_CPU 8000000UL     &lt;br /&gt;
#endif &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I ara el resultat és correcte, torno a trobar que el blink és cada segon&lt;br /&gt;
&lt;br /&gt;
===Cristall extern de 16MHz===&lt;br /&gt;
Fins ara he fet proves amb l'oscil.lador intern. Ara faré proves amb un cristall extern de 16MHz&lt;br /&gt;
&lt;br /&gt;
Llegeixo a http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=71917&amp;amp;view=previous:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
You will want CKOPT programmed for 16mhz. &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Però per al Atmega168 aquesta opció no hi és.&lt;br /&gt;
&lt;br /&gt;
sense tenir en compte el fuse extended, queda:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-U lfuse:w:0x62:m -U hfuse:w:0xdf:m&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Per a cristalls d'alta freqüència (com ara 16MHz) és convenient retrassar el start-up time.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo avrdude -p m168 -P usb -c usbasp -U lfuse:w:0x62:m -U hfuse:w:0xdf:m&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
   #define F_CPU 2000000UL   (fico 2000000 en comptes de 16000000 perquè hi ha el divide per 8)&lt;br /&gt;
#endif &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
40 blinks, 80 segons. Per tant, és un blink cada 2 segons, la meitat de freqüència de lo esperat. Això és lògic, perquè l'opció del fuse és 8MHz (no hi ha opció 16Mhz). Com que jo li poso un cristall de 16MHz treballa el doble de ràpid, i per tant en el #define jo li he de dir que vagi la meitat de lent:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
   #define F_CPU 1000000UL&lt;br /&gt;
#endif &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Efectivament, ara sí que fa pampellugues cada segon. Però fixem-nos que el resultat que he ficat (1000000UL) és el mateix que si tingués un cristall de 8MHz. I això confirma la idea de què quan selecciono cristall extern de 8MHz en realitat vol dir ''de 8Mhz o més''.&lt;br /&gt;
 &lt;br /&gt;
==Interface USB-joystick: usb_game12-1.0==&lt;br /&gt;
el projecte està disponible per a Atmega8. Si jo vull programar amb el Atmega168 i 16MHz, quins canvis s'hauran de fer? El projecte està realitzat a:&lt;br /&gt;
*[[Controlador_USB_per_a_joystick_i_botons_MAME]]&lt;br /&gt;
on ha funcionat correctament amb la configuració Atmel8/12MHz i Atmel168/16MHz.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make&lt;br /&gt;
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -c usbdrv/usbdrv.c -o usbdrv/usbdrv.o&lt;br /&gt;
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -x assembler-with-cpp -c usbdrv/usbdrvasm.S -o usbdrv/usbdrvasm.o&lt;br /&gt;
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -c usbdrv/oddebug.c -o usbdrv/oddebug.o&lt;br /&gt;
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -c main.c -o main.o&lt;br /&gt;
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -c twelve.c -o twelve.o&lt;br /&gt;
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -c devdesc.c -o devdesc.o&lt;br /&gt;
avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega8 -DF_CPU=12000000L  -o main.bin usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o twelve.o devdesc.o -Wl,-Map=main.map&lt;br /&gt;
rm -f main.hex main.eep.hex&lt;br /&gt;
avr-objcopy -j .text -j .data -O ihex main.bin main.hex&lt;br /&gt;
./checksize main.bin&lt;br /&gt;
ROM: 2560 bytes (data=58)&lt;br /&gt;
RAM: 134 bytes&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Compila sense problemes per a atmega8, i es genera el fitxer .hex, que és el que interessa per cremar el xip amb avrdude.&lt;br /&gt;
&lt;br /&gt;
Si canvio les comandes ''atmega8'' per ''atmega168'', falla la 4a comanda:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ avr-gcc -Wall -Os -Iusbdrv -I. -mmcu=atmega168 -DF_CPU=12000000L  -c main.c -o main.o&lt;br /&gt;
main.c: In function ‘hardwareInit’:&lt;br /&gt;
main.c:123:2: error: ‘TCCR0’ undeclared (first use in this function)&lt;br /&gt;
main.c:123:2: note: each undeclared identifier is reported only once for each function it appears in&lt;br /&gt;
main.c:125:2: error: ‘TCCR2’ undeclared (first use in this function)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Important llegir: swithcing from atmeg8 to atmega168&lt;br /&gt;
*http://forums.obdev.at/viewtopic.php?f=8&amp;amp;t=2360&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
means the code was written for an AVR that has a register called &amp;quot;TCCR0&amp;quot; and your one does not.&lt;br /&gt;
Note that the OP's register name is TCCRO, with a capital O letter rather than a zero, which is invalid on every AVR model. &lt;br /&gt;
&lt;br /&gt;
The registers are defined through proper use of &amp;lt;avr/io.h&amp;gt;. If they are not defined, then you are doing something wrong. You need to specify the AVR you are using in the project settings.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Es soluciona fent els següents canvis en els noms dels registres en el fitxer main.c:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TCCR0 to TCCR0B&lt;br /&gt;
TCCR2 to TCCR2B&lt;br /&gt;
TIFR to TIFR0 &lt;br /&gt;
OCR2 to OCR0A&lt;br /&gt;
OCF2 to OCF0A&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I ara ja puc compilar per al atmega168. N'hi ha prou en editar el fitxer ''Makefile'' i canviar ''atmega8'' per ''atmega168''.&lt;br /&gt;
&lt;br /&gt;
En el fitxer ''Makefile'' també he de canviar aquesta línia per dir quin és el meu AVR i quin és el meu programador:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
flash_usb:&lt;br /&gt;
        sudo avrdude -p m168 -P usb -c usbasp -Uflash:w:$(HEXFILE) -B 1.0 &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
I ja puc gravar el nou hex file:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ make flash_usb&lt;br /&gt;
sudo avrdude -p m168 -P usb -c usbasp -Uflash:w:main.hex -B 1.0&lt;br /&gt;
&lt;br /&gt;
avrdude: set SCK frequency to 750000 Hz&lt;br /&gt;
avrdude: warning: cannot set sck period. please check for usbasp firmware update.&lt;br /&gt;
avrdude: AVR device initialized and ready to accept instructions&lt;br /&gt;
&lt;br /&gt;
Reading | ####&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{Autor}}, febrer 2014&lt;/div&gt;</summary>
		<author><name>Joan</name></author>
		
	</entry>
</feed>