Ir ao conteúdo

PIC+Sonar


knightd

Posts recomendados

Postado

Boas pessoal. Tenho de fazer um trabalho em que ligo um sonar (srf08) a uma pic (pic18f2221), através de i2c. Eu tenho noção do que é o i2c, no entanto não sei como fazer em C. Será que alguém me dá algumas dicas de como fazer? O compilador em que tenho que fazer este programa é o xc8,em mplab. Fico muito agradecido se alguém me conseguir explicar como é que tenho de fazer.

  • 2 semanas depois...
Postado

Eu tenho este codigo feito para a ligaçao i2c entre a pic(18f2550), no entanto nao esta a funcionar, será que alguem me poderia ajudar? Ja tenho resistencias de pull-up no sda e scl, ja testei num osciloscopio e nao trasmite nada. Será que me podem ajudar?

#include <xc.h>
#include "stdio.h"
#include "i2c.h"

#pragma config FOSC = HS //HS Oscillator
#pragma config IESO = OFF //Oscillator Switchover mode disabled
#pragma config PWRT = OFF //Power-up Timer disabled
#pragma config BOR = OFF //Brown-out Reset disabled in hardware and software
#pragma config WDT = OFF //WDT disabled (control is placed on the SWDTEN bit)
#pragma config MCLRE = OFF //RE3 input pin enabled; MCLR disabled
#pragma config LVP = OFF //Single-Supply ICSP disabled
#pragma config FCMEN = OFF
#pragma config STVREN = OFF //Stack full/underflow will not cause Reset
#pragma config DEBUG = OFF //Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins

int ir, lightsen, alcance, cont=50, cont1=0, flag;

void interrupt tc_int(void)
{
if (TMR0IE && TMR0IF) {
TMR0=61;
TMR0IF=0;
cont--;
cont1++;
if(cont1==7)
{
cont1=0;
flag=0;
}
if(cont==0)
{
cont=50;
PORTAbits.RA0=~PORTAbits.RA0;
//ir=PORTA&0b00000001; //ir->variavel que guarda o valor existente no pino 0 do porto A
//if(ir==0){ //se emissor estiver desligado
// PORTA=PORTA|0b00000001;} //liga
//else {PORTA=PORTA&0b00000000;} //desliga
}
}

return;
}

void envia_i2c(char end, char reg, char cmd)
{
//StartI2C(); //começa a comunicaçao enviando o start bit e espera ate que a condiçao (enviar startbit) termine
SSPCON2bits.SEN=1;
while(SSPCON2bits.SEN);
//while(!PIR1bits.SSPIF);
//while ((SSPCON2 & 0x1F) | (SSPSTATbits.R));

//WriteI2C(end); //manda o endereço do dispositivo que pretende comunicar (o endereço 0xE0 é o endereço inicial do sonar) e vai transmitir
PIR1bits.SSPIF = 0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)
SSPBUF=end; //carrega no SSPBUF o valor do endereço de destino
while(!PIR1bits.SSPIF); //espera pela interrupçao
PIR1bits.SSPIF = 0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

SSPBUF=reg; //carrega com o registo que pretende
while(!PIR1bits.SSPIF); //espera pela interrupçao
PIR1bits.SSPIF = 0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

SSPBUF=cmd;
while(!PIR1bits.SSPIF); //espera pela interrupçao
PIR1bits.SSPIF = 0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

//StopI2C();
SSPCON2bits.PEN=1;
while(SSPCON2bits.PEN);
while(!PIR1bits.SSPIF);
}

