Ir ao conteúdo
  • Cadastre-se

Programando PIC16F628A com todas as portas


Marcos Baungartner

Posts recomendados

  • Membro VIP

Fiz um programa em C no compilador PCW da CCS para controlar um carrinho de controle remoto, estou usando as 16 portas de entrada e saída, porém quando vou testar o PIC no meu circuito ora ele funciona corretamente, ora não funciona. acredito que falta especificar alguma parametro na programação, estou usando o clock interno do PIC de 4MHz.

Essa é a programação:

#include <16f628a.h>
#use delay(clock=4000000)
#fuses intrc_io,nowdt

void main(void)
{
int sensorf=0, sensort=0, x=0; //x serve para frear uma unica vez
while(true)
{
//COMANDOS DE DIRECAO EM REPOUSO
if(input(PIN_A0)==0) //ENTRADA 0 for 0
{
output_low(PIN_B0); //FRENTE desliga
}

if(input(PIN_A1)==0) //ENTRADA 1 for 0
{
output_low(PIN_B1); //RE desliga
}

if(input(PIN_A2)==0) //ENTRADA 2 for 0
{
output_low(PIN_B2); //ESQUERDA desliga
output_low(PIN_B5); //APAGA SETA ESQUERDA
}

if(input(PIN_A3)==0) //ENTRADA 3 for 0
{
output_low(PIN_B3); //DIREITA desliga
output_low(PIN_B6); //APAGA SETA DIREITA
}


//SENSORES LIGADOS E DESLIGADOS
if(input(PIN_A4)==0) //ENTRADA 4 for 0
{
sensorf=0; //SENSOR FRENTE desliga
x=0;
}
if(input(PIN_A4)==1) //ENTRADA 4 for 1
{
sensorf=1; //SENSOR FRENTE liga
if(x==0)
{
output_high(PIN_B0); //TRAVA RODAS
output_high(PIN_B1);
delay_ms(1000);
output_low(PIN_B0); //LIBERA RODAS
output_low(PIN_B1);
x=1;
}
}

if(input(PIN_A5)==0) //ENTRADA A5 for 0
{
sensort=0; //SENSOR TRASEIRO desliga
x=0;
}
if(input(PIN_A5)==1) //ENTRADA A5 for 1
{
sensort=1; //SENSOR TRASEIRO liga
if(x==0)
{
output_high(PIN_B0); //TRAVA RODAS
output_high(PIN_B1);
delay_ms(1000);
output_low(PIN_B0); //LIBERA RODAS
output_low(PIN_B1);
x=1;
}
}




//COMANDOS DE DIRECAO ATIVOS
if(input(PIN_A0)==1 && sensorf==0) //ENTRADA 0 for 1 e sensor frente for 0
{
output_high(PIN_B0); //FRENTE liga
output_low(PIN_B1);
}

if(input(PIN_A1)==1 && sensort==0) //ENTRADA 1 for 1 e sensor frente for 0
{
output_high(PIN_B1); //RE liga
output_low(PIN_B0);
}

if(input(PIN_A2)==1) //ENTRADA 2 for 1
{
output_high(PIN_B2); //ESQUERDA liga
output_low(PIN_B3);
output_high(PIN_B5); //PISCA SETA ESQUERDA por 500ms
delay_ms(500);
output_low(PIN_B5); //PISCA SETA ESQUERDA por 500ms
}

if(input(PIN_A3)==1) //ENTRADA 3 for 1
{
output_high(PIN_B3); //DIREITA liga
output_low(PIN_B2);
output_high(PIN_B6); //PISCA SETA DIREITA por 500ms
delay_ms(500);
output_low(PIN_B6); //PISCA SETA DIREITA por 500ms
}




}
}

Alguém saberia me dizer o que pode estar faltando na programação?

Agradeço.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
desabilite os comparadores (cmcom = 7) olhe no datasheet

poste o hardware, pode ser pau de hardware

na verdade eu só alimentei o PIC com 5v e testei as saidas e entradas com o multimetro. então nao pode ser problema de circuito. Para desabilitar os comparadores precisa usar alguma parametro na programação?

O cmcom = 7 não funciona no compilador PICC.

Link para o comentário
Compartilhar em outros sites

na verdade eu só alimentei o PIC com 5v e testei as saidas e entradas com o multimetro. então nao pode ser problema de circuito. Para desabilitar os comparadores precisa usar alguma parametro na programação?

O cmcom = 7 não funciona no compilador PICC.

