Los demás son ejemplos de C++ que no se compilan en C y en eso estoy de acuerdo desde el principio porque todos los añadidos y todos los extras que tiene C++ no compilarán en C.
A efectos prácticos, que es lo que le interesa a Loudness, todos los programas en C se pueden compilar con un compilador de C++ como el de Arduino.
Y el compilador C++ de Arduino es uno de los mejores que existen, es un port de GCC, el compilador estandar de GNU/Linux.
Un saludo.
Pero te desvías del estándar y es porque el compilador lo permite, pero no existe la certeza que con otros compiladores lo puedas hacer.
Lo que hace Arduino es que al compilador le agregan la opción -fpermissive, y como tiene una mezcla de liberías en C y en C++ usa tanto avr-gcc como avr-g++ al compilar las fuentes.
Es decir, todo lo que tenga terminación .cpp lo va a compilar a código objeto (.o) con avr-g++ y todos las fuentes que terminen con .c lo va a compilar a código objeto (.o) con avr-gcc y al finalizar los va a enlazar todos con avr-gcc.
Entonces, realmente no puedes decir que estás aprendiendo C y tampoco C++, estás aprendiendo un tipo de Frankenstein, porque si fuera completamente C++, no tendrías que hacer
pinMode(13,OUTPUT) y digitalWrite(13,HIGH)
Tendrias por ejemplo que declarar
DigitalOut LED(13)
Entonces LED pasaría a ser un objeto de la clase DigitalOut. Para después usarlo de la siguiente manera
LED = 0
LED = 1
Sobrecargando el operador =
o
LED.write(0)
y
LED.set()
LED.reset()
LED.toggle()
Entonces, que es lo que realmente estás aprendiendo. C con algunos conceptos que le piden prestado a C++, porque apenas estás tocando la superficie de lo que es C++.
¿Podrían haber alcanzado el mismo objetivo si hubieran usado sólo C?
Claro que sí.
¿Lo podían haber conseguido usando únicamente C++?
Claro que sí. Pero veamos los horrores de haber creado las funciones pinMode y digitalWrite para después compararlo con una seudo implementación en C++
pinMode
void pinMode(uint8_t pin, uint8_t mode)
{
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg, *out;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
out = portOutputRegister(port);
if (mode == INPUT) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out &= ~bit;
SREG = oldSREG;
} else if (mode == INPUT_PULLUP) {
uint8_t oldSREG = SREG;
cli();
*reg &= ~bit;
*out |= bit;
SREG = oldSREG;
} else {
uint8_t oldSREG = SREG;
cli();
*reg |= bit;
SREG = oldSREG;
}
}
digitalWrite
void digitalWrite(uint8_t pin, uint8_t val)
{
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
// If the pin that support PWM output, we need to turn it off
// before doing a digital write.
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
}
Se viola el principio de no repetirse así mismo
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *reg, *out;
if (port == NOT_A_PIN) return;
// JWS: can I let the optimizer do this?
reg = portModeRegister(port);
out = portOutputRegister(port);
-------------------------------------------------
uint8_t timer = digitalPinToTimer(pin);
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
volatile uint8_t *out;
if (port == NOT_A_PIN) return;
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
Son cosas que sólo se tienen que verificar cuando se declara el pin como salida (en el constructor), por lo tanto hay configuraciones que pueden quedar alamacenadas en variables protegidas dentro de una clase de nombre DigitalOut
Así, la implementación de un supuesto write incluiría únicamente las siguientes lineas
uint8_t oldSREG = SREG;
cli();
if (val == LOW) {
*out &= ~bit;
} else {
*out |= bit;
}
SREG = oldSREG;
Hay mucha diferencia en el rendimiento, ya que no tienes que estar haciendo
uint8_t bit = digitalPinToBitMask(pin);
uint8_t port = digitalPinToPort(pin);
...
if (port == NOT_A_PIN) return;
if (timer != NOT_ON_TIMER) turnOffPWM(timer);
out = portOutputRegister(port);
Cada vez que quieres leer o escribir en el pin, además de propiciar a que el compilador optimice mejor la parte de la escritura en el pin por medio de las funciones, sbi y cbi.
Así por ejemplo un LED.set() el compilador lo podría traducir por un
Y un LED.reset()
Esto es porqué, el avr-gcc, es demasiado inteligente para saber que
PORTC |= 0B10000000;
PORTC |= 1<7;
es el equivalente a querer un sbi 0x08, 7
PORTC &= 0B01111111;
PORTC &= ~(1<7);
es el equivalente a querer un cbi 0x08, 7
Hola ., y perdonen si "meto la cuhara donde no debo"
Yo uso avr ., desde que empece con los micros ., ASM intente aprenderlo ., pero "no doy pie con bola" ., el consultante pregunta si se puede pasar de lenguaje C++ a ASM ., para grabar un arduino
Si bien el compilador acepta librerias con extencion .C (las redefiniciones para que funcione en C++ o .CPP tiene que estar en una libreria .H) ., y tambien acepta librerias .S (ASM)
Pero aca no es el problema del lenguaje ., sino si el arduino acepta que sea de otra manera (y es lo que no seme entendio)
Si yo quisiera grabar una compilacion ( C o ASM) ., en un arduino ., no me deja marca error
Y es a eso alo que me refiero ., cualquiera de las compilaciones anteriores ya tiene el "BOOTLADER" incomporado ., y el arduino lo agrega al momento de grabarlo
Si alguno piensa que se puede grabar con otro grbador por los terminales ISP ., veran que no los deja
La proteccion logica delos FUSEBIT ., (que se graban aparte en los ATMEGA., no es igual que los PIC)
La unica manera de solucionar esto es acceder desde el compilador en la plataforma arduino y cambiarlo desde alii (fusebit)
Entonces si podemos grabar deslos terminales ISP como si fuera cualquier micro
Yo creo que la confucion se da por el tema de los lenguajes ., pero aparte de eso ., esta la limitacion que impone el propio arduino par su programacion
Si el consultante quiere compilar en ASM ., puede hacerlo ., pero sobre un micro "virgen" o bien borrar el arduino y dejarlo con la configuracion igual a uno virgen
De otra manera ., dudo que pueda hacerlo
De hecho con avrdude puedes subir cualquier programa al arduino usando el bootloader de arduino, por lo que no lo tienes que borrar el micro antes.