void inicializacoes(void)
{
//configurações dos portos
LATA=0; //limpa as saidas configuradas na latch
ADCON1=0b00001111; //Todos os pinos I/O analogicos, passam a digitais
TRISA=0b11111100; //RA0 e RA1 como saidas e o restantes como entradas

LATB=0x00;
TRISB=0b00000011; //os pinos do sda e scl

//timer0
TMR0=61;
T0CON=0b11010111;

//configuraçoes das interrupçoes
INTCON=0b01100000; //activa as interrupçoes de perifericos e TMR0 por overflow

INTCON2=0b11110000;

//i2c
//OpenI2C(MASTER,SLEW_OFF); //define como master (clock=Fosc/(4*(sspadd+1))) e Slew rate desativado para o modo 100kHz
SSPCON1=0b00101000;
SSPADD=49; //funciona com baud rate (clock=Fosc/(4*(sspadd+1))) clock=100khz, Fosc=20MHz; pois esta em modo master

//definir alcance
envia_i2c(0xE0,0x02,0x74); //manda o endereço 0xE0 (endereço inicial do sonar)
//manda o comando de registo (2->alcance)
//valor do registo alcance 0x74 (que corresponde a 116 decimal) ficando deste modo o alcance total de 5.031m

//definir ganho atraves da funcao envia_i2c
envia_i2c(0xE0,0x01,0x0A); //manda o endereço 0xE0 (endereço inicial do sonar)
//manda o comando de registo (1->ganho)
//valor do ganho (Set Maximum Analogue Gain to 352)


//ativa-se as interrupçoes gerais no fim
GIE=1;

return;
}

void ler_sonar(char end)
{

int alcancelow=0, alcancehigh=0;

flag=1;

//definir medidas do alcance
envia_i2c(0xE0,0x00,0x51); //manda o endereço 0xE0 (endereço inicial do sonar)
//manda o comando de registo (0->Command Register)
//resultados em cm (Ranging Mode - Result in centimeters)

while(flag==1);
flag=1;

//começa a sequencia para poder ler o sonar
//StartI2C(); //começa a comunicaçao enviando o start bit e espera ate que a condiçao (enviar startbit) termine
SSPCON2bits.SEN=1;
while(SSPCON2bits.SEN);
SSPCON2bits.ACKDT=0; //acknowledge (reconhecer) no bit ACKDT
PIR1bits.SSPIF=0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

SSPBUF=end; //endereço do sonar
while(!PIR1bits.SSPIF); //espera pela interrupçao
PIR1bits.SSPIF=0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

SSPBUF=2; //registo de endereço para ler os 8 bits mais significativos
while(!PIR1bits.SSPIF); //espera pela interrupçao
PIR1bits.SSPIF=0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

RestartI2C(); //recomeça a comunicaçao enviando o start bit
PIR1bits.SSPIF=0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

SSPBUF=end+1; //endereço do sonar - com o bit de leitura a ser activado neste ponto
while(!PIR1bits.SSPIF); //espera pela interrupçao
PIR1bits.SSPIF=0; //limpa a flag de interrupçao do Master Synchronous Serial Port (ficando a espera para transmitir/receber)

//while(SSPCON2&0x1f); //espera
//espera
//while(flag==1);
while(flag==1);
flag=1;

SSPCON2bits.RSEN=1; //começa a receber
while(!SSPSTATbits.BF); //espera pelos valores do sensor de luz,ou seja, espera que o buffer da transmissao fique vazio
lightsen=SSPBUF; //Guarda o valor do sensor
AckI2C(); //envia um acknowledge

//while(SSPCON2&0x1f); //espera

SSPCON2bits.RSEN=1; //começa a receber
while(!SSPSTATbits.BF); //espera pelos valores mais altos do alcance,ou seja, espera que o buffer da transmissao fique vazio
alcancehigh=SSPBUF; //Guarda o valor do alcance alto
AckI2C(); //envia um acknowledge

//while(SSPCON2&0x1f); //espera (cont1 ms)
while(flag==1);

SSPCON2bits.RSEN=1; //começa a receber
while(!SSPSTATbits.BF); //espera pelos valores mais baixos do alcance,ou seja, espera que o buffer da transmissao fique vazio
alcancelow=SSPBUF; //Guarda o valor do alcance pequeno
NotAckI2C(); //envia um acknowledge e um not acknowledge para o ultimo byte

//StopI2C(); //termina
SSPCON2bits.PEN=1;
while(SSPCON2bits.PEN);

alcancehigh<<=8;
alcance=alcancehigh+alcancelow;
//alcance=alcancehigh;

}

