O software começa com as definições necessários para o compilador utilizado (PIC C) e as definições dos pinos aos quais estão conectados os sinais que nos interessam:
#include <16F676.h>Vamos manter o LED usado anteriormente. Para isto precisamos do contador que temporiza o seu apagamento. Vamos acrescentar um variável para contar as detecções de imã:
#device adc=8
#use delay(clock=4000000)
#fuses NOWDT, NOCPD, NOPROTECT
#fuses INTRC_IO, PUT, BROWNOUT, MCLR
#define DLY_SR 10 // delay p/ shift register
#define TAXA_DISP 3 // taxa de varredura dos displays
#define TAXA_ATL 100 // taxa de atualização dos valores nos displays
#define TEMPO_LED 600 // tempo que o LED fica aceso
// Pinos de E/S
#define SENSOR PIN_A5
#define LED PIN_A4
#define SHIFT_DS PIN_A2
#define SHIFT_ST PIN_C0
#define SHIFT_SH PIN_C1
#define SEL_1 PIN_C5
#define SEL_2 PIN_C4
#define SEL_3 PIN_C3
#define SEL_4 PIN_C2
// Controle do LEDUm vetor de quatro posições (segto) armazena a situação dos segmentos nos quatro dígitos do display. Na interrupção de timer usaremos este vetor para refrescar continuamente o display. Na hora de apresentar um novo valor, os segmentos serão preparados inicialmente em um segundo vetor (newsegto).
volatile int16 cntLed;
// Contador de passagens do imã
volatile unsigned int16 cntIma = 0;
Uma variável passo controlará a atualização do display:
- 0 indica que o display deve ser refrescado com o valor em segto
- 1 indica que um novo valor deve ser montado em newsegto
- 2 indica que newsegto tem um novo valor que deve ser copiado para segto
// Controle dos segmentos do displayNo programa inicial temos a iniciação das entradas e saídas e do timer, seguido de um laço infinito onde um novo conteúdo para o display é calculado periodicamente.
// Um byte para cada segmento
// Bit 7 = segto G, Bit 6 = segto F, .. Bit 1 = segto A
unsigned int8 segto [4];
unsigned int8 newsegto [4];
unsigned int8 passo = 0;
// Segmentos a serem acesos para cada dígito
const unsigned int8 digitos[10] =
{
0b01111110, 0b00001100, 0b10110110, 0b10011110, 0b11001100,
0b11011010, 0b11111010, 0b00001110, 0b11111110, 0b11011110
};
// P R O G R A M A P R I N C I P A LO tratamento do sensor é igual ao que já vimos antes, acrescido do incremento do contador de detecções:
void main()
{
unsigned int16 aux;
// Iniciações do hardware
set_tris_a (0xEB); // A4 e A2 output
#use fast_io(A)
set_tris_c (0xC0); // C0 a C5 output
#use fast_io(C)
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_comparator(NC_NC);
setup_vref(FALSE);
setup_adc(ADC_OFF);
output_low (LED);
output_low (SEL_1);
output_low (SEL_2);
output_low (SEL_3);
output_low (SEL_4);
enable_interrupts(INT_RA5);
enable_interrupts(INT_RTCC);
enable_interrupts(GLOBAL);
for (;;)
{
if (passo == 1)
{
disable_interrupts(GLOBAL);
aux = cntIma;
enable_interrupts(GLOBAL);
newsegto[0] = digitos [aux / (unsigned int16) 1000];
newsegto[1] = digitos [(aux/100) % 10];
newsegto[2] = digitos [(aux/10) % 10];
newsegto[3] = digitos [aux % 10];
passo = 2;
}
}
}
// S E N S O RNa interrupção de tempo real temos as temporizações para o LED e o display:
//////////////////////////////////////////////
// Interrupcao de mudança do sinal
// Ocorre qdo sensor detecta imã
//////////////////////////////////////////////
#int_ra
void Sensor_ISR ()
{
output_high (LED);
input_a();
clear_interrupt (INT_RA5);
cntLed = TEMPO_LED;
cntIma++;
if (cntIma > 9999)
cntIma = 0;
}
// T E M P OPor último, temos as rotinas de atualização do display:
//////////////////////////////////////////////
// Interrupcao de tempo real
// Ocorre a cada 256 uSeg
//////////////////////////////////////////////
#int_RTCC
void RTCC_isr()
{
static unsigned int8 cont_disp = TAXA_DISP;
static unsigned int8 cont_atl = TAXA_ATL;
// Tratamento do LED
if (cntLed)
{
if (--cntLed == 0)
output_low (LED);
}
// Atualização do Display
if (--cont_atl == 0)
{
passo = 1;
cont_atl = TAXA_ATL;
}
if (passo == 2)
AtlDisp ();
if (--cont_disp == 0)
{
VarreDisp ();
cont_disp = TAXA_DISP;
}
}
// D I S P L A YO vídeo abaixo mostra hardware e software funcionando. Os mais atentos perceberão que estamos contando as detecções de imã e portanto a contagem é incrementada de dois a cada volta.
static void AtlDisp (void)
{
segto[0] = newsegto[0];
segto[1] = newsegto[1];
segto[2] = newsegto[2];
segto[3] = newsegto[3];
passo = 0;
}
static void VarreDisp (void)
{
static unsigned int8 disp = 0;
unsigned int8 i, mask;
// coloca os valores dos segmentos no registrador
for (i = 0, mask = 0x80; i < 8; i++)
{
if (segto[disp] & mask)
output_low (SHIFT_DS);
else
output_high (SHIFT_DS);
delay_us (DLY_SR);
output_high (SHIFT_SH);
delay_us (DLY_SR);
output_low (SHIFT_SH);
delay_us (DLY_SR);
mask = mask >> 1;
}
// seleciona o display atual
if (disp == 0)
{
output_low (SEL_4);
output_high (SEL_1);
}
else if (disp == 1)
{
output_low (SEL_1);
output_high (SEL_2);
}
else if (disp == 2)
{
output_low (SEL_2);
output_high (SEL_3);
}
else
{
output_low (SEL_3);
output_high (SEL_4);
}
// acende os segmentos
output_high (SHIFT_ST);
delay_us (DLY_SR);
output_low (SHIFT_ST);
// passa para o dígito seguinte
disp = (disp + 1) & 3;
}
Vamos fechar esta série no próximo post, adaptando o código para apresentar no display o número de rotações por minuto e usar os outros dois tipos de sensores.
Nenhum comentário:
Postar um comentário