Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Logica AtmeL

Raccolta di codici sorgenti

Moderatore: Foto UtentePaolino

0
voti

[1] Logica AtmeL

Messaggioda Foto Utentebelva87 » 3 nov 2012, 14:42

Salve a tutti, scrivo in questa sezione in merito al primo approccio che ho avuto con un AT90USB646 della AtmeL.
Piccola premessa, ho avuto esperienza passata con i PIC in particolare il famosissimo 16F84 e 16F876 durante le scuole superiori (solo in terzo anno purtroppo) e programmazione in assembly (per i PIC) e più in generale in Pascal.
Devo dire che non èro un "drago" ma me la sono sempre cavata bene sia con il Pascal che con la programmazione a basso livello del PIC. All'università ho studiato il VHDL (che non è un vero e proprio linguaggio, tipo C o l'assembler) e il C ma l'uso ne è rimasto "su carta" perciò direi ... molta teoria e poca pratica purtroppo.
Da un po' di tempo ormai avevo nel cassetto la schedina "Pierin" progettata da Foto UtenteTardoFreak.
Ho installato Visual Studio 5 e il programmino Flip, copiato il codice da un esempio preso dal blog del nostro compagno di forum senza preoccuparmi di comprenderlo per il momento, fatto il build e programmato il micro, resettato e... tutto ok, funziona. Questo mi è servito per avere un codice funzionante e quindi escludere errori nel montaggio della PCB, nella saldatura del microcontrollore (anche se ho ricontrollato con il microscopio) e varie ed eventuali, insomma per partire con un hardware "abile e arruolato".
A questo punto mi sono detto, bene adesso tocca a me scrivere il codice, in C, perciò mi sono andato a leggere il datasheet e ho voluto far accendere il led, proprio come il codice testato precedente faceva.
Adesso la prima difficoltà, non capisco la logica di funzionamento dell'assegnazione dei pin...
Mi spiego meglio, nel PIC per alzare un pin indicavo prima nel registro TRIS che quel pin deve essere di uscita, e poi assegno al bit 3, per sempio, di PORTA il valore 1 scrivendo RB3 = 1 ... mentre qui se provo a farlo il compilatore mi da errore... se invece scrivo (1 << PINA3) funziona tutto... non riesco a comprendere questa cosa :(
Qualcuno sa aiutarmi? se necessario posto il codice e qualsiasi altra cosa serva, scusate se sono stato prolisso ma penso sia necessario.

Grazie a tutti in anticipo.
Avatar utente
Foto Utentebelva87
2.292 2 6 12
free expert
 
Messaggi: 1323
Iscritto il: 9 mag 2011, 15:01

0
voti

[2] Re: Logica AtmeL

Messaggioda Foto Utentesimo85 » 3 nov 2012, 15:07

La logica di configurazione I/O è contraria ai PIC, comunque si, posta il codice.

Non c'è nemmo bisogno dello shift etc, basta assegnare un valore, o usare gli operatori bit a bit. Io uso sempre quelli esadecimali..

Per il resto il C non cambia. vedi anche il sito delle avr-libc.
Avatar utente
Foto Utentesimo85
30,9k 7 12 13
Disattivato su sua richiesta
 
Messaggi: 9927
Iscritto il: 30 ago 2010, 4:59

2
voti

[3] Re: Logica AtmeL

Messaggioda Foto UtenteTardoFreak » 3 nov 2012, 16:16

Nella libreria del compilatore i pin di I/O del micro non sono definiti, non hanno un campo corrispondente al bit come invece hanno fatto quelli della Microchip.
Per accendere il bit 3 della porta B puoi fare:
Codice: Seleziona tutto
PORTB ^= 0x08;

che corrisponde poi a:
Codice: Seleziona tutto
PORTB = PORTB ^ 0x08;

PINB3 è definito come
Codice: Seleziona tutto
#define PINB3 3

e quindi l' espressione
Codice: Seleziona tutto
(1 << PINB3)

da come risultato un 1 shiftato a sinistra di 3 bit e quindi 0x08

Piaccia ricordare che essendo sia l' "1" che PINB3 delle costanti l' operazione (1<<PINB3) viene risolta dal compilatore che ti mette già il numero calcolato. Non va quindi a far fare operazioni al micro.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[4] Re: Logica AtmeL

Messaggioda Foto Utentebelva87 » 4 nov 2012, 11:59

TardoFreak ha scritto:Nella libreria del compilatore i pin di I/O del micro non sono definiti, non hanno un campo corrispondente al bit come invece hanno fatto quelli della Microchip.

Ah ecco, questa non la sapevo... c'è un perché la AtmeL ha optato per questa scelta? Si fa per capire e conoscere non per criticare, è solo che nella mia testa è forte ancora la logica dei PIC.
Riporto di seguito il codice che ho testato:

Codice: Seleziona tutto
#include <avr/io.h>
#include <avr/wdt.h>
#include <avr/delay.h>

void main(void)
{   
   MCUSR = (0 << WDRF); // mette a 0 il bit WDRF del registro MCUSR, disabilita watchdog
   wdt_disable();  // se non lo scrivo funziona uguale!!??
   DDRA = 0xff;    // imposto la porta A come uscita scrivendo tutti 1 dentro il registro DDRA
   _delay_ms(1000);   // aspetto per avere tempo dopo il reset
   PORTA = (1 << PINA0) ;  // scrivo 1 nel registro PORTA in posizione di PINA0, led on
   while(1) // non faccio piu niente bloccando il micro in un loop sempre vero
   {   
   }   
}   

Così funziona, se invece scrivo:

Codice: Seleziona tutto
void main(void)
{   
   MCUSR = (WDRF = 0); // mette a 0 il bit WDRF del registro MCUSR, disabilita il watchdog
   wdt_disable();  // se non lo scrivo funziona uguale!!??
   DDRA = 0xff;    // imposto la porta A come uscita scrivendo tutti 1 dentro il registro DDRA
   _delay_ms(1000);   // aspetto per avere tempo dopo il reset
   PORTA = (PINA0 = 1) ;  // scrivo 1 nel registro PORTA in posizione di PINA0, led on
   while(1) // non faccio piu niente bloccando il micro in un loop sempre vero
   {   
   }   
}

Non funziona!

Appurato questo non riesco a capire "la logica" e la sequenza degli operatori che scrivi nelle indicazioni:
TardoFreak ha scritto:
Codice: Seleziona tutto
PORTB ^= 0x08;

che corrisponde poi a:
Codice: Seleziona tutto
PORTB = PORTB ^ 0x08;

PINB3 è definito come
Codice: Seleziona tutto
#define PINB3 3

e quindi l' espressione
Codice: Seleziona tutto
(1 << PINB3)


Potresti darmi una spiegazione più "terra terra" come si dice :mrgreen:
Purtroppo sono un tipo che non ha capito come funziona quello che usa, lo abbandona... oppure rimane piantato li fino a che non capisce! Non mi va di fare il ragionameno "vabè ho visto che così quel codice funziona, vado avanti..."
Se non riesco tramite questo forum, e quindi rompendo le balle a voi, esiste un documento della atmel che spiega come "ragiona" il loro approccio??
Credo che il mio problema sia entrare nella loro ottica per poi prendere dimestichezza con la scrittura, o sbaglio anche altre cose? Non fatevi scrupoli anzi, preferisco atterrare sul duro ma capire che il morbido.

Ho un'ultima domanda, ammettendo di riuscire a comprendere questa ottica e di iniziare a padroneggiare i pin del micro senza difficoltà, è possibile scrivere una libreria "di proprio pugno" in modo da fare come ha fatto Microchip?? cioè definire direttamente i singoli pin?? Chiedo questo perché leggendo in rete, e mi è anche stato confermato poi da due programmatori professionisti uno dei quali fa parte di quessto forum..., è importante scrivere un insieme di librerie che permette una "elevazione" del livello di scrittura del codice in modo indipendente dalla macchina, così chè se si deve far migrare il codice da un micro ad un altro basta cambiare opportunamente la libreria creata e fare piccoli adattamenti invece che cominciare un progetto nuovo.... ed è quello che vorrei raggiungere come prima cosa.

Grazie a tutti e scusate ancora per la lunghezza del post, prometto che la volta prossima non sarà così e non vi romperò le balls di domenica :mrgreen:
Avatar utente
Foto Utentebelva87
2.292 2 6 12
free expert
 
Messaggi: 1323
Iscritto il: 9 mag 2011, 15:01

1
voti

[5] Re: Logica AtmeL

Messaggioda Foto UtenteTardoFreak » 4 nov 2012, 13:48

L' espressione
Codice: Seleziona tutto
PORTA = (PINA0 = 1)

Si traduce in: Alla variabile PORTA viene assegnato il valore dell' espressione di assegnazione che assegna il valore di '1' alla variabile PINA0, e che da come risultato 1.
Quindi ci sta come la bagna caoda sul tiramisù. Ed è anche sbagliato scrivere così. Strano che il compilatore non ti abbia dato un errore.

Ciò detto,
Per mettere a 0 o a 1 una linea di uscita, come ti ho detto prima, si setta o resetta il bit corrispondente.
Questo lo si fa con tutti i micro.
Poi qualcuno ha pensato bene di fare delle struct con i bit per rendere la cosa più semplice, come ha fatto Microchip ma la cosa non ha importanza anche perché, se si vogliono scrivere buoni programmi, di solito si scrivono delle funzioni o delle di set e reset delle linee di I/O.

Mi spiego meglio,
Supponiamo che io abbia un uscita collegata ad un LED e che la chiamo LED1 che collego al bit 3 della PORTB che si accende quando questa va ad 1 perché l' ho collegato a massa attraverso una resistenza.

Io devo poterlo inizializzare, accendere e spegnere.
La cosa più saggia da fare è scrivere tre funzioni (o tre macro ma non corriamo troppo eh! :mrgreen: )
- Funzione per l' inizializzazione
- Funzione per l' accensione
- Funzione per lo spegnimento

E quindi scriveremo (lo scrivo in modo esteso), assumendo che LED1 sia collegato a PORTB3 e verso massa.
Codice: Seleziona tutto
void LED1on(void)
{
  PORTB = PORTB | 0x04;
}

void LED1off(void)
{
  PORTB = PORTB & 0xF7;
}

void LED1init(void)
{
  DDRB = DDRB | 0x04;
  // Spegne il LED
  LED1off();
}

All' inizio del programma inizializzarò il LED1 chiamando la funzione LED1init().
Per accendere il LED1 chiamerò la funzione LED1on();
Per spegnere il LED1 chiamerò la funzione LED1off();

Queste tre funzioni sembrano uno spreco di codice ma hanno una funzione e un' utilità ben precisa. -:-
Infatti supponiamo che abbia un programma enorme dove questo cacchio di LED viene acceso e spento un casino di volte, in un casino di posti in giro per il programma.
Ora sfiga vuole (perché se la fortuna è cieca la sfiga ci vede benissimo :mrgreen: ) che devo cambiare pin e, invece di pilotarlo direttamente, devo accendere un pannello che di led ne monta 50 ma devo usare un PNP perché l' uscita della porta non mi permette di pilotare direttamente il transistor di potenza. ||O ||O ||O
Bada bene che questo non è il classico caso limite ma queste cose succedono sempre. :(

Se ho usato questo sistema in un paio di minuti ho risolto tutto semplicemente modificando le tre funzioncine delle balle in:
Codice: Seleziona tutto
void LED1on(void)
{
  PORTA = PORTA & 0xBF;
}

void LED1off(void)
{
  PORTA = PORTA | 0x40;
}

void LED1init(void)
{
  DDRA = DDRA | 0x40;
  // Spegne il LED
  LED1off();
}


Spero di aver chiarito il concetto che riassumo brevemente: fregatene di come fare ad accendere o spegnere i bit, usa il sistema più semplice ma scrivi le funzioni per non ritrovarti poi nei casini se devi cambiare qualcosa a programma finito.

PS: questo è un semplicissimo e banale esempio di astrazione hardware, di realizzazione di quello che è chiamato HAL (Hardware Abstraction Level) che serve per svincolare il programma dal circuito.
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[6] Re: Logica AtmeL

Messaggioda Foto Utentexyz » 4 nov 2012, 15:51

belva87 ha scritto:c'è un perché la AtmeL ha optato per questa scelta?


Il compilatore C utilizzato dal IDE del Atmel per gli AVR non è un compilatore proprietario ma si tratta di un compilatore open source multi piattaforma il GCC, questo compilatore (in realtà in questo caso è un cross-compiler) è un compilatore ANSI C, rispetta il più possibile gli standard anche se ha delle estensioni proprietarie. Il compilatore C della MicroChip ha delle estensioni non standard nella sintassi C per leggere e assegnare i bit di un registro, qualsiasi altro compilatore ANSI C segnalerebbe un errore di sintassi.

Il GCC è in grado di riconoscere le operazioni sui bit con una sintassi ANSI C e genera il codice assembler opportuno per pilotare i singoli bit nei registri evitando di utilizzare istruzioni più lente o registri temporanei aggiuntivi.

Il codice che non funziona che hai proposto non può essere compilato, sicuramente ti ha segnato un grave errore di sintassi.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

1
voti

[7] Re: Logica AtmeL

Messaggioda Foto UtenteTardoFreak » 4 nov 2012, 18:20

Se a qualcuno interessa qui di seguito ci sono alcune macro (stile arduino :roll: ) per inizializzare i bit delle porte da mettere all' inizio del sorgente o in un file .h
Codice: Seleziona tutto
// Macro per la manipolazione delle linee di I/O

// Inizializzazione come bit di OUTPUT
#define IOinitOutput(porta,bit) DDR##porta |= 1 << 0##bit

// Inizializzazione come bit di INPUT
#define IOinitInput(porta,bit) DDR##porta &= (1 << 0##bit)^0xff

// Inizializzazione come bit di INPUT con PULL-UP
#define IOinitInputPU(porta,bit) { DDR##porta &= (1 << 0##bit)^0xff; PORT##porta |= 1<<0##bit; }

// Set Bit
#define IOsetBit(porta,bit) PORT##porta |= 1<<0##bit

// Reset Bit
#define IOresetBit(porta,bit) PORT##porta &= (1<<0##bit)^0xff

// Lettura ingresso
#define IOreadBit(porta,bit) PIN##porta &= (1<<0##bit)^0xff


Supponiamo di avere il LED1 collegato A PB3. Le macro di cui sopra si usano in questo modo:
Codice: Seleziona tutto
void main(void)
{
  // Inizializza PB3 come output
  IOinitOutput(PORTB,3);
 
  while(1)
  {
    // Spegne il LED
    IOresetBit(PORTB,3);
   
    // Accende il LED
    IOsetBit(PORTB,3);
  }
}


Ma sarebbe meglio usarle così:
Codice: Seleziona tutto
#define LED1_PORT PORTB
#define LED1_BIT 3

void main(void)
{
  // Inizializza LED1 come output
  IOinitOutput(LED1_PORT,LED1_BIT);
 
  while(1)
  {
    // Spegne il LED1
    IOresetBit(LED1_PORT,LED1_BIT);
   
    // Accende il LED1
    IOsetBit(LED1_PORT,LED1_BIT);
  }
}


O_/
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

0
voti

[8] Re: Logica AtmeL

Messaggioda Foto Utentebelva87 » 4 nov 2012, 22:41

xyz ha scritto:Il codice che non funziona che hai proposto non può essere compilato, sicuramente ti ha segnato un grave errore di sintassi.


No, nessun errore! Niente di niente, genera perfettamente il file HEX e Flip lo carica senza problemi nel micro.

Ora sono davvero sfinito per concentrarmi sulle vostre risposte, però ho notato che la mia difficoltà è "più di base", o almeno penso... a quando sarò in grado di intendere e di volere :mrgreen:
Grazie comunque.
Avatar utente
Foto Utentebelva87
2.292 2 6 12
free expert
 
Messaggi: 1323
Iscritto il: 9 mag 2011, 15:01

0
voti

[9] Re: Logica AtmeL

Messaggioda Foto Utentexyz » 4 nov 2012, 23:51

belva87 ha scritto:No, nessun errore! Niente di niente, genera perfettamente il file HEX e Flip lo carica senza problemi nel micro.

Sicuro ? Quale compilatori usi ? Con il GCC per AVR dal 4.0 al 4.7 genera i seguenti errori:

Codice: Seleziona tutto
test.c:7: error: invalid lvalue in assignment
test.c:11: error: invalid lvalue in assignment

Il seguente codice:
Codice: Seleziona tutto
MCUSR = (WDRF = 0)

con la definizone della macro:
Codice: Seleziona tutto
#define WDRF 3

qualsiasi compilatore C degno di questo nome genera per forza un errore.
Avatar utente
Foto Utentexyz
6.864 2 4 6
G.Master EY
G.Master EY
 
Messaggi: 1778
Iscritto il: 5 dic 2009, 18:37
Località: Italy Turin

0
voti

[10] Re: Logica AtmeL

Messaggioda Foto UtenteTardoFreak » 5 nov 2012, 0:16

Confermo.
Codice: Seleziona tutto
PORTA = (PINA0 = 1) ;

Genera:
error: lvalue required as left operand of assignment
"La follia sta nel fare sempre la stessa cosa aspettandosi risultati diversi".
"Parla soltanto quando sei sicuro che quello che dirai è più bello del silenzio".
Rispondere è cortesia, ma lasciare l'ultima parola ai cretini è arte.
Avatar utente
Foto UtenteTardoFreak
73,9k 8 12 13
-EY Legend-
-EY Legend-
 
Messaggi: 15754
Iscritto il: 16 dic 2009, 11:10
Località: Torino - 3° pianeta del Sistema Solare

Prossimo

Torna a Firmware e programmazione

Chi c’è in linea

Visitano il forum: Nessuno e 17 ospiti