desculpe, além de um erro di digitação tem o + que acredito estar errado rsrs, tente

cmcon == 7

se eu não me engano para você atribuir um valor você tem que colocar dois sinais de igual, e tinha um erro de digitação que o cmcon estava com M.

Para você entender, olhe o datasheet do pic e vai no capítulo 9.0onde fala do módulo comparador, olhe a imagem de configuração e no radapé dela, as configurações dos bit 2-0, verá que ele direciona para outra imagen, olhe o primeiro quadrante onde a função é desativar os comparadores, verás que o valor que ele manda colocar nos bits 2-0 é 111(binario) que convertendo é o 7 em decimal. isso é só para você entender o porque desse número e também ver que o comando cmcon é do próprio PIC, acredito que não mude de compilador para compilador. Pelo menos aqui eu coloco cmcon e funciona belezera.

Link para o comentário
Compartilhar em outros sites

  • Membro VIP
desculpe, além de um erro di digitação tem o + que acredito estar errado rsrs, tente

cmcon == 7

se eu não me engano para você atribuir um valor você tem que colocar dois sinais de igual, e tinha um erro de digitação que o cmcon estava com M.

Para você entender, olhe o datasheet do pic e vai no capítulo 9.0onde fala do módulo comparador, olhe a imagem de configuração e no radapé dela, as configurações dos bit 2-0, verá que ele direciona para outra imagen, olhe o primeiro quadrante onde a função é desativar os comparadores, verás que o valor que ele manda colocar nos bits 2-0 é 111(binario) que convertendo é o 7 em decimal. isso é só para você entender o porque desse número e também ver que o comando cmcon é do próprio PIC, acredito que não mude de compilador para compilador. Pelo menos aqui eu coloco cmcon e funciona belezera.

Então, para atribuir valor é só um sinal de igual mesmo. eu coloquei cmcon=7; dentro do main mas aparece a seguinte mensagem "undefined Identifier cmcon".

modifiquei meu código e acrescentei a linha setup_adc_ports(NO_ANALOGS):

#INCLUDE <16f628a.h>

#USE delay(clock=4000000) //Clock interno de 4MHz

#FUSES NOWDT //Sem Timer Cão de Guarda

#FUSES INTRC_IO //Oscilador Interno e dois pinos de I/O liberados

#FUSES NOPUT //Sem timer de alimentação

#FUSES NOPROTECT //Epprom desprotegida (permite a leitura)

#FUSES NOBROWNOUT //Brownout desabilitado

#FUSES NOMCLR //Pino Master Clear habilitado como porta I/O

#FUSES NOLVP //Programação em baixa tensão desabilitada

#FUSES NOCPD //Código desprotegido (permite a leitura)

setup_adc_ports(NO_ANALOGS); // nao usaremos nenhum porta analogica

setup_adc(ADC_OFF); // desligamos o conversor AD

setup_psp(PSP_DISABLED); // nao utiizamos a porta PSP

void main()

