×
Ir ao conteúdo
  • Cadastre-se

I2C - Dados retornados pelo slave


dalmoguedes

Posts recomendados

Ae pessoal,

Estou utilizando o PIC 16f877A e tentando implementar o I2C. Estou até utilizando duas plaquinhas didaticas Mclab2.

O que está acontecendo agora é que o dado que recebo de volta não é bem o que eu esperava (ou não é o que eu queria). O Mestre lê o valor do potenciômetro e esse valor eu envio para o Escravo e mostro no LCD do Mestre e do Escravo. Tendo esse valor guardado em uma variável global, a partir do mestre eu tento obter esse valor novamente, só que o escravo me devolve um outro valor. Mas não é um valor aleatório, esse valor esta relacionado de alguma forma com o valor que esta armazenado na variável global dele.

Por exemplo

Valor esperado Valor obtido

0x6a 0x62

0x39 0x11

0x00 0x00

0xff 0x55

Alguem já passou por algo parecido? Se acharem que o codigo ajudaria eu coloco ele aqui.

Desde já agradeço.

Atenciosamente,

Dalmo

Link para o comentário
Compartilhar em outros sites

Olha só voce deve estar utilizando o programa exemplo da i2C usando o livro conectando o PIC certo?

(bom ele não funciona muito bem),

agora vamos ao teu problema, perguntinha básica, antes de ler o slave, voce esta colocando a posição correta do endereço onde esta armazenado o valor lido pelo potenciometro?

Está seguindo o padrão de leitura:

START - Byte de Comando - A2 - A1 - A0 -W /2byte/ endereço high - ACK /3byte / endereço low - NACK /4 byte/ Byte de Comando A2 A1 A0 R / 5 byte / ai sim os dados que voce escreveu!/

abs.

Link para o comentário
Compartilhar em outros sites

Oi Felipe! Obrigado pela resposta.

Vou detalhar tentar detalhar melhor. Eu estou usando o compilador CCS e sendo assim estou utilizando a própria biblioteca que ele possui para utilizar o i2c.

Quando eu mando um dado do mestre para o escravo, esse dado sempre chega corretamente (vejo isso no próprio lcd do escravo). Esse valor então fica armazenado em uma variável global do escravo.

O mestre então solicita um dado e o escravo devolve o valor dessa variável. Porém não está vindo o valor correto. Eu até já cheguei a ver o SSPBUF do escravo e o valor já está errado lá. Por exemplo, eu dou um i2c_write(ultimo_dado) e quando examino os bits o valor já está diferente. Acontece aquilo, sempre que mando escrever, por exemplo, 0xFF ele escreve 0x55.

Vou colocar o código do mestre e do escravo

***********************Mestre***********************

#ifndef CONFIG_PIC
#define CONFIG_PIC 1
#include <16F877A.h>
#include <stdio.h>
#include <stdlib.h>
#use delay(clock=4000000)
#fuses XT, NOWDT, NOPUT, NOBROWNOUT, NOLVP, NODEBUG
#zero_RAM
#use I2C (master, sda = PIN_C4, scl = PIN_C3, force_hw)
#endif
#include "lcd.c"

void lcd_Atualiza(byte dado)
{
char buff[10];
int i=0;
sprintf(buff,"%x",dado);
for(i=0; buff[i] != '\0'; i++) lcd_escreve(buff[i]);
}

void main()
{
byte valorPot=0,dado;
byte ack;

delay_ms(200);

setup_adc_ports(AN0_AN1_AN2_AN3_AN4);
setup_adc(ADC_CLOCK_INTERNAL);
setup_vref(FALSE);
set_tris_a(0b11111111);
set_tris_b(0xFF);
set_tris_c(0xFF);
set_tris_d(0x00);
set_tris_e(0xFF);

lcd_ini();
delay_ms(20);
lcd_pos_xy(1,1);
lcd_escreve("TX:");
lcd_pos_xy(1,2);
lcd_escreve("RX:");
delay_ms(20);

while(true)
{
set_adc_channel(1);
delay_us(30);
valorPot = read_adc();
//adequando limites

if(!input(pin_b0)){ //só envia
i2c_start();
ack=i2c_write(0xA0);
ack = i2c_write(valorPot);
i2c_stop();
lcd_pos_xy(5,1);
lcd_Atualiza(valorPot);
delay_ms(1000);
}

if(!input(pin_b1)){ //só recebe
i2c_start();
i2c_write(0xA1);
delay_ms(30);
dado = i2c_read(0);
i2c_stop();
lcd_pos_xy(5,2);
lcd_Atualiza(dado);
delay_ms(1000);
}

if(!input(pin_b3)){ //apaga os valores do lcd
lcd_escreve('\f');
lcd_pos_xy(1,1);
lcd_escreve("TX:");
lcd_pos_xy(1,2);
lcd_escreve("RX:");
delay_ms(1000);
}
}
}

*****************************************************

***************************Escravo********************

#ifndef CONFIG_PIC
#define CONFIG_PIC 1
#include <16f877A.h>
#use delay(clock=4000000)
#fuses HS,NOWDT,PUT,NOBROWNOUT,NOLVP
#use I2C (slave, address = 0xA0 ,sda = PIN_C4, scl = PIN_C3, force_hw)
#zero_RAM
#BIT SSPSTAT_RW = 0x94.2
#BIT SSPSTAT_DA = 0x94.5
#endif
#include "lcd.c"
#include <stdio.h>
#include <stdlib.h>

byte ultimo_dado=0xFF;
int totalInterrupcoes=0;

void lcd_Atualiza()
{
char buff[10];
int i=0;

sprintf(buff,"%x", ultimo_dado);
lcd_pos_xy(1,1);
for(i=0; buff[i] != '\0'; i++) lcd_escreve(buff[i]);

sprintf(buff,"%d",totalInterrupcoes);
lcd_pos_xy(1,2);
for(i=0; buff[i] != '\0'; i++) lcd_escreve(buff[i]);
}

#INT_SSP
void sspinterupt()
{
byte dado;
boolean ack;

totalInterrupcoes++;
if(SSPSTAT_RW == 1){
ack=i2c_write(ultimo_dado);
i2c_stop();
}
else{
if(SSPSTAT_DA == 1)
{
ultimo_dado=i2c_read();
}
else dado=i2c_read();
}
}

void main()
{
delay_ms(200); // power up delay
setup_adc_ports (A_ANALOG);
setup_adc(ADC_CLOCK_INTERNAL);
setup_timer_2(T2_DIV_BY_4,248,1);
setup_ccp1(ccp_pwm);
set_tris_d(0x00);

delay_ms(200);
lcd_ini();
delay_ms(20);

enable_interrupts(INT_SSP);
enable_interrupts(GLOBAL);

while(1){
lcd_Atualiza();
if(!input(pin_b0)){
ultimo_dado=0x69;
delay_ms(1000);
}

}
}

*************************************************

*************************************************

Obrigado,

Dalmo

Link para o comentário
Compartilhar em outros sites

Visitante
Este tópico está impedido de receber novos posts.

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...

Curso de Hacker Ético

LANÇAMENTO!

CLIQUE AQUI E CONFIRA!

* Este curso não é ministrado pela equipe do Clube do Hardware.