El código se puede escribir para ser portátil entre los microcontroladores. Es una buena idea hacer esto a menos que su aplicación sea muy simple o tenga mucha prisa :)
La idea es separar los procedimientos de nivel superior (el flujo de su programa principal) de la manipulación de hardware de bajo nivel (activar pines, configurar registros, etc.).
Para un ejemplo simple, tome un circuito donde desee controlar un LED. Puede configurar su código teniendo un módulo completamente separado para los LED: (No trabajo con AVR, perdone los errores)
led.c:
// For simplicity, this assumes all LEDs are on Port D.
void ledInit(uint8_t ledPin)
{
DDRD |= (1 << ledPin); // Configure the pin as an output
PORTD &= ~(1 << ledPin); // Set the pin low
}
void ledOn(uint8_t ledPin)
{
PORTD |= (1 << ledPin);
}
void ledOff(uint8_t ledPin)
{
PORTD &= ~(1 << ledPin);
}
Luego, en su código de línea principal, solo accederá al LED a través de estos comandos. Si necesitara más acceso, como un comando de alternancia, lo agregaría al archivo led.c. El código principal ni siquiera es consciente de lo que sucede dentro del módulo LED.
Esto hace que sea mucho más fácil mover el código de la línea principal entre los microcontroladores. Básicamente, solo tendría que volver a escribir el archivo led.c. No tendría que cambiar su código de línea principal en absoluto .
Esta lógica también se puede utilizar para temporizadores, puertos de comunicaciones (SPI, I2C, USART ...), etc.
En un proyecto grande, creo que es mejor tener tres capas de código:
- El código de la línea principal, que organiza todo
- Nivel medio, que proporciona funciones y nombres (# define) al código de la línea principal. Esto se traduce entre la intención del código de línea principal y las funciones de bajo nivel requeridas para hacer que las cosas sucedan, y
- Nivel bajo (controlador), que en realidad da la vuelta a los bits correctos.
En este caso, las funciones de bajo nivel solo se ven en el bloque de nivel medio. El bloque de nivel medio está expuesto al código de la línea principal.
Esto puede parecer demasiado complejo, pero en realidad no requiere mucho más trabajo. El beneficio se produce si tiene que cambiar detalles de implementación más grandes.
Por ejemplo, supongamos que ha diseñado su programa para usar un periférico SPI, pero su nuevo diseño debe usar I2C. Ahora puede cambiar el bloque de código de nivel medio para llamar correctamente a los comandos I2C de bajo nivel en lugar de los comandos SPI de bajo nivel. No tendría que cambiar el código de alto nivel o el de bajo nivel.
Dicho esto, no recomendaría esto mientras sigues aprendiendo lo básico :)