void main(void)
{
inicializacoes();
while(1)
{
ler_sonar(0xE0); //leva o endereço sobre qual sonar se pretende ler
/*if(alcance>1)
PORTAbits.RA1=1;
else
PORTAbits.RA1=0;*/
}
}

o que pretendo que o codigo faça e de mais ou menos meio em meio segundo mude o estado do led, neste momento funciona, e receber dados do sonar

Postado

Boas pessoal. A parte da comunicaçao esta quase toda a dar, excepto o valor da distancia, mudei o meu codigo para isto, será que alguem me pode ajudar?

#include <xc.h>
#include "stdio.h"
#include "i2c.h"

#pragma config FOSC = HS //HS Oscillator
#pragma config IESO = OFF //Oscillator Switchover mode disabled
#pragma config PWRT = OFF //Power-up Timer disabled
#pragma config BOR = OFF //Brown-out Reset disabled in hardware and software
#pragma config WDT = OFF //WDT disabled (control is placed on the SWDTEN bit)
#pragma config MCLRE = OFF //RE3 input pin enabled; MCLR disabled
#pragma config LVP = OFF //Single-Supply ICSP disabled
#pragma config FCMEN = OFF
#pragma config STVREN = OFF //Stack full/underflow will not cause Reset
#pragma config DEBUG = OFF //Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins

int alcance,cont=50, rangehigh, rangelow, flag, i,j;

void interrupt tc_int(void)
{
if (TMR0IE==1 && TMR0IF==1) {
TMR0=61;
TMR0IF=0;
cont--;
if(cont==0)
{
cont=50;
PORTAbits.RA0=~PORTAbits.RA0; //de 500 em 500ms muda o estado do led
}
}

if(TMR1IF==1){
TMR1IF=0;
flag=1;
}


return;
}

void envia_i2c(char end, char reg, char cmd)
{
StartI2C(); //começa a comunicaçao I2C
//IdleI2C(); //fica em estado de espera enquanto Start Condition Enable bit,Stop Condition Enable bit, Receive Enable bit, Acknowledge Sequence Enable bit of I2C Control register and Transmit Status bit I2C Status register estão limpos (ou seja, a zero).
//O periferico I2C deve estar no estado alto antes da inicializaçao do operaçao i2c, caso nao aconteça na escrita pode gerar-se colisoes.
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)); //corresponde ao idlei2c
PIR1bits.SSPIF = 0; //
WriteI2C(end); //escreve o endereço do sonar, com o bit R/W a zero(0)
//IdleI2C(); //
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)); //
PIR1bits.SSPIF = 0; //
WriteI2C(reg); //escreve o endereço do registo do comando
//IdleI2C(); //
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)); //
PIR1bits.SSPIF = 0; //
WriteI2C(cmd); //escreve o comando que pretende
//IdleI2C(); //
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)); //
PIR1bits.SSPIF = 0; //
StopI2C(); //Termina a comunicaçao I2C
}