{

int sensorf=0, sensort=0, x=0; //x serve para frear uma unica vez

setup_timer_1(T1_DISABLED); // desabilitarmos o TMR1

setup_timer_2(T2_DISABLED,0,1); // desabilitamos o TMR2

setup_comparator(NC_NC_NC_NC); // desabilitamos os comparadores

setup_vref(FALSE); // desabilitamos a tensão de referencia

porém o pic continua com o mesmo problema, do nada o pino errado começa a mandar tensão.

Link para o comentário
Compartilhar em outros sites

Seu erro é clássico!

Veja como você trata os botões:

if(input(PIN_XY))   //ENTRADA 0 for 0
{
output_low(PIN_MN); //FRENTE desliga
}

Qualquer ruído irá "trigar" o pino.

Leia: Debouncing para iniciantes

Vou te ajudar. Teste com esse debouncing:

if(input(PIN_[B][COLOR="Red"]XY[/COLOR][/B]))   //ENTRADA 0 for 0
{
output_low(PIN_MN); //FRENTE desliga
do {}
while (input(PIN_[B][COLOR="Red"]XY[/COLOR][/B]));
}

Atente-se ao comando de verificar se um botão foi pressionado:

if(input(PIN_A0))   //Se foi apertado...

if(!input(PIN_A0))   //Se foi  NÃO foi apertado...

Considerando que está utilizando nível alto para apertado e nível baixo para não apertado (isso depende de como configurou seu resistor. Se foi de pull-up ou pull-down).

Veja:

push_buttons.jpg

No circuito A, o PIC irá sentir o botão apertado em nível alto. No circuito B, o PIC irá sentir o botão pressionado em nível baixo.

Não faz sentido você utilizar o comando setup_adc_ports(NO_ANALOGS) no 16F628A pois o mesmo não possui pinos analógicos.

Não conferi o código todo.

Qualquer dúvida pergunte.

Falou

Link para o comentário
Compartilhar em outros sites

Parece que você não leu o link que enviei. Vou copiá-lo:

Por definição, quando apertamos um botão, o qual possui um contato mecânico, é gerada uma série de ruidos aleatórios chamados de spikes. Ou seja, a tensão instantânea sobre o botão pode ser qualquer valor, entre os valores que seriam obtidos com o botão em repouso e com o botão ligado após um tempo longo.

Isto pode ser observado com um osciloscópio digital.

A duração desses spikes é pequena, geralmente na ordem de milisegundos, mas o efeito prático é o de que durante esses poucos milissegundos, uma leitura efetuada nesse botão pode interpretar que ele está ligado ou desligado, devido aos ruidos aleatórios que são gerados pelo contato mecânico.

Porém, para um microprocessador, alguns milissegundos são uma eternidade, ou seja, por exemplo, após detectar que o botão foi acionado, mediante UMA ÚNICA LEITURA DO BOTÃO, nosso programa pode executar as funções correspondentes e voltar ao mesmo ponto anterior da leitura do botão, EM MENOS DE 1 milissegundo !!!!

Assim, o efeito que temos é que em vez de o nosso programa interpretar que apertamos o botão APENAS 1 VEZ, ele pode acabar interpretando que apertamos o botão mais de 20 vezes em seguida !!!!!

Claro que dependendo do programa, o resultado pode ser catastrófico !

Tente colocar um delay:

if(input(PIN_A0)==0) // SE ENTRADA 0 for 0
{
delay_ms (75);
output_low(PIN_B0); //FRENTE desliga
}

Falou

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Valeu mesmo pela força Matheus, esse programa é super importante pra mim já que se trata do meu TCC.

Sobre o setup_adc_ports(NO_ANALOGS) eu adicionei porque eu vi outros programadores utilizando para o 16F628A.

Eu também coloquei o delay_ms(100) dentro de todos os IF mas continua com o mesmo problema, eu mando sinal na entrada A0 e ao invés de liberar sinal somente na saída B0 ele está mandando na B0 e B1. Muito estranho isso, ainda mais por estar testando somente o PIC no protoboard, sem outros componentes ligados a ele. Estou alimentando o VDD com 5volts, VSS no comum, e todos os pinos RA como entrada e todos os pinos RB como saída.

Link para o comentário
Compartilhar em outros sites

Sobre o NO_ANALOGS, veja o arquivo 16F628A.h. O mesmo fica na pasta Arquivos de programas>PICC>Devices:


#device PIC16F628A
#nolist
//////// Program memory: 2048x14 Data RAM: 223 Stack: 8
//////// I/O: 16 Analog Pins: 0
//////// Data EEPROM: 128
//////// C Scratch area: 77 ID Location: 2000
//////// Fuses: LP,XT,HS,EC_IO,NOWDT,WDT,NOPUT,PUT,PROTECT,NOPROTECT
//////// Fuses: BROWNOUT,NOBROWNOUT,NOMCLR,MCLR,NOLVP,LVP,INTRC,RC_IO
//////// Fuses: INTRC_IO,RC,NOCPD,CPD
////////
////////////////////////////////////////////////////////////////// I/O
// Discrete I/O Functions: SET_TRIS_x(), OUTPUT_x(), INPUT_x(),
// PORT_x_PULLUPS(), INPUT(),
// OUTPUT_LOW(), OUTPUT_HIGH(),
// OUTPUT_FLOAT(), OUTPUT_BIT()
// Constants used to identify pins in the above are:

#define PIN_A0 40
#define PIN_A1 41
#define PIN_A2 42
#define PIN_A3 43
#define PIN_A4 44
#define PIN_A5 45
#define PIN_A6 46
#define PIN_A7 47

#define PIN_B0 48
#define PIN_B1 49
#define PIN_B2 50
#define PIN_B3 51
#define PIN_B4 52
#define PIN_B5 53
#define PIN_B6 54
#define PIN_B7 55

////////////////////////////////////////////////////////////////// Useful defines
#define FALSE 0
#define TRUE 1

#define BYTE int8
#define BOOLEAN int1

#define getc getch
#define fgetc getch
#define getchar getch
#define putc putchar
#define fputc putchar
#define fgets gets
#define fputs puts

////////////////////////////////////////////////////////////////// Control
// Control Functions: RESET_CPU(), SLEEP(), RESTART_CAUSE()
// Constants returned from RESTART_CAUSE() are:
#define WDT_FROM_SLEEP 3
#define WDT_TIMEOUT 11
#define MCLR_FROM_SLEEP 19
#define MCLR_FROM_RUN 27
#define NORMAL_POWER_UP 25
#define BROWNOUT_RESTART 26


////////////////////////////////////////////////////////////////// Timer 0
// Timer 0 (AKA RTCC)Functions: SETUP_COUNTERS() or SETUP_TIMER_0(),
// SET_TIMER0() or SET_RTCC(),
// GET_TIMER0() or GET_RTCC()
// Constants used for SETUP_TIMER_0() are:
#define RTCC_INTERNAL 0
#define RTCC_EXT_L_TO_H 32
#define RTCC_EXT_H_TO_L 48

#define RTCC_DIV_1 8
#define RTCC_DIV_2 0
#define RTCC_DIV_4 1
#define RTCC_DIV_8 2
#define RTCC_DIV_16 3
#define RTCC_DIV_32 4
#define RTCC_DIV_64 5
#define RTCC_DIV_128 6
#define RTCC_DIV_256 7


#define RTCC_8_BIT 0

// Constants used for SETUP_COUNTERS() are the above
// constants for the 1st param and the following for
// the 2nd param:

////////////////////////////////////////////////////////////////// WDT
// Watch Dog Timer Functions: SETUP_WDT() or SETUP_COUNTERS() (see above)
// RESTART_WDT()
// WDT base is 18ms
//

#define WDT_18MS 0x8008
#define WDT_36MS 9
#define WDT_72MS 10
#define WDT_144MS 11
#define WDT_288MS 12
#define WDT_576MS 13
#define WDT_1152MS 14
#define WDT_2304MS 15

////////////////////////////////////////////////////////////////// Timer 1
// Timer 1 Functions: SETUP_TIMER_1, GET_TIMER1, SET_TIMER1
// Constants used for SETUP_TIMER_1() are:
// (or (via |) together constants from each group)
#define T1_DISABLED 0
#define T1_INTERNAL 0x85
#define T1_EXTERNAL 0x87
#define T1_EXTERNAL_SYNC 0x83

#define T1_CLK_OUT 8

#define T1_DIV_BY_1 0
#define T1_DIV_BY_2 0x10
#define T1_DIV_BY_4 0x20
#define T1_DIV_BY_8 0x30

////////////////////////////////////////////////////////////////// Timer 2
// Timer 2 Functions: SETUP_TIMER_2, GET_TIMER2, SET_TIMER2
// Constants used for SETUP_TIMER_2() are:
#define T2_DISABLED 0
#define T2_DIV_BY_1 4
#define T2_DIV_BY_4 5
#define T2_DIV_BY_16 6

////////////////////////////////////////////////////////////////// CCP
// CCP Functions: SETUP_CCPx, SET_PWMx_DUTY
// CCP Variables: CCP_x, CCP_x_LOW, CCP_x_HIGH
// Constants used for SETUP_CCPx() are:
#define CCP_OFF 0
#define CCP_CAPTURE_FE 4
#define CCP_CAPTURE_RE 5
#define CCP_CAPTURE_DIV_4 6
#define CCP_CAPTURE_DIV_16 7
#define CCP_COMPARE_SET_ON_MATCH 8
#define CCP_COMPARE_CLR_ON_MATCH 9
#define CCP_COMPARE_INT 0xA
#define CCP_COMPARE_RESET_TIMER 0xB
#define CCP_PWM 0xC
#define CCP_PWM_PLUS_1 0x1c
#define CCP_PWM_PLUS_2 0x2c
#define CCP_PWM_PLUS_3 0x3c
long CCP_1;
#byte CCP_1 = 0x15
#byte CCP_1_LOW= 0x15
#byte CCP_1_HIGH= 0x16
////////////////////////////////////////////////////////////////// UART
// Constants used in setup_uart() are:
// FALSE - Turn UART off
// TRUE - Turn UART on
#define UART_ADDRESS 2
#define UART_DATA 4
////////////////////////////////////////////////////////////////// COMP
// Comparator Variables: C1OUT, C2OUT
// Constants used in setup_comparator() are:
#define A0_A3_A1_A2 0xfff04
#define A0_A2_A1_A2 0x7ff03
#define NC_NC_A1_A2 0x6ff05
#define NC_NC_NC_NC 0x0ff07
#define A0_VR_A1_VR 0x3ff02
#define A3_VR_A2_VR 0xcff0A
#define A0_A2_A1_A2_OUT_ON_A3_A4 0x7e706
#define A3_A2_A1_A2 0xeff09
#define CP1_INVERT 0x00010
#define CP2_INVERT 0x00020

#bit C1OUT = 0x1f.6
#bit C2OUT = 0x1f.7

////////////////////////////////////////////////////////////////// VREF
// Constants used in setup_vref() are:
//
#define VREF_LOW 0xa0
#define VREF_HIGH 0x80
// Or (with |) the above with a number 0-15
#define VREF_A2 0x40

////////////////////////////////////////////////////////////////// INTERNAL RC
// Constants used in setup_oscillator() are:
#define OSC_48KHZ 0
#define OSC_4MHZ 8

////////////////////////////////////////////////////////////////// INT
// Interrupt Functions: ENABLE_INTERRUPTS(), DISABLE_INTERRUPTS(),
// CLEAR_INTERRUPT(), INTERRUPT_ACTIVE(),
// EXT_INT_EDGE()
//
// Constants used in EXT_INT_EDGE() are:
#define L_TO_H 0x40
#define H_TO_L 0
// Constants used in ENABLE/DISABLE_INTERRUPTS() are:
#define GLOBAL 0x0BC0
#define INT_RTCC 0x0B20
#define INT_RB 0xFF0B08
#define INT_EXT 0x0B10
#define INT_TBE 0x8C10
#define INT_RDA 0x8C20
#define INT_TIMER1 0x8C01
#define INT_TIMER2 0x8C02
#define INT_CCP1 0x8C04
#define INT_COMP 0x8C40
#define INT_TIMER0 0x0B20
#define INT_EEPROM 0x8C80

#list
//////// Standard Header file for the PIC16F628A device ////////////////

Não há esse comando. Não era nem para ter compilado.

Sobre seu código enviar nível lógico alto tanto para B0 e B1, provavelmente é alguma condição no seu código que está permitindo isso.

Tente debugar seu código. Começe do zero.

Utilize somente o comando:

if(!input(PIN_A0)) // SE ENTRADA 0 for 0
{
delay_ms (75);
output_high(PIN_B0); //FRENTE desliga
}

Coloque um LED + resistor de 150 ohms no PINO B0 e no PINO B1. Veja se somente o B0 irá acender...

Vá adicionando linhas de código.

você tem duas condições que envolvem o teste do PINO A0 e o PINO B1:

if(!input(PIN_A0)) // SE ENTRADA 0 for 0
{
delay_ms (75);
output_high(PIN_B0); //FRENTE desliga
}

e

if(input(PIN_A0)==1 && sensorf==0) //ENTRADA 0 for 1 e sensor frente for 0
{
output_high(PIN_B0); //FRENTE liga
output_low(PIN_B1);
}

Veja se não estão incompativeis um com o outro......

Outra coisa, poste seu circuito completo. Pode usar o Proteus para desenhar e simular. Ajuda MUIIITOOOOO.

Não tenho tempo de repassar todo o seu código pois terei que copiá-lo, montar um circuito no Proteus, testar cada botão apertado para encontrar o erro.

Mais uma vez, se está "ligando" dois pinos que não deveriam, provavelmente é erro no algoritimo.

Falou

Link para o comentário
Compartilhar em outros sites

  • Membro VIP

Eu exclui essas 3 linhas do programa:

setup_adc_ports(NO_ANALOGS); // não usaremos nenhum porta analogica

setup_adc(ADC_OFF); // desligamos o conversor AD

setup_psp(PSP_DISABLED); // não utiizamos a porta PSP

Eu liguei o PIC sozinho com os 4 Leds nas saidas B0, B1, B2 e B4. O programa obedece os comandos, o problema é que mesmo depois de cortar o sinal na entrada, o PIC continua mandando o sinal na saída correspondente por uns 5 segundos.

E no comando do freio ao invés de frear somente uma vez, fica freando a cada 1 segundo, como se o IF na programação fosse um while infinito.

Link para o comentário
Compartilhar em outros sites

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

 

GRÁTIS: ebook Redes Wi-Fi – 2ª Edição

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!