(Edit: pour être clair, bon nombre des problèmes suivants ont trait à l'intégrité du signal provoquée par l'utilisation carte à carte des périphériques I2C / SPI, comme le fait remarquer Olin à juste titre.)
À moins de contraintes contraignantes qui vous poussent à réduire le nombre de fils (nous avions un projet avec un connecteur hermétique scellé, chaque contact supplémentaire étant assez coûteux), évitez autant que possible I2C et respectez SPI.
Il est assez facile de traiter avec SPI sur une base matérielle et logicielle. En matériel, il existe deux lignes de données partagées, une entrée maître entrée esclave (MISO ou SOMI) et une entrée maître sortie esclave (MOSI ou SIMO), une horloge partagée générée par le maître et une puce de sélection par périphérique. La ligne CS devient basse, l'horloge se cycle et se décale essentiellement en bits d'entrée et en sortie, jusqu'à la fin de la transaction, point auquel la ligne CS devient haute. Lorsque leur ligne CS est haute, les périphériques esclaves ne communiquent pas: ils ignorent les lignes CLK et MOSI et placent leur broche MISO dans un état haute impédance pour permettre à une autre personne de l'utiliser.
Si vous avez un microcontrôleur utilisant plusieurs périphériques SPI et qu'il possède un périphérique SPI intégré, envoyez la sortie CS du microcontrôleur à un démultiplexeur (par exemple 74HC138) et contrôlez les lignes d'adresse pour sélectionner le périphérique entre les transactions SPI. vous écrivez des mots dans un registre pour les mettre en file d'attente et les relire une fois que la broche CS est élevée.
Les signaux SPI étant tous unidirectionnels, ils peuvent être mis en mémoire tampon, utilisés au-delà d’une barrière d’isolement avec des isolateurs numériques et peuvent être envoyés d’une carte à l’autre à l’aide de pilotes de ligne tels que LVDS. La seule chose qui vous préoccupe est le délai de propagation aller-retour, qui limitera votre fréquence maximale.
I2C est une histoire complètement différente. Bien que cela soit beaucoup plus simple du point de vue du câblage, avec seulement deux fils SCL et SDA, ces deux lignes sont des lignes bidirectionnelles partagées qui utilisent des périphériques à drain ouvert avec une extraction externe. Il existe un protocole pour I2C qui commence par transmettre une adresse de périphérique, de sorte que plusieurs périphériques puissent être utilisés si chacun a sa propre adresse.
Du point de vue matériel, il est très difficile d’utiliser I2C dans des systèmes très bruyants. Pour tamponner ou isoler les lignes I2C, vous devez recourir à des CI exotiques - oui, ils existent, mais ils sont peu nombreux: nous avons utilisé un projet individuel et avons réalisé que vous pouviez utiliser un isolateur, mais vous ne pouviez pas. utiliser deux en série - il a utilisé de petites chutes de tension pour déterminer quel côté était le moteur, et deux chutes de série étaient deux beaucoup.
Les seuils de niveau logique d'I2C dépendent de Vcc. Vous devez donc faire très attention si vous utilisez des appareils 3V / 3,3V et 5V dans le même système.
Tous les signaux utilisant un câble de plus d'un pied ou deux doivent s'inquiéter de la capacité du câble. Une capacité de 100 pf / mètre n'est pas inhabituelle pour un câble multiconducteur. Cela vous oblige à ralentir le bus ou à utiliser des résistances de rappel plus faibles pour pouvoir gérer correctement la capacité supplémentaire et répondre aux exigences de temps de montée.
Supposons donc que vous avez un système que vous pensez avoir bien conçu et que vous pouvez gérer la plupart des problèmes d’intégrité du signal. Le bruit est rare (mais toujours présent). De quoi as-tu à t'inquiéter?
Il y a un tas de conditions d'erreur que vous devez être prêt à gérer:
Le périphérique esclave ne reconnaît pas un octet particulier. Vous devez le détecter, puis arrêter et redémarrer la séquence de communication. (Avec SPI, vous pouvez généralement relire les données que vous envoyez si vous voulez vous assurer qu'elles ont été reçues sans erreur.)
Vous lisez un octet de données d'un périphérique esclave, et le périphérique est "hypnotisé" à cause du bruit sur la ligne d'horloge: vous avez envoyé les 8 horloges requises pour lire cet octet, mais à cause du bruit, le périphérique esclave le pense a reçu 7 horloges et transmet toujours un 0 sur la ligne de données. Si le dispositif avait reçu la 8ème horloge, il aurait relâché la ligne de données à l'état haut afin que le maître puisse élever ou abaisser la ligne de données pour transmettre un bit ACK ou NACK, ou qu'il puisse émettre une condition d'arrêt (P). Mais l'esclave tient toujours la ligne de données basse, attendant en vain une autre horloge. Si un maître n'est pas prêt à essayer des horloges supplémentaires, le bus I2C sera bloqué dans une impasse. Bien que j’ai utilisé plusieurs microcontrôleurs qui gèrent les conditions normales d’ACK / NACK,
Le cas vraiment horrible est lorsqu'un maître écrit des données sur un périphérique esclave et qu'un autre esclave interprète l'adresse de périphérique de manière incorrecte et pense que les données transmises lui sont destinées. Des périphériques I2C (expandeurs d'E / S) ont parfois des registres mal configurés à cause de cela. Il est presque impossible de détecter ce cas, et pour résister au bruit, vous devez définir périodiquement tous les registres, de sorte que si vous rencontrez cette erreur, elle sera au moins corrigée après une courte période. (SPI n'a jamais ce problème - si vous rencontrez un petit problème sur la ligne CS, il ne persistera jamais et les données ne seront pas lues accidentellement par le mauvais périphérique esclave.)
Un grand nombre de ces conditions pourraient être gérées correctement dans le protocole en cas de détection d'erreur (codes CRC), mais peu de périphériques en disposent.
Je constate que je dois créer un logiciel complexe sur mon périphérique maître I2C pour gérer ces conditions. À mon avis, cela ne vaut tout simplement pas la peine, à moins que les contraintes de câblage ne nous obligent à utiliser I2C et non SPI.