Salve a tutti, sono fresco fresco d' iscrizione.
Ho un dubbio da porvi:
sto programmando, con un Programmatore ATMEL (l' STK500), un micro (ATMEGA8515L, quello base che si trova nel kit) con l'intendo di avere dei "delay", cioè dei momenti in cui il micro non esegue operazioni, di tempo randomico.
Uso come Compilatore l' "AVR-Studio 4" che, scritto il codice con relative librerie ".h" inserite per il "delay_ms" e il "rand", non da problemi di Debug (0 errori, 0 warning).
Una volta flashata la memoria del micro (con la EEPROM è uguale), è come se questo non riuscisse ad eseguire l'operazione ed in un ciclo "while(1)" che racchiude tutto il codice, tutte le operazioni dopo l'istruzione "int a=rand();" per esempio, non vengono eseguite.
ESEMPIO DEL CODICE:
********************************************************************************************
#include <avr/io.h>
#define F_CPU 1000000UL // 1 MHz
#include <util/delay.h> //libreria per il "delay"
#include <util/delay_basic.h>
#include <stdlib.h> //libreria per il "rand"
#define DirectionPortLED DDRC
#define LED_ON PORTC
#define msec 100
void InitializeLED()
{
DirectionPortLED = 0xFF;
LED_ON = 0xFF;
}
int main(void)
{
int tot;
double tot_1;
InitializeLED();
while(1){
PORTC = 0b11111111; //spengo tutti i LED
_delay_ms(msec);
PORTC = 0b11111110; //accendo il primo LED
_delay_ms (msec);
tot=rand()%100; //così prendo num tra 0 e 99.
tot_1=(double)tot; //delay vuole in ingresso un double
PORTC = 0b11111101; //accendo il secondo LED
_delay_ms (tot_1);
}
}
********************************************************************************************
Quindi le operazioni dopo il rand() non vengono eseguite, MA iterativamente, le prime (spegnere tutti i led ed accendere il primo) si.
NON CAPISCO--> AIUTO!
funzione rand() su scheda STK500 (ATMEL)
Moderatore: Paolino
10 messaggi
• Pagina 1 di 1
1
voti
Io sto usando un'Atmega16 (molto simile al tuo micro) e con questo codice (modificato partendo dal tuo) non ho nessun problema:
Il codice puoi usarlo direttamente sul tuo micro senza modificare niente.
Come vedi, ho semplificato il codice, ho usato le notazioni esadecimali per assegnare i valori alle porte e ho sistemato le linee per ottenere il numero casuale con una semplice istruzione:
Solo una domanda, nel tuo codice, per accendere il LED, imposti il bit a 0. Sei sicuro che per il tuo circuito sia corretto? Considerando che in questo caso penso non abbia molta importanza, ma se usi un circuito come questo:
ottieni l'accensione "inversa", cioè quando tu nei commenti scrivi che accendi, in realtà spegni, e viceversa.
La cosa è diversa, invece, se usi questo circuito:
allora i commenti sono corretti.
Spero di esserti stato d'aiuto
- Codice: Seleziona tutto
/*
* RandomDelay.c
*
* Created: 17/03/2012 22:04:44
* Author: Giacky98
*/
#include <avr/io.h>
#define F_CPU 1000000UL // 1 MHz
#include <util/delay.h> //libreria per il "delay"
#include <stdlib.h> //libreria per il "rand"
#define LEDDDR DDRC
#define LEDPORT PORTC
#define msec 100
void Init(void)
{
LEDDDR = 0xFF; // Imposto la porta C come uscita
LEDPORT = 0xFF; // Spengo tutti i LED
}
int main(void)
{
int d; // La variabile che conterrà il numero casuale
Init(); // Inizializzo la porta del LED come uscita
while(1){
LEDPORT = ~0x00; // Spengo il primo LED
_delay_ms(msec); // Delay
LEDPORT = ~0x01; // Accendo il primo LED
_delay_ms(msec); // Delay
d = (int)(rand()%100); // Ottengo un valore casuale da 0 a 99
LEDPORT = ~0x02; // Accendo il secondo LED
_delay_ms(d); // Delay (tempo casuale)
}
return 0; // Non serve a niente ma bisogna metterlo
}
Il codice puoi usarlo direttamente sul tuo micro senza modificare niente.
Come vedi, ho semplificato il codice, ho usato le notazioni esadecimali per assegnare i valori alle porte e ho sistemato le linee per ottenere il numero casuale con una semplice istruzione:
- Codice: Seleziona tutto
d = (int)(rand()%100);
Solo una domanda, nel tuo codice, per accendere il LED, imposti il bit a 0. Sei sicuro che per il tuo circuito sia corretto? Considerando che in questo caso penso non abbia molta importanza, ma se usi un circuito come questo:
ottieni l'accensione "inversa", cioè quando tu nei commenti scrivi che accendi, in realtà spegni, e viceversa.
La cosa è diversa, invece, se usi questo circuito:
allora i commenti sono corretti.
Spero di esserti stato d'aiuto
0
voti
Ti ringrazio innanzi tutto per la chiarezza e meticolosità con il quale mi hai risposto.
Venendo al dunque: ho provato a copiare il codice direttamente come tu mi hai riportato, ma quello che accade è che il 1° LED si accende con il suo delay (dato da #DEFINE), ma il secondo no.
Per tagliare la testa al toro ho scritto l'istruzione "d=(int)(rand()%100)" all'inizio del ciclo while(1) e, dopo la programmazione del micro con tal codice, ho tristemente visto che, COME SCRITTO SUL PRIMO messaggio POSTO SUL FORUM, sembra quasi che tale micro non sia in grado di fare la funzione "rand()".
Pensi sia cosa plausibile?
Mi informerò un po' in rete comunque.
Grazie mille delle informazioni.
Massimo
Venendo al dunque: ho provato a copiare il codice direttamente come tu mi hai riportato, ma quello che accade è che il 1° LED si accende con il suo delay (dato da #DEFINE), ma il secondo no.
Per tagliare la testa al toro ho scritto l'istruzione "d=(int)(rand()%100)" all'inizio del ciclo while(1) e, dopo la programmazione del micro con tal codice, ho tristemente visto che, COME SCRITTO SUL PRIMO messaggio POSTO SUL FORUM, sembra quasi che tale micro non sia in grado di fare la funzione "rand()".
Pensi sia cosa plausibile?
Mi informerò un po' in rete comunque.
Grazie mille delle informazioni.
Massimo
-
massimonanni86
0 3 - Messaggi: 5
- Iscritto il: 17 mar 2012, 13:55
0
voti
Ho velocemente cercato in rete se qualcuno ha avuto qualche problema relativo all'uso di rand() sul tuo Atmega, ma non ho trovato niente.
Quindi i casi sono 2:
o il micro è danneggiato, dal punto di vista hardware;
o c'è qualche errore nel software.
Nel primo caso, l'unico modo è sostituire il micro.
Nel secondo, ci sono principalmente due fattori che possono causare il problema: potrebbe essere un errore di codice (che magari sul mio Atmega16 funziona ma sul tuo no anche se non capisco perché) oppure un problema di compilazione.
Riguardo a quest'ultimo, volevo sapere, stai usando le ottimizzazioni del codice? Se sì, a che livello?
Quindi i casi sono 2:
o il micro è danneggiato, dal punto di vista hardware;
o c'è qualche errore nel software.
Nel primo caso, l'unico modo è sostituire il micro.
Nel secondo, ci sono principalmente due fattori che possono causare il problema: potrebbe essere un errore di codice (che magari sul mio Atmega16 funziona ma sul tuo no anche se non capisco perché) oppure un problema di compilazione.
Riguardo a quest'ultimo, volevo sapere, stai usando le ottimizzazioni del codice? Se sì, a che livello?
0
voti
No, non so nemmeno cosa tu intenda per "ottimizzazione del codice".. magari risulterò un po' un novello, ma non si finisce mai di imparare! :) :) :)
-
massimonanni86
0 3 - Messaggi: 5
- Iscritto il: 17 mar 2012, 13:55
0
voti
Non preoccuparti, fino a un mese fa non sapevo neanch'io cos'era
Adesso non ti so dare una definizione perfetta, ma ti posso brevemente dire che l'ottimizzazione è un'operazione che compie il compilatore (avr-gcc) prima di effettuare la compilazione vera e propria. L'ottimizzazione consiste nel ridurre parti di codice in cui ci sono istruzioni in eccesso o rimuovere automaticamente variabili non necessarie, per esempio.
Oltre ad essere utile per ridurre la dimensione del programma, è anche utile per far funzionare meglio certe procedure. Per esempio, la libreria <util/delay.h> produce un Warning se l'ottimizzazione non è abilitata.
Per selezionare il livello di ottimizzazione (-O1, -O2, ...), da AVR Studio fai click destro sul progetto (nella finestra di esplorazione a destra) e fai "Properties". Si aprono le proprietà del progetto. Da qui mi sembra devi andare sulla scheda Toolchain e trovare la voce Compiler Optimization o Code Optimization. Da qui puoi impostare il livello.
Probabilmente adesso le ottimizzazioni saranno disabilitate, prova a mettere un'ottimizzazione di secondo livello (-O2), compilare e caricare il codice.
Adesso non ti so dare una definizione perfetta, ma ti posso brevemente dire che l'ottimizzazione è un'operazione che compie il compilatore (avr-gcc) prima di effettuare la compilazione vera e propria. L'ottimizzazione consiste nel ridurre parti di codice in cui ci sono istruzioni in eccesso o rimuovere automaticamente variabili non necessarie, per esempio.
Oltre ad essere utile per ridurre la dimensione del programma, è anche utile per far funzionare meglio certe procedure. Per esempio, la libreria <util/delay.h> produce un Warning se l'ottimizzazione non è abilitata.
Per selezionare il livello di ottimizzazione (-O1, -O2, ...), da AVR Studio fai click destro sul progetto (nella finestra di esplorazione a destra) e fai "Properties". Si aprono le proprietà del progetto. Da qui mi sembra devi andare sulla scheda Toolchain e trovare la voce Compiler Optimization o Code Optimization. Da qui puoi impostare il livello.
Probabilmente adesso le ottimizzazioni saranno disabilitate, prova a mettere un'ottimizzazione di secondo livello (-O2), compilare e caricare il codice.
0
voti
Nemmeno con il terzo livello di ottimizzazione il risultato è lo stesso!
Dai, ti ringrazio ugualmente per il tuo aiuto!
Proverò ad acquistare un altro micro, magari prima di essermi informato da qualche ex docente dell'università!
-
massimonanni86
0 3 - Messaggi: 5
- Iscritto il: 17 mar 2012, 13:55
0
voti
Molto strano, perché a me funziona anche con ottimizzazione pari a 0...
Comunque, c'è un altro modo per ottenere numeri casuali. Ci sono tanti altri modi, basta cercare su Google.
Per esempio si possono usare alcuni algoritmi per ottenere il numero. Ne ho provati un paio di semplici, ma ho scoperto che il risultato non è molto "casuale", perché alla fine i numeri sono sempre gli stessi 20-30 che si ripetono...
Ho però trovato un modo per ottenere un numero abbastanza casuale: usare il timer.
Con questo codice funziona abbastanza bene (dal punto di vista della casualità):
Non sono sicuro che funzioni sul tuo AVR senza bisogno di modifiche, prova e fammi sapere se dà errori
Comunque, c'è un altro modo per ottenere numeri casuali. Ci sono tanti altri modi, basta cercare su Google.
Per esempio si possono usare alcuni algoritmi per ottenere il numero. Ne ho provati un paio di semplici, ma ho scoperto che il risultato non è molto "casuale", perché alla fine i numeri sono sempre gli stessi 20-30 che si ripetono...
Ho però trovato un modo per ottenere un numero abbastanza casuale: usare il timer.
Con questo codice funziona abbastanza bene (dal punto di vista della casualità):
- Codice: Seleziona tutto
/*
* RandomDelay.c
*
* Created: 17/03/2012 22:04:44
* Author: Giacky98
*/
#define F_CPU 1000000UL // 1 MHz
#include <avr/io.h>
#include <util/delay.h> //libreria per il "delay"
#define LEDDDR DDRC
#define LEDPORT PORTC
#define msec 100
void Init(void)
{
LEDDDR = 0xFF; // Imposto la porta C come uscita
LEDPORT = 0xFF; // Spengo tutti i LED
TCNT0=0; // Inizializza il contatore del timer
TCCR0|=(1<<CS02)|(1<<CS00); // Prescaler = FCPU/1024
}
int main(void)
{
int d; // La variabile che conterrà il numero casuale
Init(); // Inizializzo la porta del LED come uscita
while(1){
LEDPORT = ~0x00; // Spengo il primo LED
_delay_ms(msec); // Delay
LEDPORT = ~0x01; // Accendo il primo LED
_delay_ms(msec); // Delay
d = TCNT0%100; // Ottengo il valore dal contatore del timer (0 - 99)
LEDPORT = ~0x02; // Accendo il secondo LED
_delay_ms(d); // Delay (tempo casuale)
}
return 0; // Non serve a niente ma bisogna metterlo
}
Non sono sicuro che funzioni sul tuo AVR senza bisogno di modifiche, prova e fammi sapere se dà errori
0
voti
Flebilmente il secondo LED si accendeva, ma provando a variare il codice (dao chè il tempo di accensione non mi sembrava così "random") in quello sotto per es.:
while(1){
d = TCNT0%100; // Ottengo il valore dal contatore del timer (0 - 99)
LEDPORT = ~0x00; // Spengo il primo LED
_delay_ms(d); // Delay
LEDPORT = ~0x01; // Accendo il primo LED
_delay_ms(d); // Delay
LEDPORT = ~0x02; // Accendo il secondo LED
_delay_ms(d); // Delay (tempo casuale)
}
Ottengo che nessun LED si accende!
Anche provando ad aumentare il tempo randomico scelto ("%1000"), magari avessi problemi a vedere un flash del LED di 99 milli secondi. Ma nemmeno in tal modo funziona.
La cosa non me la so spiegare.
Grazie comunque del tuo supporto ed aiuto!
while(1){
d = TCNT0%100; // Ottengo il valore dal contatore del timer (0 - 99)
LEDPORT = ~0x00; // Spengo il primo LED
_delay_ms(d); // Delay
LEDPORT = ~0x01; // Accendo il primo LED
_delay_ms(d); // Delay
LEDPORT = ~0x02; // Accendo il secondo LED
_delay_ms(d); // Delay (tempo casuale)
}
Ottengo che nessun LED si accende!
Anche provando ad aumentare il tempo randomico scelto ("%1000"), magari avessi problemi a vedere un flash del LED di 99 milli secondi. Ma nemmeno in tal modo funziona.
La cosa non me la so spiegare.
Grazie comunque del tuo supporto ed aiuto!
-
massimonanni86
0 3 - Messaggi: 5
- Iscritto il: 17 mar 2012, 13:55
0
voti
E' veramente molto strano... Il codice come l'hai modificato a me funziona...
Allora, probabilmente non funziona benissimo sul tuo perché tra Atmega8515 e Atmega16 i timer sono un po' diversi.
Ora non ho avuto il tempo di cercare su internet i registri del timer del tuo micro, ma ti consiglio di leggere una guida o un tutorial (anche in inglese, penso non ci siano problemi) sui timer degli AVR, perché è importante conoscerli e saperli usare correttamente. Io ho imparato da questa http://extremeelectronics.co.in/avr-tutorials/avr-timers-an-introduction/.
Comunque, proviamo un altro modo, questa volta usiamo un'algoritmo. Prova questo codice:
Fammi sapere se funziona. A me non dà problemi... se non funziona sinceramente non saprei proprio quale potrebbe essere il problema...
Allora, probabilmente non funziona benissimo sul tuo perché tra Atmega8515 e Atmega16 i timer sono un po' diversi.
Ora non ho avuto il tempo di cercare su internet i registri del timer del tuo micro, ma ti consiglio di leggere una guida o un tutorial (anche in inglese, penso non ci siano problemi) sui timer degli AVR, perché è importante conoscerli e saperli usare correttamente. Io ho imparato da questa http://extremeelectronics.co.in/avr-tutorials/avr-timers-an-introduction/.
Comunque, proviamo un altro modo, questa volta usiamo un'algoritmo. Prova questo codice:
- Codice: Seleziona tutto
/*
* RandomDelay.c
*
* Created: 17/03/2012 22:04:44
* Author: Giacky98
*/
#define F_CPU 1000000UL // 1 MHz
#include <avr/io.h>
#include <util/delay.h>
#define LEDDDR DDRC
#define LEDPORT PORTC
#define msec 100
unsigned long x = 0;
/*****Seek changing function*********************/
void srand(unsigned long s) {
x = s;
}
/*****random number function*********************/
int randm(void) {
x = x * 1664525L + 1013904223L;
return ((int)((x>> 17) & 0x7fff));
}
void Init(void)
{
LEDDDR = 0xFF; // Imposto la porta C come uscita
LEDPORT = 0xFF; // Spengo tutti i LED
}
int main(void)
{
int d; // La variabile che conterrà il numero casuale
Init(); // Inizializzo la porta del LED come uscita
srand(0); //defining starting point of seek
while(1){
LEDPORT = ~0x00; // Spengo il primo LED
_delay_ms(msec); // Delay
LEDPORT = ~0x01; // Accendo il primo LED
_delay_ms(msec); // Delay
d = randm()%250+1; // Ottengo il valore casuale (1 - 250)
LEDPORT = ~0x02; // Accendo il secondo LED
_delay_ms(d); // Delay (tempo casuale)
}
return 0; // Non serve a niente ma bisogna metterlo
}
Fammi sapere se funziona. A me non dà problemi... se non funziona sinceramente non saprei proprio quale potrebbe essere il problema...
10 messaggi
• Pagina 1 di 1
Torna a Firmware e programmazione
Chi c’è in linea
Visitano il forum: Nessuno e 5 ospiti