Pages: [1]   Go Down
Author Topic: Programmazione CLKPR  (Read 1265 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 156
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ciao!
Sto provando da poco la programmazione tramite tramite Atmel Studio 6 e mi son voluto imbattere nella programmazione, per prova, dei registri del prescaler.
C'è tanta documentazione, datasheet incluso, che spiega come farlo. E l'ho fatto. E' uno stile simile al Freescale, dal quale provengo diciamo, ma comunque come tutti i micro anche senza bootloader.
Dopo aver realizzato che i fuses non li posso cambiare se non riscrivo il bootloader ho fatto una cosa: togglo il led della scheda con un for, se cambio il prescaler deve cambiare pure quello. E invece no. Come mai?

Code:
# define F_CPU 16000000UL
#include <avr/io.h>
#include <util/delay.h>


int main(void)
{

CLKPR=_BV(CLKPCE);
CLKPR=(CLKPR & (~_BV(CLKPS0) | ~_BV(CLKPS1) | ~_BV(CLKPS2) | _BV(CLKPS3)));
DDRB=0x20;
unsigned int i;
    while(1)
    {
for(i=0; i<65000; i++);
for(i=0; i<65000; i++);
for(i=0; i<65000; i++);
for(i=0; i<65000; i++);
     //_delay_ms(1000); era per un prova per vedere che usasse davvero i 16Mhz, forse è compensato dal prescaler dnque son passato ai for
PINB=0x20;
    }
}

Grazie a tutti anticipatamente!
Logged

0
Offline Offline
Faraday Member
**
Karma: 30
Posts: 2905
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Circa il prescaler non so risponderti, dovrei leggere il datasheet del micro.

Riguardo al resto del codice posso dirti la seguente:

Nel commento fai riferimento al fatto che toggli un pin di una porta, cioè assegni al pin il valore attuale ma invertito, detto in altri termini fai il flip di un bit di una porta.

Però io il codice che fa il flip non lo vedo.

Code:
// imposta un pin di una porta come OUTPUT
PORT? |= _BV(nbit);   // sostituisci il ? con la lettera della porta, sostituisci nbit con il nome del pin.
// es. imposta il pin PB0 (dal datasheet) della porta B come output

PORTB |= _BV(PB0);

// flip bit 0 di porta B, cioè quando viene eseguito se il valore corrente è 0 diverrà 1, accade l'inverso  prossimo cilco
PORTB ^= _BV(PB0);

Su quei for vuoti ho il dubbio che il compilatore li compili, credo che li salti del tutto, per evitare di saltarli
inserisci una direttiva asm nop

Code:
for (.....
    asm volatile("nop\n\t"::);

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Full Member
***
Karma: 1
Posts: 156
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

No no il toggle lo fa. E' riguardo i timing il problema.
Per il resto bo, io ho cominciato a studiarlo seriamente dal datasheet. Scrivendo 1 al bit #x del PINB register della porta Bx viene invertito il suo valore ad ogni nuova scrittura, in pratica è come l'equivalente di una XOR con un latch sul bit. smiley
Logged

0
Offline Offline
Faraday Member
**
Karma: 30
Posts: 2905
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hai raggione il pin toggle funziona, e io non lo sapevo perchè non ho letto quanto è scritto nel datasheet:

Quote
Writing a logic one to PINxn toggles the value of PORTxn, independent on the value of DDRxn.
Note that the SBI instruction can be used to toggle one single bit in a port.

Mentre per il prescaler dice che per evitare di cambiare il valore accidentalmente c'è da fare una procedura.

Imposta il bit CLKPCE a 1 e poi entro 4 cicli di clock applica il valore del prescaler voluto al registro CLKPR  impostando il bit CLKPCE  a 0.

Dal datasheet:
Quote
To avoid unintentional changes of clock frequency, a special write procedure must be followed
to change the CLKPS bits:
  1. Write the Clock Prescaler Change Enable (CLKPCE) bit to one and all other bits in
      CLKPR to zero.
  2. Within four cycles, write the desired value to CLKPS while writing a zero to CLKPCE.
Interrupts must be disabled when changing prescaler setting to make sure the write procedure is
not interrupted.

Mi dici su quale micro stai lavorando? così almeno guardiamo lo stesso datasheet.

_delay_ms e us dovrebbero funzionare, non c'è motivo che non funzionino, tra l'altro la versione 6 dovrebbe lavorare con la toolchain 4.5.1 è il delay è costruito su un funzione built-in del compilatore.

PS: nel codice che ho postato c'è un errore, al posto di PORT? ci va DDR?, ora lo correggo.

Ciao.



Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Full Member
***
Karma: 1
Posts: 156
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Atmega 328p. Scusa.
Ho risolto per il prescaler: CLKPR=8 e tutto si risolve perché chiede meno di 4 cicli smiley-grin

Le funzioni vanno bene, ma lo sto facendo per capire il micro con approccio in C puro, non oggetti in C++ e senza librerie Arduino.
Logged

0
Offline Offline
Faraday Member
**
Karma: 30
Posts: 2905
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Atmega 328p. Scusa.
Ho risolto per il prescaler: CLKPR=8 e tutto si risolve perché chiede meno di 4 cicli smiley-grin

Le funzioni vanno bene, ma lo sto facendo per capire il micro con approccio in C puro, non oggetti in C++ e senza librerie Arduino.


Ottimo, se posti il codice funzionante magari c'è qualcuno che vuole seguire la stessa strada e si fa esperienza insieme.

Ciao.
Logged

AvrDudeQui front end per avrdude https://gitorious.org/avrdudequi/pages/Home

Offline Offline
Full Member
***
Karma: 1
Posts: 156
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

A be, per come impostare l'IDE per programmare con l'avrdude è pienissimo di guide. Per il codice, quel CLKPR=8 l'ho sostituito a tutto quel CLKPR seguito da quelle OR che settano bit per bit. IL tutto dopo CLKPR=_BV(CLKPCE); ovviamente. smiley
Logged

Pages: [1]   Go Up
Jump to: