Ho scritto un po di codice ma non ne sono convinto, il codice funziona ve lo spiego brevemente:
L' idea è quella di usare il timer0 come un system timer, cioè un timer che scorre sempre, viene avviato con il PIC e terminerà con lo shutdown del PIC.
E' stato configurato per ottenere un interrupt ogni 10ms, e incrementare un contatore ogni volta che accade.
Il software in se , non fa altro che pilotare due motori attraverso un driver LM297 , c' è un pulsante che premuto la prima volta, fa girare i motori in un senso, premendo per la seconda volta girano nell' altro senso( basta cambiare la polarità sui pin dell' integrato LM297), fin qui tutto benone.
Quando scatta l' interrupt sulla PORTAB( il pulsante) viene avviata la routine di antirimbalzo, la quale, la prima volta che è chiamata non fa altro che memorizzare il valore corrente del contatore usato nel timer0, la seconda volta che è chiamata(secondo interrupt), esegue la differenza tra il valore attuale di quel contatore e il vecchio valore, se superiore ad una certa soglia(indica che sono passati "x" ms ) allora avvia la routine di controllo del motore.
Il mio problema è che , prima o poi, ci sarà una differenza negativa( quando il contatore vecchio sarà maggiore rispetto a quello attuale( dai conti che ho fatto dopo un' ora di funzionamento).
Sapete dirmi come ovviare a questo problema e/o come scrivere un debouncing efficiente?
Probabilmente mi sto complicando la vita inultimente, ed il problema è di facile soluzione, ma al momento è la strada più semplice che vedo.
Non posso usare le istruzioni "__delay(ms)" in quanto tali istruzioni bloccano l' esecuzione del software fino al loro completamento, ed è una cosa che voglio evitare.
ecco il codice in C:
- Codice: Seleziona tutto
/*
* File: newmain.c
* Author: Davide
*
* Created on 30 novembre 2015, 18:30
*/
// importo le librerie
#include<stdio.h>
#include <htc.h>
#include <xc.h>
//motore 1 comandato da IN1 e IN3
//motore 2 comandato da IN2 e IN4
// #pragma config statements should precede project file includes.
// Use project enums instead of #define for ON and OFF.
// CONFIG
#pragma config FOSC = INTOSCCLK // Oscillator Selection bits (INTOSC oscillator: CLKOUT function on RA6/OSC2/CLKOUT pin, I/O function on RA7/OSC1/CLKIN)
#pragma config WDTE = OFF // Watchdog Timer Enable bit (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable bit (PWRT disabled)
#pragma config MCLRE = ON // RA5/MCLR/VPP Pin Function Select bit (RA5/MCLR/VPP pin function is MCLR)
#pragma config BOREN = OFF // Brown-out Detect Enable bit (BOD disabled)
#pragma config LVP = OFF // Low-Voltage Programming Enable bit (RB4/PGM pin has digital I/O function, HV on MCLR must be used for programming)
#pragma config CPD = OFF // Data EE Memory Code Protection bit (Data memory code protection off)
#pragma config CP = OFF // Flash Program Memory Code Protection bit (Code protection off)
//prototipi delle funzioni
void rotazione(int PressioniPulsate);
void antirimbalzo(void);
#define _XTAL_FREQ 4000000
#define Enable_Motori RA0
char pulsate=0;
char timer=0;
int differenza=0;
int valoretimerold=0;
char isFirstTime=0;
void main(void){
TRISA=0b00000;
TRISB=0b00010000;
PORTA=0b00000;
//PORTA=0b01010;//test mode
PORTB=0;
CMCON=0x07;// spengo i comparatori
OPTION_REG=0b10000101;
TMR0 = 99; // preset for timer register // interrupt ogni circa 10ms
INTCON=0b10101100;// accendo interrupt sulla porta B e del timer0
while(1){
}
}
void antirimbalzo(void){
if(!isFirstTime){
//memorizzo il valore della prima pressione
valoretimerold=timer;
isFirstTime=1; // non è più la prima volta
}else{
differenza=timer-valoretimerold;
if (PORTBbits.RB4 && ((differenza)>1)){// antirimbalzo
pulsate++;
rotazione(pulsate);
if (pulsate>1)
pulsate=0;
}
}
}
void rotazione(int PressioniPulsate){
//abilito i motori, sono sempre abilitati
Enable_Motori=1;
if (PressioniPulsate==1){
//indicatore led
PORTA=0b01011;
PORTAbits.RA7=1;
//porto i motori in posizione
__delay_ms(5000);//delay necessario, valutare di rimuoverlo usando un interrupt
//fermo i motori
PORTA=0b00000;
}else{
// attendo che i motori siano fermi
PORTA=0b00000;
PORTAbits.RA7=1;
__delay_ms(500);//delay necessario, valutare di rimuoverlo usando un interrupt
//indicatore led
PORTAbits.RA7=0;
//Effettuo l' inversione
PORTA=0b10101;
//porto i motori in posizione
__delay_ms(5000);//delay necessario, valutare di rimuoverlo usando un interrupt
//fermo i motori
PORTA=0b00000;
}
}
void interrupt ISR(void){
if (TMR0IF){
TMR0IF=0;
TMR0 = 99;
// generato interrupt timer0 ogni 10 ms
timer++;
if (timer>3600)//resetto il timer dopo un ora
timer=0;
}
// è stato premuto un pulsante?
if (RBIF){
//genera interrupt sia sul fronte di salita che di discesa
//quindi chiamo la funzione antirimbalzo due volte
// antirimbalzo
// Verificare sul progetto finale
antirimbalzo();
RBIF=0;
}
}
Il PIC che sto usando è un PIC16F628A, e purtroppo genera un'interrupt unico , sia sul fronte di salita che di discesa.

Elettrotecnica e non solo (admin)
Un gatto tra gli elettroni (IsidoroKZ)
Esperienza e simulazioni (g.schgor)
Moleskine di un idraulico (RenzoDF)
Il Blog di ElectroYou (webmaster)
Idee microcontrollate (TardoFreak)
PICcoli grandi PICMicro (Paolino)
Il blog elettrico di carloc (carloc)
DirtEYblooog (dirtydeeds)
Di tutto... un po' (jordan20)
AK47 (lillo)
Esperienze elettroniche (marco438)
Telecomunicazioni musicali (clavicordo)
Automazione ed Elettronica (gustavo)
Direttive per la sicurezza (ErnestoCappelletti)
EYnfo dall'Alaska (mir)
Apriamo il quadro! (attilio)
H7-25 (asdf)
Passione Elettrica (massimob)
Elettroni a spasso (guidob)
Bloguerra (guerra)











