• Non ci sono risultati.

F IRMWARE PER L ’AT XMEGA 128 A 1

N/A
N/A
Protected

Academic year: 2021

Condividi "F IRMWARE PER L ’AT XMEGA 128 A 1"

Copied!
11
0
0

Testo completo

(1)

F

IRMWARE PER L

’AT

XMEGA

128

A

1

Per una miglior leggibilità del codice ed un più veloce intervento in fase di

debug, il programma è stato diviso in diversi settori, che tengono conto delle

caratteristiche delle funzioni descritte all’interno di essi. Ad ognuno di questi settori è stato attribuito un simbolo grafico (per esempio alle funzioni di routine è stato assegnato il carattere ‘=’) che, riportato appena prima della dichiarazione della funzione, permette di individuare velocemente le finalità della funzione in esame.

#include <avr/io.h> #include <avr/interrupt.h> #include <math.h> #define Tguardia 100 #define ON_UP_gc(PIN0_bm|PIN1_bm)

#define ON_DOWN_gc (PIN2_bm|PIN3_bm)

#define Vrif 4895 //(Vrif/(LSB*PartitoreVload)^2 #define ADCA_CH0_RESL _SFR_MEM8(0x0224)

//riferimento diretto agli 8 bit meno significativi del

//registro dei risultati dell'ADC, non presente di default nei header //file

#define Tsample 61

//Tsample=(tempo_di_campionamento)/(prescaler_timer) #define MAXIMUM 65535

// --- // dichiarazione variabili globali // ---

typedef enum {ASPETTAINTERRUZIONE0, ASPETTAINTERRUZIONE1} INTERNO;

INTERNO STATO;

unsigned int semiperiodo; unsigned int conduzione;

(2)

unsigned int conduzione100; unsigned int correzione; unsigned long int Veff;

unsigned long int sommatoria; unsigned int ADCres;

unsigned int delta; float Rload;

float K100; float Kp;

char RegolazionePassiva;

//flag per la regolazione passiva

// ############################ // funzioni di inizializzazione // ############################ // ########## // processore void AttivaClock32M(void) { OSC_CTRL |= OSC_RC32MEN_bm;

char controllo = (OSC_STATUS & OSC_RC32MRDY_bm); while (!controllo)

{

controllo = (OSC_STATUS & OSC_RC32MRDY_bm); //aspetta che il clock a 32 MHz si pronto

}

CCP = CCP_IOREG_gc;

//abilita la modifica del registro protetto CLK_CTRL CLK_CTRL = CLK_SCLKSEL_RC32M_gc;

//abilita il clock a 32 MHz

OSC_CTRL &= ~OSC_RC2MEN_bm; } void AbilitaInterruzioni(void) { PMIC_CTRL |= (PMIC_LOLVLEN_bm|PMIC_MEDLVLEN_bm|PMIC_HILVLEN_bm); sei(); }

(3)

// ## // AC void SettaAC(void) { ACB_AC0MUXCTRL |= (AC_MUXPOS_PIN2_gc|AC_MUXNEG_PIN3_gc); // Vmo-a --> PB2; Vmo-rif --> PB3 ACB_AC0CTRL |= (AC_HSMODE_bm|AC_HYSMODE_SMALL_gc);

//abilita il funzionamento in alta velocità e l'isteresi a 50 //mV

ACB_CTRLA |= AC_AC0OUT_bm;

//manda l'uscita del comparatore su PB7 } // #################### // Interruzioni esterne void SettaInterruzioniEsterne(void) { PORTH_INTCTRL |= PORT_INT1LVL_LO_gc; PORTH_INTCTRL |= PORT_INT0LVL_LO_gc; PORTH_PIN0CTRL |= PORT_ISC_RISING_gc;

//PH0 invia una IRQ durante la transizione 0->1 PORTH_PIN1CTRL |= PORT_ISC_FALLING_gc;

//PH1 invia una IRQ durante la transizione 1->0 PORTH_INT0MASK |= PIN0_bm; //PH0 genera INT0 PORTH_INT1MASK |= PIN1_bm; //PH1 genera INT1 } // ##### // timer void SettaTimer(void) { TCD0_INTCTRLB |= TC_CCAINTLVL_HI_gc; //alta priorità per la IRQ del timer

