I2C EEPROM bitbanging: Escribe bien, pero solo si el primer bit no está establecido

8

Actualmente estoy trabajando en un proyecto I2C EEPROM que usa bit banging para impulsar las líneas SDA y SCL.

Mi función de lectura funciona bien, pero cada vez que escribo un byte con un "1" inicial, siempre leo FF atrás; incluso si el byte ha sido programado con algo más antes. Liderar "0" es perfecto. No es mi rutina de lectura; Como puedo ver en el alcance, devuelve FF.

Estoy buscando sugerencias sobre por qué esto podría ser. ¿Hay algo obvio que pueda pasar por alto y que pueda causar el problema? [No puedo publicar el código - confidencial de la compañía ... :(]

Cada forma de onda que veo cumple exactamente la especificación. Estoy desacoplando la EEPROM. Mis pull ups son 2.2k por lo que dentro de las especificaciones. Estoy cronometrando a unos 500 Hz en este prototipo. El chip está enviando ACK a cada uno de mis bytes para que los reconozca. Pero simplemente no funciona ...

Estoy usando un Microchip 24LC256 .

Algoritmo de escritura simplificado para un 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 lectura simplificado para un 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
    
pregunta Thomas O

5 respuestas

3

Estás leyendo los datos cuando el reloj vuelve a estar bajo. Tendrás que hacer eso entre hacer el reloj alto y hacerlo bajo. Una vez que el reloj está en baja, el esclavo puede cambiar la línea de datos, no mientras esté alta.

Así que la lectura debería ser así:

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
    
respondido por el stevenvh
2

El problema al final resultó ser que, de manera involuntaria, estaba enviando una condición de DETENCIÓN en algunas condiciones debido a una sincronización alterada. Renuncié a usar el alcance y saqué el analizador lógico, y pude solucionar el problema en 15 minutos, ya que resaltaba el STOP que no debería haber estado allí. Elegiré a quién dar la recompensa según la respuesta más útil. Gracias por todas las soluciones.

    
respondido por el Thomas O
1

Parece que podría ser un par de cosas:

  1. ¿Qué más hay en el autobús? ¿Podría haber una contención de bus con otro dispositivo que se está reteniendo o sin inicializar?
  2. ¿Está cambiando correctamente la dirección del pin de E / S? Si está funcionando bien en el caso de salida, podría haber olvidado inadvertidamente cambiar la dirección del pin a la entrada y siempre leerá 0xFF . El pin podría dejarse como una salida conduciendo el autobús mientras usted lo lea.
  3. ¿Tiene pull-ups internos en el pin mismo y / o en las líneas de E / S? Los microcontroladores generalmente ofrecen un rango de resistencia y no un valor fijo. Es posible que desee deshabilitar los pull-ups en el micro y simplemente usar los discretos en el bus, ya que puede obtener una resistencia de pull-up más precisa a partir de componentes discretos.
  4. Polaridad del reloj: ¿está seguro de que está midiendo en el borde o la fase correcta entre el reloj y los datos? Podría estar registrando lo que se ve bien en el alcance, pero si la fase está fuera de línea, todo lo que verá en su EEPROM será 0xFF s (y lo más probable es que devuelva lo mismo ya que probablemente sea una condición / comando no válido).
respondido por el Joel B
1

OK, su alcance demuestra que el primer byte que llega al PIC es malo, por lo que no es la función de lectura del PIC.

¿Verificaste que el tiempo de escritura es correcto en el extremo receptor?

¿Esto falla en los dos modos a continuación?

- Byte mode sequential
- Page mode Sequential

La especificación muestra "El bit más significativo (MSB)‘ b7 'se envía primero " Esto también es coincidente cuando b7 = 1 que todo el byte se lee como FF. Entonces, o bien no se escribe y solo se borra (condición de falla) cuando b7 = 1, o se lee mal como FF independientemente del contenido anterior. Dado que cada escritura es un byte, se borra todo antes de escribir, podría ser una mala escritura o una mala lectura o la sincronización del primer byte es diferente.

Sugerencia: verifique la señal de PTC durante una escritura / lectura para garantizar un funcionamiento normal.

Hay una opción de usar un reloj externo para cronometrar la longitud de un ciclo E / W utilizando PTC. ¿Has intentado usar esto?

tiempo de ciclo tE / W

  • oscilador interno 7ms typ
  • reloj externo 4 ~ 10 ms min ~ max

¿Pasa este criterio?

    
respondido por el user11355
0

Presenté esto como un comentario anterior, pero mi confianza en la respuesta ha estado creciendo silenciosamente en lo profundo de mi mente, así que lo estoy promoviendo a una respuesta.

Tengo el presentimiento de que esto es casi un error de software de bajo nivel relacionado con la firmeza de algunas variables. En su código de cada bit, ¿está extendiendo inadvertidamente la señal con una operación de cambio a la derecha? Si eres el líder, eventualmente te dejará con un 0xFF después de 7 operaciones de turno.

Steven aludió a esto en un comentario, pero ¿has presenciado la santidad de tus operaciones de escritura en un osilloscopio, o solo supones que funcionan basándose en que la mitad de las respuestas son buenas? Si no ha intentado ver la operación de escritura del valor 0xAA, podría ser una buena cosa intentarlo.

Si puede proporcionar el código real de su bucle interno y las declaraciones de variables asociadas, podríamos detectar un error.

    
respondido por el vicatcu

Lea otras preguntas en las etiquetas