Necesito dos puertos seriales para este proyecto Arduino Atmega328, pero este procesador tiene solo un UART de hardware. El procesador, el diseño del hardware y el entorno de programación ya están configurados y no puedo cambiar el hardware o el procesador en absoluto, por lo que se requiere una solución de software.
Las bibliotecas Arduino incluidas proporcionan una biblioteca SoftwareSerial que he descubierto que es solo semidúplex: durante la rutina de envío, las interrupciones están deshabilitadas, lo que por supuesto significa que la rutina de recepción impulsada por interrupciones está cerrada.
Antes de implementar mi propia biblioteca de dúplex completo, quería saber si otros han encontrado una solución simple para esto, o si hay bibliotecas que la implementen correctamente.
No he usado Arduino, pero he escrito UART suaves y eficientes en varias plataformas. El mejor enfoque en una plataforma determinada dependerá de los tipos de operaciones de manipulación de bits que pueda realizar de manera más eficiente. Sin embargo, ofrecería algunas sugerencias:
... cerca del comienzo de la interrupción (para una sincronización constante) shiftreg >>= 1; si (EN_PORT) shiftreg |= 0x20000000; ... otra lógica de interrupción, entonces... si ((shiftreg & 0x20000007) == 0x20000001) { resultado int = 0; si (shiftreg & 0000000040) resultado |= 1; // Nota: ¡las constantes son OCTAL! si (shiftreg & 0000000400) resultado |= 2; si (shiftreg & 0000004000) resultado |= 4; si (shiftreg & 0000040000) resultado |= 8; si (shiftreg & 0000400000) resultado |= 16; si (shiftreg & 0004000000) resultado |= 32; si (shiftreg & 0040000000) resultado |= 64; si (shiftreg & 0400000000) resultado |= 128; // Haz algo apropiado con el resultado, luego... shiftreg |= 0x3FFFFFFFF; } si no (shiftreg = 1) { ... Haz algo con pausa larga (se detectará exactamente una vez) }
Tenga en cuenta que, si bien el tiempo en el peor de los casos puede ser significativo, el tiempo en el caso normal será bastante rápido. Además, cuando se detecta un byte entrante, uno podría copiarlo en otra palabra de la memoria y hacer el cambio de bits en una interrupción posterior. Dado que la transmisión en serie solo necesitará hacer algo cada tercera interrupción, la manipulación de bits podría realizarse en las interrupciones donde la rutina de transmisión en serie no se ejecuta.
Dices que no puedes cambiar el hardware existente, ¿puedes agregarlo? Si no es necesario que ambas líneas seriales estén activas al mismo tiempo, puede usar un multiplexor o un interruptor analógico en las líneas UART y alternar entre los dos dispositivos que necesitan servicio. Solo tendrá que asegurarse de que cuando cambie el nivel en su pin TX permanezca alto cuando se aleje del UART (para evitar una condición de INICIO falso).
Cuando necesité un segundo UART de hardware en un AVR, usé un dispositivo MAX3100. Tiene una interfaz SPI y es muy fácil de usar. Son bastante caros, pero ahorran mucho trabajo.
¿El cliente le permitirá usar un Arduino Mega que tiene 4 puertos seriales de hardware?
No use SoftSerial, al menos use NewSoftSerial... Creo que es una hazaña realmente desafiante (quizás incluso imposible) lograr una comunicación UART full-duplex multicanal sin dos UART de hardware... con NewSoftSerial, creo que el sacrificio lo que haces es que solo puedes "usar" un canal a la vez. Creo que si se pudiera hacer con Arduino ya se habría hecho.
Vea la discusión aquí sobre el uso de múltiples instancias de NewSoftSerial.
adam davis