TCD0_CTRLB |= TC0_CCAEN_bm; //abilita il compare match TCD0_CNT = 0;

(4)

// ###### // driver void SettaDriver(void) { PORTJ_DIR |= 0x0F; PORTJ_PIN1CTRL |= PORT_INVEN_bm; //abilita l'inverter del pin PORTJ_PIN3CTRL |= PORT_INVEN_bm; //abilita l'inverter del pin

PORTJ_OUT &= ~(ON_UP_gc|ON_DOWN_gc); //genera i segnali di off_on e off_down } // ### // ADC void SettaADC(void) { ADCA_CTRLB |= ADC_RESOLUTION_8BIT_gc; //Risoluzione a 8 bit ADCA_REFCTRL |= ADC_REFSEL_AREFA_gc; //Riferimento esterno su AREFA

ADCA_PRESCALER |= ADC_PRESCALER_DIV16_gc; //Fclock = 2 MHz ADCA_CH0_CTRL |= ADC_CH_INPUTMODE_SINGLEENDED_gc; ADCA_CH0_MUXCTRL |= (ADC_CH_MUXPOS_PIN3_gc); //ingresso su PA3 ADCA_CH0_INTCTRL |= ADC_CH_INTLVL_MED_gc; //media priorità per la IRQ

} // =================== // funzioni di routine // =================== // == // AC void AttivaAC(void) { ACB_AC0CTRL |= AC_ENABLE_bm; }

(5)

// ===== // timer

void AccendiTimer(void) {

TCD0_CTRLA |= TC_CLKSEL_DIV2_gc; //fclock=16 MHz }

void ResettaTimer(void) {

semiperiodo = (unsigned int)TCD0_CNT; TCD0_CNT = 0; } // === // ADC void AccendiADC(void) { ADCA_CTRLA |= (ADC_ENABLE_bm|ADC_CH0START_bm); } void RiavviaADC(void) { ADCA_CH0_CTRL |= ADC_CH_START_bm; } void DisattivaADC(void) {

ADCA_CTRLA &= ~ADC_ENABLE_bm; } // ============= // calcolo Rload void RiferimentoConduzione(void) { conduzione100 = 829.1+semiperiodo*((4.338e-5)* semiperiodo-0.1493); } void StimaCarico(void) {

(6)

Rload = 100000/ ((float)(763+delta*(5.883+0.002217*delta))); } // ================= // fattore controllo void Kbase(void) { K100 = (float)(semiperiodo*(semiperiodo* (2.13e-8)+(2.43e-5))-.01044); } void CalcoloK(void) { Kp = K100/(0.445+Rload*((12.6e-3)-(7.157e-5)*Rload)); } // =========== // controllore void controllore(void) { RegolazionePassiva = 0; if (Veff>Vrif) {

correzione = (unsigned int)(Kp*(Veff-Vrif)); PORTD_OUT = 0b11110011; if ((conduzione-correzione)<Tguardia) { conduzione = Tguardia; } else {

conduzione = (unsigned int)(conduzione-correzione);

} }

else {

correzione = (unsigned int)(Kp*(Vrif-Veff)); PORTD_OUT = 0b11111100;

if ((conduzione+correzione)>(semiperiodo-Tguardia)) {

(7)

RegolazionePassiva = 1; }

else {

conduzione = (unsigned int)(conduzione+ correzione); } } } ////////// // MAIN // ////////// int main (void)

