En mis tiempos de estudiante tuve una tarea parecida, aunque era una tarea para poner en práctica la programación multihilos. Tenía que tomar muestras desde un módulo software productor y luego graficarlos y almacenarlos. Lo que hice fue implementar unas clases de C++ que hacian las tareas. Cada cosa en hilos separados (1 productor, un muestreador un graficador y un almacenador).
De todos el más interesante era el muestreador, se creaba un hilo y este comenzaba a llenar un buffer, cuando el éste se llenaba el hilo se detenía, se registraba en la cola del graficador-almacenador. Además se creaba otro objeto de su mismo tipo que era registrado con el driver de toma de datos, para que nunca estuviese sin un buffer donde poner datos. Cuando el graficador terminaba de vaciar el buffer de un objeto muestreador lo destruia. El productior simulaba algo como tu PIC conectado por el puerto serie.
El objetivo era tener cada módulo trabajando a su ritmo. Lo inetersante es que al hacerlo multihilos, le puedes cambiar las prioridades a los hilos y en la misma aplicación tener cosas que van más ráìdo y cosas que van más lento, eso sin contar que divides los flujos de programas. Es cierto que gestionar este modelo es más complejo porque te hará falta saber utilizar mecanismos de sincronización, aunque con un poco de cuidado se pueden evitar los semáforos y esas cosas. La verdad es que mi trabajo quedó muy bueno, al profesor le gustó mucho sobre todo notar lo confiable que era el trabajo del sistema y la estructura de clases, me gané un excelente esa vez y me ha quedado como una experiencia muy útil. Divide y vencerás, reparte la carga y tendrás aplicaciones confiables, es lo que aprendí de eso.
Te comento que las interfaces de usuario son muy problemáticas porque tienen el inconveniente del usuario interactuando con ellas. Si por ejemplo el usuario decide mover la ventana, tendrás el hilo de ventana bloqueado por el SO hasta que el usuario suelte la ventana en la nueva posición y sea necesario volver a redibujarla. Lo mismo ocurre con los procesos que cambian la ventana, el SO es quién la redibuja, lo que te pone en manos del gestror de ventanas. Lo mejor cuando hay datos que entran por una interfaz como el puerto serie es separar la toma o transmisión de datos de las interfaces gráficas. Además puedes hacer actualizaciones de la ventana en ráfagas, es decir si sabes que tienes un conjunto de puentos que mostrar cada cierto tiempo, puedes decirdir bloquear la ventana y volcar todo el buffer en el gráfico, luego le dices al SO que dibuje la ventana nuevamente (usualmente basta con desbloquear la ventana o el objeto gráfico) y de esa forma disminuyes la acción de refrescamiento.
Saludos
Reinier