void ler_sonar(char end)
{
envia_i2c(0xE0,0x00,0x51); //envio o endereço do sonar, o endereço do comando a efetuar, e o comando(0x51-> medidas em cm)

//tem de esperar um tempo
TMR1=15535; //para um tempo de 65ms(24910), 70ms(21785), 80ms(15535)
flag=0;
TMR1ON=1;
while(flag==0)
{
PORTAbits.RA1=0;
}
TMR1ON=0;

StartI2C(); //começa a comunicaçao I2C
//IdleI2C(); //fica em estado de espera enquanto Start Condition Enable bit,Stop Condition Enable bit, Receive Enable bit, Acknowledge Sequence Enable bit of I2C Control register and Transmit Status bit I2C Status register estão limpos (ou seja, a zero).
//O periferico I2C deve estar no estado alto antes da inicializaçao do operaçao i2c, caso nao aconteça na escrita pode gerar-se colisoes.
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W)); //corresponde ao idlei2c
PIR1bits.SSPIF = 0; //limpa a flag da interrupçao do mssp
WriteI2C(end); //escreve o endereço do sonar para o qual pretende enviar/receber informaçao, com o bit R/W a zero(modo slave, sonar, interpreta como escrita; modo master, pic, transmissao nao esta em progresso)
//IdleI2C();
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W));
PIR1bits.SSPIF = 0;
WriteI2C(0x02); //escreve o endereço a partir do qual se vai querer começar a ler
//IdleI2C();
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W));
PIR1bits.SSPIF = 0;
RestartI2C(); //manda uma sequencia de restart
//IdleI2C();
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W));
PIR1bits.SSPIF = 0;
WriteI2C(end+1); //envia o endereço do sonar, com o bit R/W a um(modo slave, sonar, interpreta como leitura; modo master, pic, transmissao em progresso)
//IdleI2C();
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W));
PIR1bits.SSPIF = 0;
rangehigh=ReadI2C(); //le o valor dos bits mais significativos e guarda-os em rangehigh
AckI2C(); //envia-se um acknowledgement para o sonar, a confirmar.
//internamente no sonar, para ler, e incrementado o registo
//IdleI2C();
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W));
PIR1bits.SSPIF = 0;
rangelow=ReadI2C(); //le o valor dos bts menos significativos e guarda em rangelow
NotAckI2C(); //envia-se um notacknowledgement na ultima informaçao que se pretende receber
//IdleI2C();
while ((SSPCON2 & 0x1F) | (SSPSTATbits.R_W));
PIR1bits.SSPIF = 0;
StopI2C(); //finaliza a comunicaçao

}

void inicializacoes(void)
{
//configurações dos portos
LATA=0; //limpa as saidas configuradas na latch
ADCON1=0b00001111; //Todos os pinos I/O analogicos, passam a digitais
TRISA=0b11111100; //RA0 e RA1 como saidas e o restantes como entradas

LATB=0;
TRISB=0b00000011; //os pinos do sda e scl definidos como entrada(de modo a ser i2c)

//timer0
TMR0=61;
T0CON=0b11010111;

//timer1
TMR1=15535; //para um tempo de 65ms(24910), 70ms(21785), 80ms(15535)
T1CON=0b10110000; //operaçao em 16bits, prescaler de 8, clock interno, timer desligado
TMR1IE=1;
TMR1IP=1;

//configuraçoes das interrupçoes
INTCON=0b01100000; //activa as interrupçoes de perifericos e TMR0 por overflow

INTCON2=0b11110000; //TMR0 com prioridade baixa

//i2c
SSPADD=49; //funciona com baud rate (clock=Fosc/(4*(sspadd+1))) clock=100khz, Fosc=20MHz; pois esta em modo master
OpenI2C(MASTER,SLEW_OFF); //define como master (clock=Fosc/(4*(sspadd+1))) e Slew rate desativado para o modo 100kHz

//definir alcance
envia_i2c(0xE0,0x02,0x74); //manda o endereço 0xE0 (endereço inicial do sonar)
//manda o comando de registo (2->alcance)
//valor do registo alcance 0x74 (que corresponde a 116 decimal) ficando deste modo o alcance total de 5.031m

//definir ganho atraves da funcao envia_i2c
envia_i2c(0xE0,0x01,0x10); //manda o endereço 0xE0 (endereço inicial do sonar)
//manda o comando de registo (1->ganho)
//valor do ganho (Set Maximum Analogue Gain to 352)


//ativa-se as interrupçoes gerais no fim
GIE=1;

return;
}

void main(void)
{
inicializacoes();
while(1)
{
for(i=0;i<=1000;i++)
{ for(j=0;j<=1000;j++);}
ler_sonar(0xE0); //leva o endereço sobre qual sonar se pretende ler
alcance=rangehigh<<8;
alcance=alcance+rangelow;
if(alcance>100)
PORTAbits.RA1=1;
else
PORTAbits.RA1=0;

}
}

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!