{

//cambio clock AttivaClock32M();

//inizializzazione led per controllo visivo PORTD_DIR |= 0xFF;

PORTD_OUT |= 0xFF;

//inizializzazione porta Q per il controllo delle //interruzioni

PORTQ_DIR |= (PIN0_bm|PIN1_bm|PIN2_bm|PIN3_bm);

//inizializzazione porte e periferiche PORTB_DIR |= PIN7_bm;

//PB7 è l'uscita del comparatore ACB0 SettaAC(); SettaInterruzioniEsterne(); SettaDriver(); SettaTimer(); SettaADC(); //inizializzazione variabili Veff = 0;

(8)

RegolazionePassiva = 0; sommatoria = 0; semiperiodo = MAXIMUM; TCD0_CCA = MAXIMUM; Kp = 0.19; K100 = 0.19; conduzione100 = Tguardia; Rload = 100; //attivazione perififeriche AttivaAC(); AccendiTimer();

//cambio di stato interno e attivazioni interruzioni a //livello globale STATO = ASPETTAINTERRUZIONE0; AbilitaInterruzioni(); while (1) { //ciclo infinito } } /////////////// // FINE MAIN // /////////////// // ++++++++++++++++++++++++++ // vettori delle interruzioni // ++++++++++++++++++++++++++

// ++++++++++++++++++++ // interruzioni esterne ISR(PORTH_INT0_vect){

PORTQ_OUT |= (1<<PIN0_bp); //controllo esecuzione switch (STATO) {

case ASPETTAINTERRUZIONE0: {

(9)

//impulsi di off_down

STATO = ASPETTAINTERRUZIONE1; ResettaTimer();

TCD0_CCA = (semiperiodo-conduzione); //memorizzazione del nuovo istante di //chiusura degli interruttori

if (RegolazionePassiva) {

PORTJ_OUT |= ON_UP_gc; AccendiADC();

TCD0_CCA = MAXIMUM; //evita la //generazione di una inutile IRQ da //parte del timer

}

Veff = (sommatoria/semiperiodo)*Tsample; //calcolo del valore efficace di Vload RiferimentoConduzione(); Kbase(); sommatoria = 0; break; } default: { break; } }

PORTQ_OUT &= ~(1<<PIN0_bp); //controllo esecuzione }

ISR(PORTH_INT1_vect) {

PORTQ_OUT |= (1<<PIN1_bp); //controllo esecuzione switch (STATO)

{

case ASPETTAINTERRUZIONE1: {

PORTJ_OUT &= ~(ON_UP_gc); STATO = ASPETTAINTERRUZIONE0; if (RegolazionePassiva)

{

(10)

} ResettaTimer(); DisattivaADC(); StimaCarico(); CalcoloK(); controllore(); break; } default: { break; } }

PORTQ_OUT &= ~(1<<PIN1_bp); //controllo esecuzione }

// +++++ // timer

ISR(TCD0_CCA_vect) {

PORTQ_OUT |= (1<<PIN2_bp); //controllo esecuzione switch (STATO) { case ASPETTAINTERRUZIONE1: { PORTJ_OUT |= ON_UP_gc; AccendiADC(); break; } case ASPETTAINTERRUZIONE0: { PORTJ_OUT |= ON_DOWN_gc; break; } default: { break; } }

PORTQ_OUT &=~(1<<PIN2_bp); //controllo esecuzione }

(11)

// ++++++++++++ // campionatore ISR(ADCA_CH0_vect)

{

PORTQ_OUT |= (1<<PIN3_bp); //controllo esecuzione switch (STATO)

{

case ASPETTAINTERRUZIONE1: {

RiavviaADC();

Sommatoria += (unsigned int)ADCA_CH0_RESL* (unsigned int)ADCA_CH0_RESL; break; } default: { break; } }

PORTQ_OUT &= ~(1<<PIN3_bp); //controllo esecuzione }

Riferimenti

Documenti correlati

[r]

Se consideriamo il grafico di una funzione: f: R → R si può osservare che f è iniettiva se ogni retta orizzontale incontra il grafico al più una

Foglio esercizi MB Corso di Laurea

per le Politiche di incentivazione della produttività delle aree funzionali AMMONTARE COMPLESSIVO DEI PREMI STANZIATI E EFFETTIVAMENTE DISTRIBUITI..

A seguito dell’incontro bilaterale attivato dalla Commissione Europea (nei giorni del 4 e 5 luglio 2019) con i rappresentanti della Direzione Generale Environment e della

28   Possiamo  a  giusto  titolo  parlare  di  due  paradigmi  epistemologici  differenziati,  poiché  profondamente  diverse  sono  le  premesse  causali  che 

[r]

[r]