|
Pulsante antirimbalzo (Debounce button) con
autoincremento
Letura / Scrittura
della EEprom interna (EEprom read write)
Gestione Interrupt sulla porta RB0
Gestione Interrupt TMR0
Lettura ADC interno PIC16F87X
Una
super barra di avanzamento con un normale display LCD
SCRITTURA
EEPROM DATI DURANTE LA COMPILAZIONE
PROGRAMMARE I FUSES
|
DEBOUNCE BUTTON
 |
/* Subroutine gestione pulsante antirimbalzo con autoincremento rapido
/* Restituisce un numero maggiore di zero se il pulsante è premuto.
/* Nuova versione per la gestione di più pulsanti.
/* Author: Antonio Bruno 09/2003 toniobr@libero.it */
#include <pic.h>
#include "delay.h"
#define N 10 //N volte autoincremento lento
char button(unsigned *addres,char bitn)
{
static char cnt=0;
static unsigned *old_addr;
static char old_bitn=0;
if (*addres & bitn)
{
if (cnt==0){
cnt+=1;
old_addr=addres;//Memorrizza l'ind. del'ultimo
old_bitn=bitn;
return(cnt); //pulsante premuto
}
if (cnt==1){
DelayMs(250);
cnt+=1;
return(0);
}
if (cnt<=N){ //Ripetizione dell'auto_lento=5
DelayMs(200); //Tempo autoincremento lento
cnt+=1;
return(cnt);
}
if (cnt>N){
DelayMs(25); //Tempo autoincremento rapido
return(cnt);
}
}
if (!(*old_addr & old_bitn)) //azzera il contatore solo quando
return (cnt=0); //si porta a liv. 0 l'ultimo puls.
return (0); //premuto.
}
/*---------------- EOF gestione pulsante antirimbalzo-----------------*/
nel main inserire le definizioni dei pulsanti es. :
/*-------- Definizioni per i pulsanti antirimbalzo----------*/
#define START (unsigned *)&PORTB,2 // inp 7 6 5 4 3 2 1 0
#define UP (unsigned *)&PORTD,64 // val 128 64 32 16 8 4 2 1
#define DOWN (unsigned *)&PORTD,32 // es. se utilizziamo PORTB1 val sarà 2
#define PG (unsigned *)&PORTD,128
la chiamata sarà es.:
if(button(PG))
...... 
|
|
LETTURA SCRITTURA EEPROM
INTERNA
 |
/*
*******************************************************************
* Funzione per la scrittura dati nella memoria EEprom del PIC
*
* Author : Antonio Bruno 08/2003
*
*
*******************************************************************/
void eeprom_w(char addr,char value)
{
EEADR=addr; // indirizzo cella memoria eeprom
EEDATA=value; // valore da memorizzare
GIE=0; // disabilita interrupt
WREN=1; // abilita la scrittura
EECON2=0x55; // Sequenza richiesta
EECON2=0xAA;
WR=1;
while(WR);
WREN=0;
GIE=1; // riabilita global interrupt
}
/*---------------------- EOF funzione eeprom_w --------------------- */
/* *******************************************************************
* Funzione per la ettura dati dalla memoria EEprom del PIC *
* Author : Antonio Bruno 08/2003 *
* *******************************************************************/
unsigned char eeprom_r(char addr)
{
EEADR=addr; // indirizzo cella
memoria eeprom
EEPGD=0; // accedi alla
eeprom dati (no 16f84)
RD=1;
return EEDATA;
}
/*---------------------- EOF funzione eeprom_r
--------------------- */
/*---------------------- EOF funzione eeprom_r --------------------- */
|
|
GESTIONE INTERRUPT RB0
 |
/*******************************************************
*
* Gestione interrupt Porta RB0
* Bruno Antonio 08-2003
*
********************************************************/
void interrupt prv_int(void)
{
if(INTF){ //Flag provenienza int
if(Led_A0) //INTF = RB0
Led_A0=0;
else
Led_A0=1;
INTF=0; //Riabilita linterrupt flag
} //porta RB0,altrimenti non
} //vi saranno altri int RB0
/*-------------------- EOF interrupt ----------------*/
|
|
GESTIONE INTERRUPT TMR0
 |
