I2C EEPROM bit-banging: écrit bien, mais uniquement si le premier bit n'est pas défini

9

Je travaille actuellement sur un projet EEPROM I2C utilisant le bit banging pour piloter les lignes SDA et SCL.

Ma fonction de lecture fonctionne bien mais chaque fois que j'écris un octet avec un "1", je relis toujours FF; même si l'octet a été programmé avec autre chose auparavant. Un "0" en tête est parfait. Ce n'est pas ma routine de lecture; comme je peux le voir sur la portée, il retourne FF.

Je cherche des suggestions sur la raison pour laquelle cela pourrait être. Y a-t-il une évidence que je pourrais manquer qui pourrait causer le problème? [Je ne peux pas poster le code - société confidentielle ... :(]

Chaque forme d'onde que je regarde répond exactement aux spécifications. Je suis en train de découpler l'EEPROM. Mes tractions sont de 2,2k donc conformes aux spécifications. Je pointe à environ 500 Hz dans ce prototype. La puce envoie des ACK à chacun de mes octets pour les reconnaître. Mais ça ne marche pas ...

J'utilise une Microchip 24LC256 .

Algorithme d'écriture simplifié pour un octet:

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

Algorithme de lecture simplifié pour un octet:

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
Thomas O
la source
1
@Justin - Je pense qu'il dit que l'écriture de la valeur 0x7F à n'importe quelle adresse fonctionne, mais l'écriture de 0x80 à n'importe quelle adresse ne fonctionne pas.
Rocketmagnet
1
Ce sont des trucs comme ça qui me font détester I2C.
Rocketmagnet
1
J'ai une intuition folle. Dans votre code pour chaque bit, est-ce que vous étendez par inadvertance une extension de signe avec une opération de décalage à droite? Si vous êtes alors votre leader vous laissera éventuellement un 0xFF après 7 opérations de quart.
vicatcu
3
L'ironie, ici, c'est le code "confidentiel de l'entreprise". C'est précieux pour eux. Tout le monde ici partage du code qui fonctionne. Ce qui distingue le code de cette entreprise des autres, c'est qu'il ne fonctionne pas.
gbarry
2
Il est difficile d'imaginer pourquoi une entreprise a si désespérément besoin de garder confidentiels certains codes de frappe I2C. Il y en a tellement sur Internet.
Rocketmagnet

Réponses:

4

Vous lisez à nouveau les données une fois que l'horloge est basse. Vous devrez faire cela entre faire en sorte que l'horloge soit haute et basse. Une fois que l'horloge est basse, l'esclave est autorisé à changer la ligne de données, pas tant qu'elle est haute.

entrez la description de l'image ici

La lecture devrait donc être comme ceci:

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
stevenvh
la source
C'est un bon point; Je vais arranger ça. Cependant, mes données s'affichent toujours en tant que tout-en-un (FF) sur ma portée, donc ma lecture ne peut pas être le problème ... :(
Thomas O
3

En fin de compte, le problème s'est avéré que j'envoyais par inadvertance une condition STOP dans certaines conditions en raison d'un timing tronqué. J'ai abandonné l'utilisation de l'oscilloscope et sorti l'analyseur logique, et j'ai pu résoudre le problème en 15 minutes car il a mis en évidence l'ARRÊT qui n'aurait pas dû être là. Je choisirai à qui donner la prime en fonction de la réponse la plus utile. Merci pour toutes les solutions.

Thomas O
la source
Heureux que vous ayez résolu le
3
Je vous ai dit que cela serait résolu en regardant la forme d'onde.
Rocketmagnet
@Rocketmagnet J'ai toujours regardé la forme d'onde, mais je ne l'avais jamais remarquée auparavant.
Thomas O
Oui, mais vous ne nous avez pas montré la forme d'onde, malgré que nous vous le demandions à plusieurs reprises. Vous auriez pu résoudre ce problème il y a quelques jours.
Rocketmagnet
@Rocket - Je suis d'accord. J'aimerais avoir une caméra disponible à l'époque. Le Tek DPO que j'utilisais avait un lecteur de disquette mais pas de disquette. J'aurais pu poster une photo si j'aurais pu.
Thomas O
2

OK, votre portée prouve que le 1er octet entrant dans le PIC est mauvais, donc ce n'est pas la fonction de lecture PIC.

Avez-vous vérifié que le délai d'écriture est correct du côté réception?

Est-ce que cela échoue dans les deux modes ci-dessous?

- Byte mode sequential
- Page mode Sequential

La spécification indique que "le bit le plus significatif (MSB) 'b7' est envoyé en premier". Cela coïncide également lorsque b7 = 1 que l'octet entier est lu en FF. Donc, soit il n'est pas écrit et seulement effacé (condition de défaut) lorsque b7 = 1, soit il est mal lu comme FF quel que soit le contenu précédent. Étant donné que chaque écriture est un effacement de large octet avant l'écriture, pourrait-il encore être une mauvaise écriture ou une mauvaise lecture ou le timing du 1er octet est différent.

Suggestion: vérifiez le signal PTC pendant une écriture / lecture pour assurer un fonctionnement normal. entrez la description de l'image ici

Il est possible d'utiliser une horloge externe pour chronométrer la durée d'un cycle E / W à l'aide de PTC. Avez-vous essayé de l'utiliser?

temps de cycle tE / W

  • oscillateur interne 7 ms typ
  • horloge externe 4 ~ 10 ms min ~ max

Répond-elle à ces critères?


la source
1

On dirait que cela pourrait être un couple de choses:

  1. Quoi d'autre dans le bus? Pourrait-il y avoir un conflit de bus avec un autre périphérique qui est en attente de réinitialisation ou non initialisé?
  2. Modifiez-vous correctement la direction de la broche d'E / S? Si cela fonctionne bien dans le cas de sortie, vous pourriez avoir oublié par inadvertance de changer la direction de la broche à l'entrée et lira toujours 0xFF. La broche peut être laissée en sortie en conduisant le bus pendant que vous lisez.
  3. Avez-vous des tractions internes sur la broche elle-même et / ou sur les lignes d'E / S? Les microcontrôleurs donnent généralement une plage de résistance et non une valeur fixe. Vous voudrez peut-être désactiver les tractions sur le micro et simplement utiliser celles qui sont discrètes sur le bus car vous pouvez obtenir une résistance à la traction plus précise des composants discrets.
  4. Polarité d'horloge - Êtes-vous sûr de mesurer sur le bord / la phase droite entre l'horloge / les données? Vous pourriez être en train de chronométrer ce qui vous semble bien sur la portée, mais si la phase est hors ligne, toute votre EEPROM verra est 0xFFs (et retournera probablement la même chose car il s'agit probablement d'une commande / condition non valide).
Joel B
la source
1. Juste l'EEPROM et le MCU. 2. Oui, je le crois, car l'EEPROM est capable de maintenir le SDA / SCL bas. 3. Il y a 2,2 k 5% de tractions sur la carte adjacente à l'EEPROM.
Thomas O
pour # 2, êtes-vous sûr que l'EEPROM est celle qui maintient le bus bas. L'EEPROM a-t-elle des conditions dans la fiche technique où elle renverra tous les 0xFFs? Voir aussi mes modifications ci-dessus.
Joel B
# 4. L'EEPROM "ACK" ing mes demandes et fonctionne avec quelques mots, mais pas tous.
Thomas O
0

J'ai soumis cela en tant que commentaire ci-dessus, mais ma confiance dans la réponse a tranquillement grandi dans les profondeurs de mon esprit, donc je la promeut en réponse.

J'ai un pressentiment fou qu'il s'agit presque certainement d'un bogue logiciel de bas niveau lié à la signature de certaines variables. Dans votre code pour chaque bit, est-ce que vous étendez par inadvertance des signes avec une opération de décalage vers la droite? Si vous êtes alors votre leader vous laissera éventuellement un 0xFF après 7 opérations de quart.

Steven y a fait allusion dans un commentaire, mais avez-vous été témoin du caractère sacré de vos opérations d'écriture sur un osilloscope, ou présumez-vous seulement qu'elles fonctionnent sur la base de la moitié des lectures qui semblent bonnes? Si vous n'avez pas essayé de regarder l'opération d'écriture de la valeur 0xAA, cela peut être une bonne chose à essayer.

Si vous pouvez fournir le code réel de votre boucle interne et les déclarations de variables associées, nous pourrons peut-être détecter un bogue.

vicatcu
la source
Mes écrits sont bons; Je peux voir cela sur la portée. Autre bizarrerie: les adresses avec MSB en tête sont correctes. Seules les données causent des problèmes! Je pense publier bientôt le code.
Thomas O
1
À l'appui de cette réponse: s'il s'agit du code C, remplacez toutes les déclarations 'char' par 'unsigned char' et réessayez.
Wouter van Ooijen