I2C EEPROM-banging: Escreve bem, mas apenas se o primeiro bit não estiver definido


9

Atualmente, estou trabalhando em um projeto I2C EEPROM, usando bit-banging para conduzir as linhas SDA e SCL.

Minha função de leitura funciona bem, mas sempre que escrevo qualquer byte com um "1" inicial, sempre leio FF de volta; mesmo que o byte tenha sido programado com outra coisa antes. O "0" inicial é perfeito. Não é minha rotina de leitura; como posso ver no escopo, ele retorna FF.

Estou procurando sugestões sobre por que isso pode ser. Existe algum óbvio que eu possa perder que possa causar o problema? [Não consigo postar o código - empresa confidencial ... :(]

Cada forma de onda que eu olho atende exatamente às especificações. Estou dissociando a EEPROM. Meus pull ups são 2.2k, portanto, dentro das especificações. Estou com clock de cerca de 500 Hz neste protótipo. O chip está enviando ACKs para cada um dos meus bytes para reconhecê-los. Mas isso simplesmente não funciona ...

Estou usando um Microchip 24LC256 .

Algoritmo de escrita simplificado para um byte:

wait
SDA low
SCL low
wait
for each bit
    if bit is set:   SDA high
    if bit is unset: SDA low
    wait
    SCL high
    wait
    wait
    SCL low
    wait
wait
SDA high 
SCL high
wait
wait
check ACK status
SDA low
SCL low
wait
return ACK status

Algoritmo de leitura simplificado para um byte:

wait
SCL low
SDA high
for each bit (8 bits)
    SCL high
    wait
    wait
    SCL low
    wait
    check and store received bit
    wait
do a NACK or ACK depending on if it is the last byte

11
@ Justin - Eu acho que ele está dizendo que escrever o valor 0x7F em qualquer endereço funciona, mas escrever 0x80 em qualquer endereço não funciona.
Rocketmagnet

11
São coisas assim que me fazem odiar o I2C.
Rocketmagnet

11
Eu tenho um palpite maluco. No seu código para cada bit, você inadvertidamente estende o sinal com uma operação shift right? Se você é o líder, o deixará com um 0xFF após 7 operações de turno.
vicatcu 3/08/2012

3
A ironia, aqui, é o código "confidencial da empresa". É valioso para eles. Todo mundo aqui compartilha código que funciona. O que diferencia o código dessa empresa dos outros é que ele não funciona.
gbarry

2
É difícil imaginar por que uma empresa precisa desesperadamente manter em sigilo algum código de troca de bits I2C. Existe muito disso na internet.
Rocketmagnet

Respostas:


4

Você está lendo os dados depois que o relógio está baixo novamente. Você terá que fazer isso entre aumentar o relógio e diminuí-lo. Depois que o relógio está baixo, o escravo pode alterar a linha de dados, não enquanto estiver alto.

insira a descrição da imagem aqui

Portanto, a leitura deve ser assim:

wait
SCL low
SDA high
for each bit (8 bits)
    SCL high                      <--------
    wait
    check and store received bit  <--------
    wait
    SCL low                       <--------
    wait
    wait
do a NACK or ACK depending on if it is the last byte

Este é um bom ponto; Eu vou consertar isso. No entanto, meus dados ainda são mostrados como todos (FF) no meu escopo, de modo que minha leitura não pode ser o problema ... :(
Thomas O

3

O problema no final acabou sendo que eu estava inadvertidamente enviando uma condição de STOP sob algumas condições devido a um tempo mutilado. Desisti de usar o escopo e saí do analisador lógico, e consegui resolver o problema em 15 minutos, pois destacava a PARADA que não deveria estar lá. Vou escolher a quem dar a recompensa com base na resposta mais útil. Obrigado por todas as soluções.


Que bom que você resolvê-lo por "verificar o tempo de gravação"

3
Eu lhe disse que isso seria resolvido observando a forma de onda.
Rocketmagnet

@Rocketmagnet Eu sempre estive olhando a forma de onda, mas nunca tinha notado isso antes.
Thomas O

Sim, mas você não nos mostrou a forma de onda, apesar de pedirmos repetidamente. Você poderia ter esse problema resolvido dias atrás.
Rocketmagnet

@Rocket - eu concordo. Eu gostaria de ter uma câmera disponível no momento. O Tek DPO que eu estava usando tinha uma unidade de disquete, mas não uma disquete. Eu teria postado uma foto, se eu pudesse.
Thomas O

2

OK, seu escopo prova que o primeiro byte que chega ao PIC é ruim, portanto não é a função de leitura do PIC.

Você verificou que o tempo de gravação está bom no final do recebimento?

Isso falha nos dois modos abaixo?

- Byte mode sequential
- Page mode Sequential

A especificação mostra "O bit mais significativo (MSB) 'b7' é enviado primeiro" Isso também é coincidente quando b7 = 1 que todo o byte é lido como FF. Portanto, ele não é gravado e apenas é apagado (condição de falha) quando b7 = 1, ou lê incorretamente como FF, independentemente do conteúdo anterior. Como toda gravação é apagada em bytes antes da gravação, ainda pode ser uma gravação ruim ou uma leitura ruim ou o tempo do 1º byte é diferente.

Sugestão: Verifique o sinal PTC durante uma gravação / leitura para garantir a operação normal. insira a descrição da imagem aqui

Existe a opção de usar um relógio externo para cronometrar a duração de um ciclo E / W usando PTC. Você já tentou usar isso?

tempo de ciclo tE / W

  • oscilador interno 7ms typ
  • relógio externo 4 ~ 10 ms min ~ max

Passa neste critério?


1

Parece que pode haver algumas coisas:

  1. O que mais há no ônibus? Poderia haver uma contenção de barramento com outro dispositivo que está sendo mantido em redefinição ou não inicializado?
  2. Você está mudando corretamente a direção do pino de E / S? Se estiver funcionando bem no caso de saída, você pode ter esquecido inadvertidamente de mudar a direção do pino para entrada e sempre lerá 0xFF. O pino pode ser deixado como uma saída dirigindo o ônibus enquanto você o lê.
  3. Você possui puxadores internos no próprio pino e / ou nas linhas de E / S? Os microcontroladores geralmente fornecem uma faixa de resistência e não um valor fixo. Convém desativar as flexões no micro e usar apenas as discretas no barramento, para obter uma resistência à tração mais precisa de componentes discretos.
  4. Polaridade do relógio - Tem certeza de que está medindo na borda / fase direita entre o relógio / dados? Você pode estar criando o que parece ótimo para você no escopo, mas se a fase estiver fora de linha, toda a sua EEPROM verá é 0xFFs (e provavelmente retornará o mesmo, provavelmente uma condição / comando inválido).

1. Apenas a EEPROM e o MCU. 2. Sim, acredito que sim, pois a EEPROM é capaz de manter o SDA / SCL baixo. 3. Existem 2,2k 5% de pull ups na placa adjacente à EEPROM.
Thomas O

para o número 2, você tem certeza de que é a EEPROM que mantém o barramento baixo. A EEPROM possui alguma condição na folha de dados em que retornará todos os 0xFFs? Veja minhas edições acima também.
Joel B

# 4 A EEPROM está "aceitando" meus pedidos e funciona com algumas palavras, mas não com todas.
Thomas O

0

Enviei isso como um comentário acima, mas minha confiança na resposta tem crescido silenciosamente nos recônditos profundos da minha mente, por isso estou promovendo isso para uma resposta.

Eu tenho um palpite maluco de que este é quase certamente um bug de software de baixo nível relacionado à assinatura de algumas variáveis. No seu código para cada bit, você inadvertidamente estende o sinal com uma operação shift right? Se você é o líder, o deixará com um 0xFF após 7 operações de turno.

Steven fez alusão a isso em um comentário, mas você testemunhou a santidade de suas operações de gravação em um osciloscópio ou apenas presume que elas funcionam com base em metade das costas de leitura com boa aparência? Se você ainda não tentou examinar a operação de gravação do valor 0xAA, pode ser uma boa coisa para tentar.

Se você puder fornecer o código real do seu loop interno e as declarações de variáveis ​​associadas, poderemos detectar um bug.


Minhas escritas são boas; Eu posso ver isso no escopo. Outra esquisitice: os endereços com os principais MSB estão bem. Somente dados causam problemas! Penso em publicar o código em breve.
Thomas O

11
Para apoiar esta resposta: se esse for o código C, altere todas as declarações 'char' para 'unsigned char' e tente novamente.
Wouter van Ooijen
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.