/*******************************************************
* *
* Gestione interrupt tmr0 (esmpio impulso i secondo ca)*
* Bruno Antonio 08-2003 *
* *
********************************************************/
//Settare nel main:
//config timer0 interrupt
OPTION=0b10000111;
GIE=1; //--> Abilita global interrupt
T0IE=1; //--> Abilita l'interrupt sul tmr0
//eof config interrupt
//quindi, il prescaler sarà = 256, per cui, il tmr0 verrà
//decrementato ogni 1.000.000/256=3906 volte al secondo
//supponendo di utilizzare una fclock(quarzo) di 1MHz.
//Essendo il tmr0 un registro a otto bit e quindi 256 valori,
//l'interrupt verr… generato 3906/256=15 volte al secondo(ricorda che
//l'interrupt viene generato ogni qualvolta il tmr0 passa per lo 0).
void interrupt prv_int(void)
{
static int cnt=15;
if(T0IF){ //Flag int tmr0
cnt--;
if (!cnt){
Led_A0=!Led_A0;
cnt=15;
}
T0IF=0; //Riabilita linterrupt flag
} //altrimenti non
} //vi saranno altri int TMR0
/*-------------------- EOF interrupt ----------------*/
|
|
ADC INTERNO PIC16F877 |
|
/*
*******************************************************************
* Funzione per la lettura dell'ADC interno del PIC16F877 *
* Ritorna un valore intere che rappresenta il valore di tensione *
* letto su dieci bit. *
* Author : Antonio Bruno 08/2003 *
*
*******************************************************************/
/* Il valore per canale va da 0 a 7.
Dal main inviare almeno una volta il comando adc_config.
Impostare ADCON1 nella sub adc_config con un valore diverso se si
vuole utilizzare una configurazione diversa (vedi datasheet 16f87x).
nb. La frequenza del clock di conversione deve essere uguale a:
fosc/2 per quarzo <=1,25Mhz ; fosc/8 per quarzo <=5Mhz ;
fosc/32 per quarzo <=20Mhz ;*/
#include <pic.h>
#include "adc.h"
void adc_config(void)
{
ADCON1 = 0b10000101;//formato e imp. canali analog inp
(RA0=AN0-RA1=AN1-RA3=Vref)
}
unsigned int adc_read(unsigned char canale)
{
unsigned int val=0;
ADCON0 = 0b10000001; //imposta clock conv.=fosc/32 e
<ON> adc
ADCON0|=canale<<3; // seleziona il
can. da leggere
ADGO=1; // start conversione
while(ADGO) // attende la fine della conversione
continue;
val=(ADRESH<<8)|ADRESL;
return(val) ;
}
|
|
Una super barra di avanzamento con un normale display LCD
 |
