Appendice B Firmware
Appendice B: Firmware
// v@@@@@@@@@@@@@@@@@@@@@@@@@@ main.c @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//#include "stdafx.h"
#include "config.h"
#include "init.h"
#include "task.h"
#include "driver.h"
// --- DEFINIZIONE INTERFACCIA BOOTLOADER --- ---
/*
Uchar data api_command _at_ 0x1C;
Uchar data api_value _at_ 0x1D;
Uchar data api_dpl _at_ 0x1F;
Uchar __api_rd_generic (Uchar command, Uchar dpl) {
api_command = command;
api_dpl = dpl;
MAP_BOOT;
__API_FLASH_ENTRY_POINT();
UNMAP_BOOT;
return(api_value);
}
*/
// --- DEFINIZIONE VARIABILI GLOBALI --- ---
// variabili di controllo
volatile Uchar task_in_progress; // attivazione ciclo lento type_stato_nodo stato_nodo, nuovo_stato_nodo;
Int8 livello_precarico, nuovo_livello_precarico;
Int32 corsa_media;
bdata Uchar stato_L, stato_H;
Sbit( done, stato_H, 7 );
Sbit( vel_inrange, stato_H, 6);
Sbit( set, stato_H, 5);
Sbit( setting, stato_H, 4);
Sbit( stato_algoritmo_3, stato_H, 3 );
Sbit( stato_algoritmo_2, stato_H, 2 );
Sbit( stato_algoritmo_1, stato_H, 1 );
Sbit( stato_algoritmo_0, stato_H, 0 );
Sbit( errore, stato_L, 7 );
Sbit( setta, stato_L, 6 );
Sbit( leggi, stato_L, 5 );
Sbit( fine_corsa, stato_L, 4 );
Sbit( cav, stato_L, 3 );
Appendice B Firmware
Sbit( dir_m, stato_L, 2 );
Sbit( stato_m, stato_L, 1 );
Sbit( cmd_m, stato_L, 0 );
//variabili per il controllo della corrente assorbita DA
SETTARE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
bdata Uchar corrente_motore;
Sbit(s_m , corrente_motore, 0);
Sbit(misura_in_corso , corrente_motore, 1);
Sbit(prima_misura , corrente_motore, 2);
//Uint8 s_m=0;
//Uint8 misura_in_corso=1;
bdata Uchar controllo;
Sbit( enable_log, controllo, 7 );
Sbit( controllo_remoto, controllo, 6 );
Sbit( leggi_precarico, controllo, 5 );
Sbit( azzera_precarico, controllo, 4 );
Sbit( m_up_down, controllo, 3 );
Sbit( setta_precarico, controllo, 2 );
Sbit( setta_corsa, controllo, 1 );
Sbit( attiva_m, controllo, 0 );
Uchar cicli_dopo_off;
// variabili d'ingresso remote Uchar chiave;
// variabili d'ingresso locali bdata Uchar in_on_off_A;
Sbit( in_on_off_A_7, in_on_off_A, 7 );
Sbit( in_on_off_A_6, in_on_off_A, 6 );
Sbit( cav_lat, in_on_off_A, 5 );
Sbit( in_on_off_A_4, in_on_off_A, 4 );
Sbit( in_on_off_BtConnected, in_on_off_A, 3 );
Sbit( in_on_off_A_2, in_on_off_A, 2 );
Sbit( in_on_off_A_1, in_on_off_A, 1 );
Sbit( in_on_off_A_0, in_on_off_A, 0 );
// misura velocità Uint16 delta_tempo;
Uchar num_cicli_contati;
// misura corrente
volatile Uint16 corrente_media;
volatile Uint16 corrente_media_sal;
volatile Uint16 corrente_media_disc;
volatile Uint16 corrente_media_assorbita;
volatile Uint16 num_sample_corrente;
volatile Uchar nuova_misura_vel;
volatile Uint16 sospensione, pressione, precarico;
volatile Uint16 corrente;
Appendice B Firmware
Uchar velocita, temperatura;
// variabili ricevute su seriale bdata Uchar controllo_rx;
Sbit( enable_log_rx, controllo_rx, 7 );
Sbit( controllo_remoto_rx, controllo_rx, 6 );
Sbit( leggi_precarico_rx, controllo_rx, 5 );
Sbit( azzera_precarico_rx, controllo_rx, 4 );
Sbit( m_up_down_rx, controllo_rx, 3 );
Sbit( setta_precarico_rx, controllo_rx, 2 );
Sbit( setta_corsa_rx, controllo_rx, 1 );
Sbit( attiva_m_rx, controllo_rx, 0 );
Uchar livello_precarico_rx;
// variabili di uscita locali // variabili per il debug
Uchar pacchetto_log[NUM_BYTE_PACCHETTO_LOG];
// --- main()
{
/* tutte le variabili sono a 0 (il compilatore inserisce la porzione di codice
che azzera la memoria, mentre le porte di I/O (dopo reset hardware) sono a 1
*/
// disabilitazione generale delle interruzioni EA = 0;
// stato RESET
stato_nodo = STATO_RESET;
// 6 cicli x istruzione CKCON = CKCON | 0x01;
// lettura identificazione nodo
// cris = __api_rd_CRIS(); // id nodo
// id_nodo = __api_rd_NNB(); // indentificatore base msg flip // inizializzazione periferiche uC
init_uart();
init_timer1();
init_pca();
init_ADC();
// inizializzazione misura frequenza reset_mis_freq();
// inizializzazione variabili globali enable_log = FALSE;
Appendice B Firmware
// inizializzazione ciclo lento task_in_progress = 1;
// inizializzazione variabili globali sospensione = 0;
precarico = 0;
/// stato = 0;
// batteria = 0;
chiave = TRUE;
dir_m = 1;
controllo = 0;
controllo_rx = 0;
//abilito generale delle interruzioni EA = 1;
// --- CICLO LENTO --- while(1)
{
if (task_in_progress) {
task_in_progress = 0;
// esecuzione task
lettura_ingressi_locali();
calcola_nuovo_stato_nodo();
esegui_controllo();
scrivi_uscite_locali();
logging();
// fine task }
// attesa di un nuovo tick idle();
} }
// --- DEFINIZIONE VETTORI DI INTERRUPT --- // driver che gestisce l'interrupt generata dal TIMER 1
Interrupt(driver__tick_sistema(void), 3) {
static conta_tempo = 0;
static conta_tempo_ADC = 0;
// riazzera flag interrupt TF1 = 0;
// sampling ADC
if (conta_tempo_ADC == CONTA_CICLI_ADC)
{ adc_start_conv_interrupt(SOSPENSIONE_ADC_CH, 2);
conta_tempo_ADC = 0;
}
else conta_tempo_ADC ++;
Appendice B Firmware
// tick di sistema
if (conta_tempo == CONTA_CICLI_TIMER1) { task_in_progress = 1;
conta_tempo = 0;
}
else conta_tempo ++;
}
// driver che gestisce l'interrupt generata da uart Interrupt(driver_uart(void), 4)
{
if (TI) tx_carattere();
else rx_carattere();
}
// driver che gestisce l'interrupt generata dal PCA Interrupt(it_6(void), 6)
{
mis_freq_driver();
}
// driver che gestisce l'interrupt generata dall'ADC Interrupt(it_8(void), 8)
{
adc_driver();
}
// --- //
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// @@@@@@@@@@@@@@@@@@@@@@@@@@@ task.c @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#include "config.h"
#include "task.h"
#include "driver.h"
// --- DEFINIZIONE VARIABILI LOCALI --- Uchar modo_prog; // attivazione stato programmazione
Uchar cycles; // conta i cicli
//---DICHIARAZIONE VARIBILI ESTERNE --- extern Uchar _num_adc_conv, _adc_channel; //driver.c
// --- DEFINIZIONE TASK --- // --- lettura_ingressi_locali --- void lettura_ingressi_locali()
{
Appendice B Firmware
static Uchar star_0_A = 0;
static Uchar star_1_A = 0;
Uchar nuovo_star_0;
Uchar sample_in_on_off_A;
//campionamento ingressi
sample_in_on_off_A = PORTA_IN_on_off_A;
//RC che produce il nuovo stato
nuovo_star_0 = ( star_0_A & ~star_1_A ) |
( star_0_A & ~sample_in_on_off_A ) | ( star_1_A & ~sample_in_on_off_A );
star_1_A = ( ~star_0_A & ~star_1_A & ~sample_in_on_off_A) | ( star_0_A & ~star_1_A & sample_in_on_off_A);
star_0_A = nuovo_star_0;
//l'uscita della rete seq. coincide con star_0 in_on_off_A = star_0_A;
}
// --- calcola_nuovo_stato_nodo --- void calcola_nuovo_stato_nodo()
{
// conto i cicli dello scheduler in un certo stato cycles ++;
switch(stato_nodo) {
case STATO_RESET:
if (cycles == CYCLES_RESET) nuovo_stato_nodo = STATO_SLEEP;
break;
case STATO_SLEEP:
if (chiave) nuovo_stato_nodo = STATO_ON;
break;
case STATO_ON:
if (!chiave) nuovo_stato_nodo = STATO_SLEEP;
else if (modo_prog == 1) nuovo_stato_nodo = STATO_PROG;
break;
default:
nuovo_stato_nodo = STATO_SLEEP;
break;
}
if ( (nuovo_stato_nodo ^ stato_nodo) ) {
stato_nodo = nuovo_stato_nodo;
cycles = 0;
switch (stato_nodo)
Appendice B Firmware
{
case STATO_RESET:
break;
case STATO_SLEEP:
break;
case STATO_ON:
break;
case STATO_PROG:
EA = 0;
TH2 = 0;
TL2 = 0;
RCAP2L = 0;
RCAP2H = 0;
MAP_BOOT;
__API_JMP_BOOTLOADER();
//reset break;
} }
}
// --- esecuzione controllo --- enum {START=0, READY=1, MEASURE=2, REMOTE=3, ERROR=4, WAIT = 5, PRELOAD_SET=6, PRELOAD_SETTING=7} stato_algoritmo=START, stato_algoritmo_saved;
void esegui_controllo() {
static enum {IDLE_CTRL, RESET_CTRL, LEGGI_CTRL, SETTA_CTRL}
stato_controllo = IDLE_CTRL;
static Uchar segno_precarico = 0;
static Uint16 nuovo_precarico, conta_cicli;
static Uint16 cicli_misura = 0, cicli_nuova_misura, cicli_vel_zero, cicli_inrange_prima_misura;
static Uint32 vel_prec=0;
Uint32 vel, acc;
// Int8 segno_correzione_precarico;
// macchina a stati che implementa algoritmo di controllo switch(stato_nodo) {
case STATO_ON:
switch(stato_algoritmo) { case START:
misura_in_corso=1;// massimo prima_misura=1;// massimo
controllo = 0;
enable_log = 1;
// azzero precarico done = 0;
azzera_precarico = 1;
livello_precarico = 0;
stato_algoritmo_saved = READY;
stato_algoritmo = WAIT;
break;
case READY:
set = FALSE;
Appendice B Firmware
if(!cav_lat) stato_algoritmo = MEASURE;
else if(controllo_remoto_rx) { enable_log_rx = 1;
attiva_m_rx = 0;
setta_precarico_rx = 0;
stato_algoritmo = REMOTE;
} break;
case MEASURE:
#define VEL_MAX 5243 // 40 km/h
#define VEL_MIN 2621 // 20 km/h
#define ACC_MAX 285 // 0.5 m/s^2
/* #define DURATA_MISURA 500 // x10 ms = 5 s
*/
#define DURATA_MISURA 350 // x10 ms = 3.5 s
#define CORRENTE_MEDIA1 42,623
#define CORRENTE_MEDIA2 50,819 leggi = TRUE;
// calcolo velocità e accelerazione if(nuova_misura_vel) {
nuova_misura_vel = 0;
if(delta_tempo==0) vel = 0;
else {
vel = num_cicli_contati;
vel = vel << 24;
vel = vel/delta_tempo;
}
if(vel>vel_prec) acc = vel - vel_prec; else acc = vel_prec - vel;
// vel in range acc in modulo minore val max vel_prec = vel;
}
//CONTROLLO VELOCITA E ACCELERAZIONE //verifica se velocita' e accelerazione if((vel < VEL_MAX) && (vel > VEL_MIN) && (acc <
ACC_MAX)) {
vel_inrange = TRUE;
//eseguo la misura della corrente if(misura_in_corso){// definita in main //stabilisco il livello di precarico
if (prima_misura){
prima_misura=0;
if(livello_precarico==0){nuovo_livello_precarico=3, s_m = MOTORE_UP;}
else{if(livello_precarico==4){nuovo_livello_precarico=7, s_m = MOTORE_UP;}
else{nuovo_livello_precarico=4, s_m = MOTORE_DOWN;}}
corrente_media_sal = 0;
stato_controllo = LEGGI_CTRL;
Appendice B Firmware
}else{prima_misura=1;
if(livello_precarico==3){nuovo_livello_precarico=0, s_m = MOTORE_DOWN;}
else{if(livello_precarico==7){nuovo_livello_precarico=4, s_m = MOTORE_DOWN;}
else{nuovo_livello_precarico=7, s_m = MOTORE_UP;} }
corrente_media_disc = 0;
stato_controllo = LEGGI_CTRL;
misura_in_corso = 0;
} }
else{ //se non c'è misura in corso corrente_media_assorbita =
corrente_media_sal/NUM_CAMPIONI_PRELEVATI_SAL-
corrente_media_disc/NUM_CAMPIONI_PRELEVATI_DISC;
}
//la misura della corrente è finita e calcolo il carico
if(corrente_media_assorbita <
CORRENTE_MEDIA1){
nuovo_livello_precarico = 0; //carico = CONDUCENTE;
}else{
if(corrente_media_assorbita <
CORRENTE_MEDIA2)
nuovo_livello_precarico = 4; //carico = CONDUCENTE_BAGAGLI;
else nuovo_livello_precarico = 7;
//carico = CONDUCENTE_PASSEGGERO;
// conosco il carico e devo impostare il nuovo_livello_precarico
stato_algoritmo = PRELOAD_SETTING;
cicli_nuova_misura = CICLI_NUOVA_MISURA;
cicli_vel_zero = CICLI_VEL_ZERO;
leggi = FALSE;
}
}else{
//velocita' e accelerazione NON sono nel range
vel_inrange = FALSE;
cicli_misura = 0;
corrente_media = 0;
cicli_inrange_prima_misura = 0;
}
if(cav_lat) {
stato_algoritmo = START;
leggi = FALSE;
} break;
case REMOTE:
Appendice B Firmware
if (!controllo_remoto_rx) stato_algoritmo = READY;
else {
azzera_precarico = azzera_precarico_rx;
azzera_precarico_rx = 0;
attiva_m = attiva_m_rx;
attiva_m_rx = 0;
m_up_down = m_up_down_rx;
setta_precarico = setta_precarico_rx;
setta_precarico_rx = 0;
nuovo_livello_precarico = livello_precarico_rx;
} break;
case WAIT:
if(done) stato_algoritmo = stato_algoritmo_saved;
else if(errore) stato_algoritmo = ERROR;
break;
case ERROR:
if(controllo_remoto_rx) { enable_log_rx = 1;
attiva_m_rx = 0;
setta_precarico_rx = 0;
stato_algoritmo = REMOTE;
} break;
case PRELOAD_SETTING:
if((nuovo_livello_precarico - livello_precarico!=0) && !set) {
stato_algoritmo_saved = PRELOAD_SET;
done = FALSE;
setta_precarico = TRUE;
stato_algoritmo = WAIT;
setting = TRUE;
}
else stato_algoritmo = PRELOAD_SET;
break;
case PRELOAD_SET:
cicli_nuova_misura--;
setting = FALSE;
set = TRUE;
if (num_cicli_contati==0) cicli_vel_zero--;
else cicli_vel_zero = CICLI_VEL_ZERO;
if(cav_lat) stato_algoritmo = START;
else if((cicli_nuova_misura==0) ||
(cicli_vel_zero==0)) stato_algoritmo = MEASURE;
break;
default:;
} break;
default:stato_algoritmo = START;
}
// macchina a stati che controlla il motore;
conta_cicli++;
switch (stato_controllo) { case IDLE_CTRL:
Appendice B Firmware
conta_cicli = 0;
if(azzera_precarico) { fine_corsa = 0;
stato_controllo = RESET_CTRL;
}
else if (attiva_m) { attiva_m = 0;
cmd_m = 1;
dir_m = m_up_down;
stato_controllo = IDLE_CTRL;
done = 1;
}
else if (leggi_precarico) { num_sample_corrente = 0;
stato_controllo = LEGGI_CTRL;
corrente_media = 0;
leggi_precarico = 0;
leggi = 1;
}
else if(setta_precarico) {
#define OFFSET_PRECARICO 50
#define DELTA_PRECARICO 53 setta = 1;
setta_precarico = FALSE;
nuovo_precarico =
OFFSET_PRECARICO+nuovo_livello_precarico*DELTA_PRECARICO;
stato_controllo = SETTA_CTRL;
if(nuovo_precarico > precarico) segno_precarico=1;
else segno_precarico = 0;
if(segno_precarico) dir_m = MOTORE_UP;
else dir_m = MOTORE_DOWN;
} break;
case RESET_CTRL:
if(fine_corsa) { precarico = 0;
stato_controllo = IDLE_CTRL;
azzera_precarico = 0;
errore = 0;
done = 1;
}
else if(conta_cicli<RESET_CTRL_TIMEOUT) { cmd_m = 1;
dir_m = MOTORE_DOWN;
}
else {
errore = 1;
azzera_precarico = 0;
stato_controllo = IDLE_CTRL;
} break;
case LEGGI_CTRL:
if( num_sample_corrente<NUM_SAMPLE_CORRENTE) { stato_m = 1;// accendo il motore
dir_m =s_m;
Appendice B Firmware
_adc_channel=CORRENTE_ADC_CH;// campiono la corrente
adc_driver();
}
else {
stato_controllo = IDLE_CTRL;
leggi = 0;
done = 1;
stato_m=0;
} break;
case SETTA_CTRL:
if ((nuovo_precarico>precarico)^segno_precarico) { stato_controllo = IDLE_CTRL;
setta = 0;
done = 1;
livello_precarico = nuovo_livello_precarico;
}
else {
cmd_m = 1;
} break;
default:
stato_controllo = IDLE_CTRL;
} }
// --- scrittura uscite locali--- void scrivi_uscite_locali()
{
// aggiungere watchdog sul tempo max di attivazione motore stato_m = cmd_m;
cmd_m = 0;
// DIR_MOTORE(dir_m);
// MOTORE(stato_m);
MOTOR_CTRL(stato_m, dir_m);
}
// --- logging --- void logging()
{
static periodo = 0;
if (enable_log && (stato_nodo == STATO_ON)) { periodo++;
if (periodo == PERIODO_LOG) { periodo = 0;
// preparo il pacchetto EA = 0;
cav = cav_lat;
stato_H &= 0xF0;
stato_H |= (stato_algoritmo & 0x0F);
Appendice B Firmware
pacchetto_log[0] = stato_L;
pacchetto_log[1] = BYTE1(sospensione);
pacchetto_log[2] = BYTE1(precarico);
pacchetto_log[3] = BYTE0(precarico);
pacchetto_log[4] = BYTE1(corrente);
pacchetto_log[5] = BYTE1(corrente);// batteria----corrente pacchetto_log[6] = BYTE1(delta_tempo);
pacchetto_log[7] = BYTE0(delta_tempo);
pacchetto_log[8] = num_cicli_contati;
pacchetto_log[9] = temperatura;
pacchetto_log[10] = stato_H;
pacchetto_log[11] = BYTE0(corrente);
pacchetto_log[12] = livello_precarico;
pacchetto_log[13] = nuovo_livello_precarico;
EA = 1;
// abilito la trasmissione TI = 1;
} }
else periodo = 0;
}
// --- Attesa di un nuovo tick di sistema --- void idle()
{
EA = 1;
PCON = PCON | 0x01; // idle }
//
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ driver.c @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#include "config.h"
#include "driver.h"
//--- // struttura dati per la misura della frequenza
Uchar misura;
Uchar msk_capture;
Uchar start_time_L;
Uchar start_time_H;
Uchar stop_time_L;
Uchar stop_time_H;
Uchar num_eventi;
Appendice B Firmware
Uchar evento_catturato;
//--- MISURA FREQUENZA --- /*
alterno NUM_MISURE_FREQ misure:
misura_0 -> velocità misura_1 ->
misura_2 ->
misura_3 ->
precarico (deve essere gestito autonomamente; vanno contati gli impulsi con segno dato da dir motore)
*/
void reset_mis_freq() {
Uint16 start_time, stop_time;
TCON = TCON & 0xCF; // disbilito timer0;
// converto la misura su 16 bit e la scrivo start_time = start_time_H;
start_time = start_time << 8;
start_time = start_time + start_time_L;
stop_time = stop_time_H;
stop_time = stop_time << 8;
stop_time = stop_time + stop_time_L;
EA = 0;
delta_tempo = stop_time - start_time;
num_cicli_contati = num_eventi;
nuova_misura_vel = 1;
EA = 1;
// imposto il nuovo tempo di misura e seleziono il modulo del PCA TL0 = TH0_MISURA_VELOCITA;
TH0 = TH0_MISURA_VELOCITA;
//abilito capture mode(positive) e interrupt quando cattura un evento CCAPM_MISURA_PRECARICO = 0x21;
CCAPM_MISURA_VELOCITA = 0x21;
msk_capture = MSK_CAPTURE_MISURA_VELOCITA;
TCON = TCON | 0x10; // abilito il timer0 // azzero le variabili della misura
num_eventi = 0;
evento_catturato = 0;
start_time_L = 0;
start_time_H = 0;
stop_time_L = 0;
Appendice B Firmware
stop_time_H = 0;
// azzero il contatore del PCA CL = 0;
CH = 0;
CCON = CCON & MSK_CAPTURE_MISURA_PRECARICO; // disabilito il contatore del PCA e resetto tutti i flag ad eccezione del precarico
CCON |= 0x40; //abilito il contatore del PCA // abilito le interruzioni provenienti dal PCA EC = 1;
}
void mis_freq_driver() {
Uchar aux, ramo_ov;
Uchar ccapl, ccaph;
EC = 0; //disabilito le interruzioni provenienti dal PCA
// guardo chi ha generato l'interrupt: capture e/o overflow o precarico //precarico
#define CICLI_DOPO_OFF 4
if (CCON & MSK_CAPTURE_MISURA_PRECARICO) {
CCON = CCON & ~MSK_CAPTURE_MISURA_PRECARICO;
if(dir_m==MOTORE_UP) {
if (cicli_dopo_off<CICLI_DOPO_OFF) { if(precarico < 0xFFFF) precarico++;}
else if (precarico >0) precarico--;
}
// motore down
else if (cicli_dopo_off<CICLI_DOPO_OFF) {if (precarico >0) precarico--;}
else if (precarico < 0xFFFF) precarico++;
}
else {
// velocità
aux = CCON; //leggo registro di controllo
// leggo i registri di cattura del modulo coinvolto nella misura corrente
ccapl = CCAPL_MISURA_VELOCITA;
ccaph = CCAPH_MISURA_VELOCITA;
ramo_ov = 0;
//controllo se CF = 1 e CCF0 = 1 e in quel caso decido //quale delle due è arrivata prima
if ((aux & msk_capture) && (aux & MSK_OVERFLOW) && (ccaph==0)) ramo_ov = 1;
if((aux & msk_capture) && !ramo_ov) // ramo capture {
//resetto flag CCF0 CCON = CCON & ~msk_capture;
Appendice B Firmware
if(!evento_catturato) //primo evento {
evento_catturato = 1;
start_time_H = ccaph;
start_time_L = ccapl;
start_time_H = ccaph;
start_time_L = ccapl;
} else {
stop_time_H = ccaph;
stop_time_L = ccapl;
stop_time_H = ccaph;
stop_time_L = ccapl;
num_eventi++;
} }
else //ramo overflow: la misura corrente è terminata {
// scrivo il risultato della misura e configuro la misura succesiva
reset_mis_freq();
} }
// riabilito interruzioni provenienti dal PCA EC = 1;
}
//--- COMUNICAZIONE SERIALE CON LO HOST --- Uchar bin_to_ascii (Uchar to_convert)
{
Uchar convert;
if ((to_convert >= 0) && (to_convert <= 9)) convert = to_convert + 0x30;
else convert = to_convert + 0x37;
return (convert);
}
Uchar ascii_to_bin (Uchar to_convert) { Uchar convert;
if ((to_convert >= '0') && (to_convert <= '9')) convert = to_convert - '0';
else if ((to_convert >= 'A') && (to_convert <= 'F')) convert = 10 + to_convert - 'A';
else convert = 255; //errore return (convert);
}
Appendice B Firmware
#define TRAILER_RX 13 void rx_carattere() {
static type_stato_rx stato_rx;
Uchar carattere_rx;
carattere_rx = SBUF;
switch(stato_rx) { case WAIT_RX:
switch (carattere_rx) {
case 'A': // Azzera precarico azzera_precarico_rx = TRUE;
stato_rx = WAIT_TRAILER_RX;
break;
case 'C': // disabilita logging enable_log_rx = FALSE;
stato_rx = WAIT_TRAILER_RX;
break;
case 'I':
controllo_remoto_rx = FALSE;
stato_rx = WAIT_TRAILER_RX;
break;
case 'L':
leggi_precarico_rx = 1;
stato_rx = WAIT_TRAILER_RX;
break;
case 'M':
stato_rx = MOTORE_RX;
break;
case 'O': // abilita logging enable_log_rx = TRUE;
stato_rx = WAIT_TRAILER_RX;
break;
case 'R':
controllo_remoto_rx = TRUE;
stato_rx = WAIT_TRAILER_RX;
break;
case 'S':
stato_rx = SETTA_RX;
break;
default:
stato_rx = WAIT_TRAILER_RX;
} break;
case SETTA_RX:
livello_precarico_rx = ascii_to_bin(carattere_rx);
setta_precarico_rx = 1;
stato_rx = WAIT_TRAILER_RX;
break;
case MOTORE_RX:
switch (carattere_rx) { case '+':
attiva_m_rx = 1;
m_up_down_rx = 1;
Appendice B Firmware
stato_rx = WAIT_TRAILER_RX;
break;
case '-':
attiva_m_rx = 1;
m_up_down_rx = 0;
stato_rx = WAIT_TRAILER_RX;
break;
default:
stato_rx = WAIT_TRAILER_RX;
} break;
case WAIT_TRAILER_RX:
if (carattere_rx == TRAILER_RX) stato_rx = WAIT_RX;
break;
default:
stato_rx = WAIT_TRAILER_RX;
}
// acknowledgemnt interrupt RI = 0;
}
// driver che gestisce l'invio di un pacchetto di byte
#define HEADER 'A'
#define TRAILER_1 13
#define TRAILER_2 10
void tx_carattere() {
static num_byte_tx = 0;
static lsb = 0;
static num_byte_servizio = 0;
// acknowledgement interrupt TI = 0;
// per ogni byte trasmetto prima i 4 msb
if ( (num_byte_tx == 0) && (num_byte_servizio == 0)) {
SBUF = HEADER;
num_byte_servizio = 1;
}
else if ( num_byte_tx < NUM_BYTE_PACCHETTO_LOG) {
if ( !lsb ) SBUF = (bin_to_ascii((pacchetto_log[num_byte_tx] & 0xF0)
>> 4));
else SBUF = (bin_to_ascii(pacchetto_log[num_byte_tx] & 0x0F));
num_byte_tx += lsb;
lsb = lsb ^ 1;
}
else if ( num_byte_servizio == 1 ) {
SBUF = TRAILER_1;
num_byte_servizio = 2;
}
else if ( num_byte_servizio == 2 )
Appendice B Firmware
{
SBUF = TRAILER_2;
num_byte_servizio = 3;
} else {
num_byte_servizio = 0;
num_byte_tx = 0;
} }
Uchar _num_adc_conv, _adc_channel;
void adc_start_conv_interrupt(Uchar channel, Uchar num_adc_conv) {
//we assume that the ADC interrupt is already enable //as well as the general intterpt
if(num_adc_conv) {
_num_adc_conv = num_adc_conv;
_adc_channel = channel;
//select channel
ADCON &= ~MSK_ADCON_SCH;
ADCON |= channel;
//start the conversion ADCON |= MSK_ADCON_ADSST;
} }
void adc_driver() {
static Uchar cicli_attesa=0;
Int16 appoggio;
//clear flag end of concersion ADCON &= ~MSK_ADCON_ADEOC;
switch(_adc_channel) {
case SOSPENSIONE_ADC_CH:
appoggio = ADDH - BYTE1(sospensione);
sospensione += appoggio;
_adc_channel = CORRENTE_ADC_CH;
break;
case CORRENTE_ADC_CH:
//corrente istantanea
appoggio = ADDH - BYTE1(corrente);
corrente += appoggio;
//corrente media
#define CICLI_ATTESA_SAL 150 // 1 ciclo ogni 10 msec finito transistorio corrente di spunto motore salita
#define CICLI_ATTESA_DISC 80 //finito transistorio corrente di spunto motore discesa
if(stato_m){ //motore attivo if(s_m){
if(cicli_attesa < CICLI_ATTESA_SAL) cicli_attesa++;
Appendice B Firmware
else {
num_sample_corrente ++ ; if (num_sample_corrente <
NUM_CAMPIONI_PRELEVATI_SAL)
corrente_media_sal += ADDH;
if (ADDH >= MAX_CORRENTE) { fine_corsa = 1;
stato_m = OFF;
MOTOR_CTRL(stato_m, MOTORE_UP);
//disattivazione motore
}
else fine_corsa = 0;
}}
else {
if(cicli_attesa < CICLI_ATTESA_DISC) cicli_attesa++;
else {
num_sample_corrente ++;
if (num_sample_corrente <=
NUM_CAMPIONI_PRELEVATI_DISC)
corrente_media_disc += ADDH;
if (ADDH >= MAX_CORRENTE) { fine_corsa = 1;
stato_m = OFF;
MOTOR_CTRL(stato_m, MOTORE_UP);//disattivazione motore
}
else fine_corsa = 0;
} }
}
else cicli_attesa = 0;
_adc_channel = SOSPENSIONE_ADC_CH;
break;
default:
_num_adc_conv = 1;
}
_num_adc_conv--;
adc_start_conv_interrupt(_adc_channel, _num_adc_conv);
}
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ init.c @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#include "config.h"
#include "init.h"
// INIZIALIZZAZIONE DEL TIMER 1 A GENERARE UN INTERRUPT OGNI 0.19 ms void init_timer1()
{
CKCON = CKCON | 0x04; // dimezzo il clock del timer 1 TMOD = TMOD & 0x0F;
TMOD = TMOD | 0x20; // 8-bit e auto-reload mode TH0 = RELOAD_TIMER1;
Appendice B Firmware
TL0 = RELOAD_TIMER1;
TCON = TCON | 0x40;
ET1 = 1;
}
// INIZIALIZZAZIONE UART A 19200 SOLO IN TRASMISSIONE void init_uart (void)
{
PCON = PCON & 0X3F; // selezione SMO in SCON SCON = 0x50; // seleziono mode 1 e non mulitiprocessor communication
// abilito la ricezione // utilizzo overflow del timer2 per generare clock uart
T2CON = 0;
TH2 = 65527;
TL2 = 65527;
// RCAP2L = LOW(65536-52); // baud_rate = 19200 // RCAP2H = HIGH(65536-52);
RCAP2L = LOW(65536-26); // baud_rate = 38400 RCAP2H = HIGH(65536-26);
TCLK = 1;
RCLK = 1;
TR2 = 1; // attiva il timer
TI = 0; // azzero flag interrupt relativo
a tx ok
RI = 0; // azzero flag interrupt relativo
a rx ok
ES = 1; // abilito uart a generare interrupt }
// INIZIALIZZAZIONE PCA void init_pca()
{
//configurazione PCA
CMOD = 0x05; //scelgo come il clock timer0 ov e abilito interrupt quando c'è overflow
//configurazione del timer0
TMOD = TMOD & 0xF0; //selezione il modo 2 TMOD = TMOD | 0x02;
TCON = TCON & 0xCF; // disabilito timer0 e resetto flag relativo }
void init_ADC() {
ADCF = 0x81; // configuro P1.0 (corsa), P1.7(corrente) come ingresso ADC
ADCLK = 12; // Clock ADC = 16000/2/ADCLK kHx (max 700 kHz) ADCON = 0x20; // ADEN
EADC = 1;
}
Appendice B Firmware
//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
// ************************************* NODO 1
*****************************************
/* CONFIGURAZIONE PERIFERICHE uC
FOSC = 16 MHz e 6 cicli x istruzione (X2 = 2) TIMER 0 -> clock PCA
TIMER 1 -> orologio di sistema TIMER 2 -> clock uart
PCA moduli 1, 2, 3, 4 -> CAPTURE MODE
*/
// @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ config.h @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#ifndef _CONFIG_H_
#define _CONFIG_H_
#define KEIL // è utilizzata in compiler.h
//---INCLUDO FILE REGISTRI E INTESTAZIONE LIBRERIE ---
#include "AT89C51CC03/include/compiler.h"
#include "AT89C51CC03/include/at89c51cc03.h"
#include "AT89C51CC03/include/can_lib.h"
#include "AT89C51CC03/include/interfacciamento_power.h"
//--- PARAMETRI DI CONFIGURAZIONE SOFTWARE --- // OROLOGIO (UN TICK OGNI 10 ms)
#define RELOAD_TIMER1 0 // genera un interrupt ogni // 1/(Fosc/12/(256-
RELOAD_TIMER1)) = 0.192ms
#define CONTA_CICLI_TIMER1 51 // conta CONTA_CICLI_TIMER1+1 interrupt // prima di avere un nuovo tick
#define CONTA_CICLI_ADC 4 // conta CONTA_CICLI_ADC+1 interrupt // prima di avere un nuovo
campionamento ADC
// TEMPORIZZAZIONE STATI
#define CYCLES_RESET 5
#define CYCLES_SLEEP 100
#define CYCLES_MONIT 1
//--- DEFINIZIONE NOMI SIMBOLICI ALLE PORTE uC ---
#define PORTA_IN_on_off_A P2
Appendice B Firmware
#define CAVALLETTO 5 // (P2.5)
#define SOSPENSIONE_ADC_CH 0 //P
#define CORRENTE_ADC_CH 7
#define CICLI_ATTIVAZIONE_MOTORE 10
#define CICLI_ATTIVAZIONE_MOTORE_OFF 9
#define NUM_SAMPLE_CORRENTE 250 //Tsample = 1ms
#define SALTA_LETTURE 2
#define RESET_CTRL_TIMEOUT 1500
#define MAX_CORRENTE 125
#define CICLI_NUOVA_MISURA 6000 //2 min tempo dopo il quale ripete la misura
#define CICLI_VEL_ZERO 2000 //20s t
#define NUM_CAMPIONI_PRELEVATI_SAL 1500 // 1,5 sec campiono a 1kHz
#define NUM_CAMPIONI_PRELEVATI_DISC 1000 // 1 sec campiono a 1kHzempo a vel nulla dopo il quale ripete la misura
#define CICLI_INRANGE_PRIMA_MISURA 250
//#define MOTORE(x) {P1_3 = !x;} //inversione sulla scheda //#define DIR_MOTORE(x) {P2_1 = x;}
#define MOTORE_DOWN 0
#define MOTORE_UP 1
#define INA_DRIVER P2_0
#define INB_DRIVER P2_1
#define MOTOR_CTRL(stato_m, dir_m) { INA_DRIVER = !dir_m; \ INB_DRIVER = (stato_m&&dir_m) || (!stato_m&&!dir_m); }
/* esempi di utilizzo MOTORE = MOTORE_ON;
MOTORE = UP; MOTORE = DOWN;
*/
//--- INTERFACCIA BOOTLOADER ---
#define __API_JMP_BOOTLOADER (*((const void(code*)(void)) 0xFBF1 ))
#define __API_FLASH_ENTRY_POINT (*((const void(code*)(void)) 0xFFC0 ))
#define __api_rd_NNB() __api_rd_generic(_COMMAND_RD_XAF, 0x1F)
#define __api_rd_CRIS() __api_rd_generic(_COMMAND_RD_XAF, 0x20)
#define MAP_BOOT AUXR1 |= MSK_AUXR1_ENBOOT;
#define UNMAP_BOOT AUXR1 &= ~MSK_AUXR1_ENBOOT;
#define _COMMAND_RD_XAF 5
Uchar __api_rd_generic (Uchar command, Uchar dpl);
Appendice B Firmware
//--- DICHIARAZIONE MACRO ---
#define BYTE0(U32) ((Uchar) (U32))
#define BYTE1(U32) ((Uchar) (U32 >> 8))
#define BYTE2(U32) ((Uchar) (U32 >> 16))
#define BYTE3(U32) ((Uchar) (U32 >> 24))
//--- DICHIARAZIONE TIPI --- typedef enum { STATO_RESET = 0,
STATO_SLEEP = 1, STATO_ON = 2, STATO_PROG = 3 } type_stato_nodo;
//--- DICHIARAZIONE VARIABILI GLOBALI --- // variabili di controllo
extern Uchar cris; // identificatore base msg FLIP extern Uchar id_nodo;
extern Uchar modo_prog;
extern Uchar task_in_progress; // attivazione ciclo lento extern type_stato_nodo stato_nodo, nuovo_stato_nodo;
extern Uchar cicli_dopo_off;
extern Uchar stato_L, stato_H;
extern bit dir_m, cmd_m, stato_m, leggi, setta, errore, cav, fine_corsa, done, vel_inrange, set, setting;
extern bdata Uchar controllo;
extern bit enable_log, leggi_precarico, azzera_precarico, setta_precarico, setta_corsa, controllo_remoto, attiva_m, m_up_down;
extern Uchar velocita, corsa_impostata, temperatura;
extern Int8 livello_precarico, nuovo_livello_precarico;
extern Int32 corsa_media;
//variabili per il controllo della corrrente assorbita //extern Uint8 s_m, misura_in_corso;
extern bit s_m, misura_in_corso, prima_misura;
// variabili d'ingresso locali extern bdata Uchar in_on_off_A;
extern bit cav_lat;
extern volatile Uint16 sospensione, pressione, precarico, corrente_media, corrente, corrente_media_sal, corrente_media_disc, corrente_media_assorbita;
extern volatile Uint16 corrente_media;
extern volatile Uint16 num_sample_corrente;
extern volatile Uchar nuova_misura_vel;
extern volatile Uint16 delta_tempo;
extern volatile Uchar num_cicli_contati;
//variabili d'ingresso remote extern Uchar chiave;
// variabili d'ingresso remote rx extern bdata Uchar controllo_rx;
Appendice B Firmware
extern bit enable_log_rx, leggi_precarico_rx, azzera_precarico_rx, setta_precarico_rx, setta_corsa_rx, controllo_remoto_rx, attiva_m_rx, m_up_down_rx;
extern Uchar livello_precarico_rx;
// variabili d'uscita locali // variabili per il logging
#define PERIODO_LOG 10 // periodicità di invio del pacchetto in multipli di 10 ms
#define NUM_BYTE_PACCHETTO_LOG 14 // numero byte pacchetto extern Uchar pacchetto_log[NUM_BYTE_PACCHETTO_LOG];
#endif //
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
This document was created with Win2PDF available at http://www.win2pdf.com.
The unregistered version of Win2PDF is for evaluation or non-commercial use only.
This page will not be added after purchasing Win2PDF.