Ir ao conteúdo
  • Comunicados

    • Gabriel Torres

      Seja um moderador do Clube do Hardware!   12-02-2016

      Prezados membros do Clube do Hardware, Está aberto o processo de seleção de novos moderadores para diversos setores ou áreas do Clube do Hardware. Os requisitos são:   Pelo menos 500 posts e um ano de cadastro; Boa frequência de participação; Ser respeitoso, cordial e educado com os demais membros; Ter bom nível de português; Ter razoável conhecimento da área em que pretende atuar; Saber trabalhar em equipe (com os moderadores, coordenadores e administradores).   Os interessados deverão enviar uma mensagem privada para o usuário @Equipe Clube do Hardware com o título "Candidato a moderador". A mensagem deverá conter respostas às perguntas abaixo:   Qual o seu nome completo? Qual sua data de nascimento? Qual sua formação/profissão? Já atuou como moderador em algo outro fórum, se sim, qual? De forma sucinta, explique o porquê de querer ser moderador do fórum e conte-nos um pouco sobre você.   OBS: Não se trata de função remunerada. Todos que fazem parte do staff são voluntários.
Entre para seguir isso  
dalmoguedes

[Resolvido] I2C - Dados retornados pelo slave

Recommended Posts

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

Compartilhar este post


Link para o post
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.

Compartilhar este post


Link para o post
Compartilhar em outros sites
  • Autor do tópico
  • 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

    Editado por Bcpetronzio
    Inserir Tags CODE

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
  • Autor do tópico
  • Cara, consegui!

    O problema era o endereço! Foi só eu nao usar mais o 0xA0 e usar por exemplo 0xB0, 0XB2 etc que passou a funcionar. Talvez tenha algum dispositivo com esse endereço ou então nao sei qual é o motivo.

    []´s

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites

    Caso o autor do tópico necessite, o mesmo será reaberto, para isso deverá entrar em contato com a moderação solicitando o desbloqueio.

    Compartilhar este post


    Link para o post
    Compartilhar em outros sites
    Visitante
    Este tópico está impedido de receber novos posts.
    Entre para seguir isso  





    Sobre o Clube do Hardware

    No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas publicações 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

    ×