/*********************************************************************************
Project: Barra di avanzamento per display lcd
Author : Bruno Antonio ---> toniobr
Date : 20/11/03
*********************************************************************************/
//Per poter realizzare simboli personalizzati ,il display prevede
un'apposita
//zona di memoria chiamata CGRAM da 512 byte (8 simboli max
realizzabili).
//E possibile scrivere su questa memoria inviando il comando 40hex
(vedi datasheet)
//che tradotto vuol dire scrivi nella CGRAM dall'indirizzo 0.
//Ogni byte corrisponde a 5 pixel orizzontali di un carattere per
cui un carattere
//occupa 8*8=64 byte.
//Ogni simbolo memorizzato , verrà indirizzato all'interno della
CGROM partendo
//dall'indirizzo 0 al 7.
//DDRAM=disply data ram
//CGROM=rom generatore di caratteri (quando scriviamo "A" inviamo il
codice 65dec
//che nella CGROM corrisponde al carattere "A").
//CGRAM=ram grnetatore di caratteri
/*
PIN I/O PIC DEMOBOARD V1
RB0 pulsante nero
RB1 pulsante blu
RB2
RB3 EN display
RB4 DB4 display
RB5 DB5 display
RB6 DB6 display
RB7 DB7 display
RA0
RA1
RA2 TX seriale
RA3 RX seriale
RA4 RS display
*/
#define XTAL_FREQ 4MHZ /* Crystal frequency in MHz */
#include <pic.h>
#include "lcd.h"
#include "delay.h"
#include "stdio.h"
//Configuration bit
__CONFIG(XT & WDTDIS & PWRTEN);
main(void)
{
unsigned char c=0;
unsigned char cnt=0;
TRISB = 0b00000011;
TRISA = 0b00001000;
PORTB=0;
PORTA=0;
lcd_init();
cgram_goto(0x0); //Indirizzo CGRAM da cui iniziare (0).
for(cnt=0;cnt<8;cnt++) //scrive nella CGRAM (address 0) il carattere
|
lcd_putch(0b10000);
for(cnt=0;cnt<8;cnt++) //scrive nella CGRAM (address 1) il carattere
| |
lcd_putch(0b10100);
for(cnt=0;cnt<8;cnt++) //scrive nella CGRAM (address 2) (il
carattere | | |
lcd_putch(0b10101);
for(c=0;c<16;c++){ //16= n caratteri LCD
for(cnt=0;cnt<3;cnt++){
lcd_goto(c); //posizionamento sull'indirizzo DDRAM su cui scrivere.
lcd_putch(cnt); //visualizza per ogni cella DDRAM i tre caratteri
DelayMs(100); //creati nella CGRAM.
}
}
//Creare un simbolo personalizzato (uomo).
cgram_goto(0x0); //CGRAM indirizzo 0
//Gli 1 seguenti rappresenano l'immagine , metti a fuoco!
lcd_putch(0b01110);
lcd_putch(0b10001); //CGRAM indirizzo 1
lcd_putch(0b01110); //CGRAM indirizzo 2
lcd_putch(0b00100); //........
lcd_putch(0b11111);
lcd_putch(0b00100);
lcd_putch(0b01010);
lcd_putch(0b10001); //CGRAM indirizzo 7
//nb. ad ogni operazione di scritura , l'indirizzo si autoincrementa.
lcd_goto(0x42);//seconda linea (80hex è l'indirizzo 0 della DDRAM e
cioè
lcd_putch(0); //la proma cella del display.
for(;;)
;
}
Scarica l'intero progetto |
|
SCRITTURA
EEPROM DATI DURANTE LA COMPILAZIONE |
/* ---macro per memorizzare valori all'interno della eeprom dati--- */
/* n.b. La macro deve essere inserita prima di qualunque funzione ,
/* subito dopo la #include <pic.h>. */
__EEPROM_DATA(1,2,3,4,5,6,7,8); //Memorizza nella eeprom dati i seguenti valori
__EEPROM_DATA(0x9,0x10,0x11,0x12,0x13,0x14,0x15,0x16); // valori esadecimale
__EEPROM_DATA(10,11,12,13,14,15,16,17); // valori decimale
|
|
PROGRAMMARE I FUSES |
|
Macro per l'impostazione dei fuses
durante la compilazione.
I fuses non sono altro che flag di
settaggio di alcune funzioni
hardware del pic tra cui il tipo
di CLOCK , se abilitare o meno
il POWER ON RESET , se bilitare i
WATCHDOG .... vedi datasheet 16f877 sezione
" 12.0 SPECIAL FEATURES OF THE CPU
".
ESEMPIO:
__CONFIG(HS & WDTDIS & PWRTEN &
BORDIS & LVPDIS & DUNPROT & WRTDIS & DEBUGDIS & UNPROTECT );
I POSSIBILI VALORI PER IL
PIC16F877 SONO:
*osc configurations*/
RC 0x3FFF // resistor/capacitor
HS 0x3FFE // high speed crystal/resonator
XT 0x3FFD // crystal/resonator
LP 0x3FFC // low power crystal/resonator
/*watchdog*/
WDTEN // enable watchdog timer
WDTDIS // disable watchdog timer
/*power up timer*/
PWRTEN // enable power up timer
PWRTDIS // disable power up timer
/*brown out reset*/
BOREN // enable brown out reset
BORDIS // disable brown out reset
/*Low Voltage Programmable*/
LVPEN // low voltage programming enabled
LVPDIS // low voltage programming disabled
/*data code protected*/
DP // protect data code
// alternately
DPROT // use DP
DUNPROT // use UNPROTECT
/* Flash memory write enable/protect */
WRTEN /* flash memory write enabled */
WRTDIS /* flash memory write protected/disabled */
/*debug option*/
DEBUGEN // debugger enabled
DEBUGDIS // debugger disabled
/*code protection*/
PROTECT /* protect program code */
UNPROTECT /* do not protect the code */
|
|
|
|
|
|
|
|
|
|
|
|
|
|