Follow along with the video below to see how to install our site as a web app on your home screen.
Nota: This feature currently requires accessing the site using the built-in Safari browser.
////////////////////////////////////////////////////////////////////////////////
// //
// ROBOT //
// //
// Robot avanza sin chocar con obstáculos y reacciona frente a presencia //
// humana y fuentes de calor //
// //
// (c) RobotyPic 2010 //
// //
////////////////////////////////////////////////////////////////////////////////
#include <16F876A.h>
#fuses NOWDT, XT, NOPROTECT
#use delay(clock=4000000) //Frecuencia del cristal oscilador 4MHz
#use i2c(master, SCL=PIN_C3, SDA=PIN_C4) //Configuración comunicación I2C
#byte PIR1=0x0C
#byte trisa=0x85
#byte porta=0x05
#byte trisb=0x86
#byte portb=0x06
#byte trisc=0x87
#byte portc=0x07
#define BIT_TEST_ON output_high(PIN_C0)
#define BIT_TEST_OFF output_low(PIN_C0)
#define AVANCE output_high(PIN_B1),output_high(PIN_B3),output_low(PIN_B2),output_low(PIN_B4)
#define RETROCESO output_low(PIN_B1),output_low(PIN_B3),output_high(PIN_B2),output_high(PIN_B4)
#define PARO output_low(PIN_B1),output_low(PIN_B3),output_low(PIN_B2),output_low(PIN_B4)
#define GIRO_DERECHA output_high(PIN_B1),output_low(PIN_B3),output_low(PIN_B2),output_high(PIN_B4)
#define GIRO_IZQUIERDA output_low(PIN_B1),output_high(PIN_B3),output_high(PIN_B2),output_low(PIN_B4)
#define BUMPER_DER bit_test(porta,4)
#define BUMPER_IZQ bit_test(porta,5)
#bit ojo_derecho = PORTB.7 //Bit 7 puerto B ojo derecho
#bit ojo_izquierdo = PORTB.6 //Bit 6 puerto B ojo izquierdo
/********************** Prototipos de las funciones ***************************/
void main (void); //función principal
void pulso_test (void); //da pulso y calcula distancia al obstáculo
void ccp2_int (void); //mide pulso de eco ultrasonidos
void navegacion (void); //avance y detección obstáculos por ultrasonidos
void bumper (void); //avance y detección obstáculos por bumpers
void servo_tpa81 (void); //establece posiciones de servos de los TPA81
void funcion_TPA81(void); //reacción frente a estímulos de los TPA81
void lectura_tpa81(void); //lectura valores tª de los TPA81
void movimiento_TPA81(void); //Avance o retroceso segun distancia al foco
/******************** Variables para lectura obstáculo ************************/
int1 nuevopulso=0; //Entra otro pulso de lectura
int16 TFB=0,TFS=0,TF=0; //Tiempo flancos
float AP=0.0; //Valor del pulso del obstáculo en microsegundos
int16 distancia=0; //Valor distancia al obstáculo
int16 distancia_derecha=0; //Valor distancia al obstáculo de la derecha
int16 distancia_izquierda=0; //Valor distancia al obstáculo de la izquierda
int1 cambio=0; //Control flanco subida o bajada del impulso leido
/********* Variables para lectura tª y control servos de los TPA81 ************/
int TPA81_h_ID = 0xD0; //Dirección I2C de acceso al TPA81
int TPA81_v_ID = 0xD2; //Dirección I2C de acceso al TPA81 vertical
int b[10]; //Buffer para datos lectura TPA81
int servo_h; //Posición del servo horizontal
int servo_v; //Posición del servo vertical
int i; //Posiciones para Buffer de datos temperatura
int media_a; //El valor medio de b[2] b[3] y b[4]
int media_b; //El valor medio de b[7] b[8] y b[9]
int condicion; //Condición para girar sensor térmico
short int flag_calor_h=0; //Con 1 se ha detectado fuente de calor
short int flag_calor_v=0; //Con 1 se ha detectado fuente de calor
short int flag_presencia_h=0; //Con 1 se ha detectado presencia
short int flag_presencia_v=0; //Con 1 se ha detectado presencia
int flag_h=0;
int flag_v=0;
int repeticiones; //Número de repeticiones de función
/******************************************************************************/
/********************* FUNCIÓN CONTROL DE LOS SERVOS **************************/
/*********** Control de las posiciones de los servos con tpa81 ****************/
void servo_tpa81 ( byte slaveID, byte servo_pos ) {
i2c_start(); //Comienzo de la comunicación I2C ...
i2c_write(slaveID); //...con la dirección del TPA81...
i2c_write(0); //...apuntando a la posición 0 del registro del TPA81
i2c_write(servo_pos&0x1F); //escribe posición del servo
i2c_stop (); //Finalización de la transmisión
}
/******************************************************************************/
/******************* FUNCIÓN DE LECTURA DEL SENSOR TPA81 **********************/
/************ Carga valores de temperatura leídos en el buffer b[] ************/
void lectura_tpa81( byte slaveID ) {
for ( i=0; i<10; i++) { //Contador de posiciones del buffer b[]
i2c_start(); //Comienzo de la comunicación I2C ...
i2c_write(slaveID); //...con la dirección del TPA81...
i2c_write(i); //...apuntando a la dirección (i) del registro
i2c_start(); //Reinicio
i2c_write(slaveID+1); //Cambio a función de lectura
b[i] = i2c_read(0); //Carga buffer b[] con datos leídos del TPA81
i2c_stop (); //Finalización de la transmisión
delay_ms(10);
}
}
/******************************************************************************/
/*********************** FUNCIÓN LECTURA DISTANCIA ****************************/
/** Da pulso test y dato obtenido por interrupción ccp2_int lo traduce a cms.**/
void pulso_test(){
enable_interrupts(INT_CCP2); //Habilitación interrupción para medida de pulso eco
BIT_TEST_ON; //salida de pulso test durante 10us por Bit 0 puerto C
delay_us(10);
BIT_TEST_OFF;
while(nuevopulso==0) //Espera a finalizar pulso eco (interrupción ccp2_int)
{}
if(nuevopulso==1){ //Finalizado el pulso eco se calcula su valor.
TF=(TFB-TFS); //Valor entre pulso de subida y bajada.
AP=TF*1.0; //Valor pulso leido en us(obstáculo) de 100u a 25ms
AP = AP/58; //Distancia del obstáculo en cm
distancia =(int16)AP; //paso de flotante a entero largo
nuevopulso=0; //Listo para recibir nuevo pulso
}
disable_interrupts(INT_CCP2);
}
/******************************************************************************/
/************************ FUNCIÓN RESPUESTA SEGÚN TPA81 ***********************/
/************ Reacciona frente a los estímulos del sensor TPA81 ***************/
void funcion_TPA81() {
delay_ms(10);
lectura_tpa81( TPA81_h_ID ); //Lectura valores temperatura horizontales
condicion = ((b[1]+b[5]+b[6])/3);
//obtine la media de entre b[2], b[3], b[4] y Tª ambiente
media_a=(b[1]+b[2]+b[3]+b[4])/4;
//obtiene la media de entre b[7], b[8], b[9] y Tª ambiente
media_b=((b[1]+b[7]+b[8]+b[9])/4);
//Comprueba si debe girar a la izquierda
if (media_a > condicion){ //Si temp. a izquierda es mayor que central...
if (media_a > media_b){ //...y además es mayor que la derecha...
servo_h=servo_h+1; //... entonces gira el servo una posición
if (servo_h>=30) { //Si servo llega al final de su giro...
servo_h=16; //...lo deja en 0º ...
servo_tpa81 ( TPA81_h_ID, servo_h );
GIRO_IZQUIERDA; //... y gira el cuerpo a la izquierda
delay_ms(800);
PARO;
}
else servo_tpa81 ( TPA81_h_ID, servo_h ); //Sino sólo gira el servo
}
}
else {
flag_h=flag_h+1;
delay_ms(5);
}
//Comprueba si debe girar a la derecha
if (media_b > condicion){ //Si temp. a derecha es mayor que central...
if (media_b > media_a){
servo_h=servo_h-1; //... entonces gira el servo una posición
if (servo_h<=1){ //Si servo llega al final de su giro...
servo_h=16; //...lo deja en 0º ...
servo_tpa81 (TPA81_h_ID, servo_h);
GIRO_DERECHA; //... y gira el cuerpo a la derecha
delay_ms(800);
PARO;
}
else servo_tpa81 ( TPA81_h_ID, servo_h ); //Sino sólo gira el servo
}
}
else {
flag_h=flag_h+1;
delay_ms(5);
}
//Comprueba si algun pixel horizontal mide temperatura > 28ºC (presencia)
flag_presencia_h=0; //Reinicia el flag deteccion_h
for (i=1; i<10; i++){
if (b[i]>28) flag_presencia_h=1;
}
if (condicion >= (media_b&&media_a)) flag_calor_h=1; //Flag calor_h=1 cuando detecta foco en el pixel central
else flag_calor_h=0;
lectura_tpa81( TPA81_v_ID ); //Lectura valores temperatura vertical
condicion = ((b[1]+b[6])/2);
//obtine la media de entre b[2], b[3], b[4] y Tª ambiente
media_a=(b[1]+b[2]+b[3]+b[4]+b[5])/5;
//obtiene la media de entre b[7], b[8], b[9] y Tª ambiente
media_b=((b[1]+b[7]+b[8]+b[9])/4);
//Comprueba si debe subir una posición
if (media_a > condicion){ //Si temp. a izquierda es mayor que central...
if (media_a > media_b){ //...y además es mayor que la derecha...
servo_v=servo_v-1; //... entonces gira el servo una posición
if (servo_v<=5) servo_v=5; //Si servo llega al final de su giro lo deja en misma posición
servo_tpa81 ( TPA81_v_ID, servo_v );
}
}
else {
flag_h=flag_v+1;
delay_ms(5);
}
//Comprueba si la cabeza debe bajar una posición
if (media_b > condicion){ //Si temp. a derecha es mayor que central...
if (media_b > media_a){
servo_v=servo_v+1; //... entonces gira el servo una posición
if (servo_v>=20) servo_v=20; //Si servo llega al final de su giro lo deja en misma posición
servo_tpa81 ( TPA81_v_ID, servo_v );
}
}
else {
flag_h=flag_h+1;
delay_ms(5);
}
//Comprueba si algun pixel vertical mide temperatura > 28ºC (presencia)d
flag_presencia_v=0; //Reinicia el flag deteccion_v
for (i=1; i<10; i++){
if (b[i]>26) flag_presencia_v=1;
}
if (condicion >= (media_b&&media_a)) flag_calor_v=1; //Flag calor_v=1 cuando detecta foco en el pixel central
else flag_calor_v=0;
}
/******************************************************************************/
/************************ FUNCIÓN CALCULO DE LA DISTANCIA *********************/
#int_ccp2 //LLamada por interrupción flanco en RC2
void ccp2_int(){
if(cambio==0){ //Si es flanco de subida...
TFS=CCP_2; //Carga en valor flanco subida valor registro ccpr1
setup_ccp2(CCP_CAPTURE_FE); //Configuración modo captura en flanco de bajada
cambio=1; //Próximo flanco debe ser de bajada
}
else{ //Si es flanco de bajada...
TFB=CCP_2; //Carga en valor flanco bajada valor registro ccpr1
setup_ccp2(CCP_CAPTURE_RE); //Configuración modo captura en flanco de subida
cambio=0; //Próximo flanco debe ser de subida
if(nuevopulso==0) //Fin de pulso...
nuevopulso=1; //Pulso finalizado.
}
}
/******************************************************************************/
/************************ FUNCIÓN LECTURA BUMPER ******************************/
void bumper(){
while (!BUMPER_DER) GIRO_IZQUIERDA; //Cuando detecte bumper derecho
while (!BUMPER_IZQ) GIRO_DERECHA; //Cuando detecte bumper izquierdo
AVANCE;
}
/******************************************************************************/
/********************* FUNCIÓN AVANCE - DETECCIÓN OBSTÁCULO *******************/
void navegacion(){
delay_ms(500); //Tiempo entre lecturas de distancia
pulso_test();
if (distancia>30){ //Si distancia >30cm avanza
AVANCE;
Bumper(); //Comprueba obstáculos laterales en el avance
}
else{
PARO;
servo_h=1; //Posición servo -90º
servo_tpa81 ( TPA81_h_ID, servo_h ); //Manda posición del servo a TPA81
delay_ms(700); //Tiempo servo en -90º
pulso_test();
distancia_derecha=distancia;
servo_h=16; //Posición servo 0º
servo_tpa81 ( TPA81_h_ID, servo_h); //Manda posición del servo a TPA81
delay_ms (300); //Tiempo servo 0º
servo_h=30; //Posición servo +90º
servo_tpa81 ( TPA81_h_ID, servo_h ); //Manda posición del servo a TPA81
delay_ms(700); //Tiempo servo +90º
pulso_test();
distancia_izquierda=distancia;
servo_h=16; //Posición servo 0º
servo_tpa81 ( TPA81_h_ID, servo_h ); //Manda posición del servo a TPA81
if (distancia_derecha>distancia_izquierda){
GIRO_DERECHA;
delay_ms(500);
}
else{
GIRO_IZQUIERDA;
delay_ms(500);
}
}
}
/******************************************************************************/
/*********************** FUNCIÓN MOVIMIENTO TPA81 *****************************/
void movimiento_TPA81 () {
//Se mantendrá entre 1,5 m y 2,5 m de la fuente de calor
if ((flag_calor_v && flag_calor_h)==1){
pulso_test(); //Comprueba distancia a la fuente
delay_ms(300);
if (distancia>130){
//Antes de avanzar se posiciona frente a la fuente de calor tomando
//como referencia el ángulo de giro del servo del cuello horizontal
if (servo_h<14){
GIRO_DERECHA;
delay_ms(((16-servo_h)*60));
servo_h=16; //Deja el servo en posición 0º
servo_tpa81 ( TPA81_h_ID, servo_h );
}
if (servo_h>18){
GIRO_IZQUIERDA;
delay_ms(((servo_h-16)*60));
servo_h=16; //Deja el servo en posición 0º
servo_tpa81 ( TPA81_h_ID, servo_h );
}
AVANCE; //Con distancia a objeto > 1,3m avanza...
while (distancia>130) { //...hasta estar a 1,3m del objeto...
bumper(); //...usando bumpers
delay_ms(300);
pulso_test(); //Revisa distancia a la fuente
}
PARO; //Acercado ya hasta 1\'3m, se para
}
if (distancia<80){ //Si distancia a objeto < 0,8m ...
RETROCESO; // ...retrocede...
while (distancia<80) { // ...hasta estar a 0,8m del objeto
pulso_test(); //Revisa distancia al objeto
delay_ms(300);
}
PARO; //Separado ya a 0\'8m, se para
}
if (80<distancia<130) PARO; //Entre 0,8m y 1,3m se para.
}
}
/******************************************************************************/
/*************************** FUNCIÓN PRINCIPAL ********************************/
void main(){
trisa=0xff;
trisb=0x00; //Puerto B todo salidas
trisc=0b00000100; //Puerto C definición de entradas y salidas
servo_h=16; //Posición 0º del servo horizontal
servo_v=14; //Posición 0º del servo vertical
PARO; //Inicia con el robot parado
setup_timer_1(T1_INTERNAL); //Configuración timer1 para lectura obstáculo
setup_ccp2(CCP_CAPTURE_RE); //Configuración modo captura en flanco de subida
disable_interrupts(INT_TIMER1);
disable_interrupts(INT_CCP2); //Deshabilitación interrupción modo comparación
enable_interrupts (GLOBAL);
ojo_derecho=1;
ojo_izquierdo=1;
delay_ms(2000); //Estabilización en el arranque del sistema
while (1){
funcion_TPA81(); //Salto a la función del TPA
if (flag_presencia_v==1||flag_presencia_h==1) { //Si detecta presencia...
PARO;
for(repeticiones=0;repeticiones<6;repeticiones++){//nºmovimientos para posicionar la cabeza
funcion_TPA81(); //Salto a la función del TPA
}
movimiento_TPA81(); //Avanzar o retroceder segun distancia
}
else {
servo_v=((servo_v+14)/2); //Posición servo v
servo_tpa81 ( TPA81_v_ID, servo_v); //Manda posición del servo a TPA81
delay_ms(10);
servo_h=((servo_h+16)/2);
servo_tpa81 ( TPA81_h_ID, servo_h);
navegacion(); //Salto a la función navegacion
}
}
}
Hoy en día los compiladores son muy buenos, y son capaces de detectar los casos de abuso de memoria, y ahorrarlos, pero no en todas las ocasiones.Eso me pareció interesante.
¿Tendrás alguna guía o algo donde explique los malos hábitos o maneras de ahorrar (uso de variables globales, etc.)?
Ese 10 % se debe referir a lo que ocupan las estructuras, no la llamada a la función. Entonces... el trabajo es ver si hay partes comunes en las estructuras que puedan reducir el consumo de memoria. O si se puede usar un procedimiento que pueda generar esa información (por ejemplo, descomprimir).Es que el PIC que uso se quedo un poco corto y me gustaría reducir el espacio. También me doy cuenta que cuando paso a una función una estructura de muchos caracteres, ocupa como un 1% del PIC, y si llamo 10 veces a la función son 10%![]()
No pasa nada: lo haces en C, y se acabó. Pero si se te queda corto, pues la opción más sencilla es gastar unos pocos céntimos más y comprar un micro con más memoria.Así que me interesa eso para ver que cosas hacer. (Sé que se pueden revisar las instrucciones en ensamblador, pero estoy seco en ensamblador, así que no sé que ocupa y que no)
El caso es que la programación en microcontrolador es curiosa: algunos pasos (como des/activar una línea, por ejemplo), ocupan lo mismo en C que en ensamblador (una línea), así que el esfuerzo en problemas sencillos es casi el mismo. Es en los problemas mayores donde vemos la ganancia de C (al manejar flotantes, las bibliotecas con las funciones para protocolos serie/paralelo ya hechas)."Más vale un código eficiente y mantenible en C, que uno deficiente en ensamblador."
#define Led1Pin PIN4
#define Pous1Pin PIN2
#define Pous2Pin PIN3
#define Pous(x) ((PIND & (1<<(x))) != 0)
#define Pous1 Pous(Pous1Pin)
#define Pous2 Pous(Pous2Pin)
#define Pous1On (Pous1 == LOW )
#define Pous1Off (Pous1 == HIGH)
#define Pous2On (Pous2 == LOW )
#define LedOn(x) (PORTD |= (1<<(x)))
#define LedOff(x) (PORTD &= ~(1<<(x)))
#define Led1On LedOn (Led1Pin)
#define Led1Off LedOff (Led1Pin)
enum {espera, aprendiendo, llenando} estado = espera;
void setup() {
DDRD = 0b11110010;
// Serial.begin(115200);
}
unsigned long ahora;
unsigned long tiempo_llenado;
void loop() {
switch (estado) {
case espera:
if (Pous1On) {
estado = aprendiendo;
ahora = millis();
Led1On;
delay(20);
// Serial.println("aprendiendo");
}
if (Pous2On) {
estado = llenando;
ahora = millis();
Led1On;
// Serial.println("llenando");
}
break;
case aprendiendo:
if (Pous1Off) {
estado = espera;
tiempo_llenado = millis() - ahora;
Led1Off;
// Serial.println("espera");
}
break;
case llenando:
if (millis() >= ahora + tiempo_llenado) {
estado = espera;
Led1Off;
// Serial.println("espera");
}
break;
}
}
// --------------------------------------------------------------------------------
static int _INCLUDE_ARDUINO_H_HERE_;
/**
* Generate unsigned long (uint32_t) with specified bit(s) set.
*
* Supports setting up to 8 individual bits. Typically used to set up registers.
* Note: Overrides Arduino.h homonym macro, adding multi-bits functionality.
*
* Examples:
* bit(0, 2) -> (1ul<<(0) | 1ul<<(2)) -> (1 | 4) -> 5
* bit(ADEN, ADIE, ADSC) -> (1ul<<(ADEN) | 1ul<<(ADIE) | 1ul<<(ADSC))
*/
#define bit(bits...) (_bit_impl(args_nb(bits), bits))
/**
* Get/set/clear/toggle bit(s).
*
* Typically used to access/modify registers, but works with variables too.
* Supports multiple bits in one instruction. See bit() for details.
*
* Examples:
* get(PIND, SW1, SW2); // get states of switches 1 and 2
* set(ADCSRA, ADEN, ADIE, ADSC); // start ADC conversion + interrupt
* clr(ADCSRA, ADEN, ADIE); // switch off ADC
* tgl(PORTD, LED1, LED2); // toggle states of LEDs 1 and 2
*/
#define get(...) _get(__VA_ARGS__)
#define set(...) _set(__VA_ARGS__)
#define clr(...) _clr(__VA_ARGS__)
#define tgl(...) _tgl(__VA_ARGS__)
/**
* Is specified bit(s) set/clear?
*
* If several bits are tested, all of them must be set/clear to yield 'true'.
*
* Examples:
* while (is_set(ADCSRA, ADSC)); // wait till ADC conversion is ready
* if (is_clr(PIND, SW1, SW2)) // both SW1 and SW2 are active (low)?
*/
#define is_set(...) _is_set(__VA_ARGS__)
#define is_clr(...) _is_clr(__VA_ARGS__)
/*
* Implementations
*/
// Preprocessor voodoo: count number of macro variadic arguments (0 to 8)
#define args_nb(...) _args_nb(,##__VA_ARGS__,)
#define _args_nb(...) __args_nb(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define __args_nb(_E,_0,_1,_2,_3,_4,_5,_6,_7,_8, N, ...) N
// Set bits implementation (steps 1 and 2)
#define _bit_impl(n, args...) __bit_impl(n, args)
#define __bit_impl(n, args...) __bit_##n(args)
// Set bits implementation (steps 3: bits 0 to 8)
#define __bit_0(none) 0
#define __bit_1(bit) 1ul<<(bit)
#define __bit_2(bit, next) __bit_1(bit) | __bit_1(next)
#define __bit_3(bit, next...) __bit_1(bit) | __bit_2(next)
#define __bit_4(bit, next...) __bit_1(bit) | __bit_3(next)
#define __bit_5(bit, next...) __bit_1(bit) | __bit_4(next)
#define __bit_6(bit, next...) __bit_1(bit) | __bit_5(next)
#define __bit_7(bit, next...) __bit_1(bit) | __bit_6(next)
#define __bit_8(bit, next...) __bit_1(bit) | __bit_7(next)
// Get/set/clear/toggle register bit(s) implementations
#define _get(reg, bits...) ((reg) & bit(bits))
#define _set(reg, bits...) ((reg) |= bit(bits))
#define _clr(reg, bits...) ((reg) &= ~bit(bits))
#define _tgl(reg, bits...) ((reg) ^= bit(bits))
// Is bit set/clear implementations
#define _is_set(reg, bits...) (get(reg, bits) == bit(bits))
#define _is_clr(reg, bits...) (!get(reg, bits))
// --------------------------------------------------------------------------------
// LEDS (actives à 1)
#define L1 4
#define L1on set(PORTD, L1);
#define L1off clr(PORTD, L1);
// Boutons poussoirs (actifs à 0)
#define P1 PIND, 2
#define P2 PIND, 3
#define P1on is_clr(P1)
#define P2on is_clr(P2)
#define P1off is_set(P1)
#define P2off is_set(P2)
// #define getCnt() ({ \
// __asm__ volatile ("" : "=r"(cnt)); \
// cnt; \
// })
// compteur de temps
register uint8_t cnt asm("r4");
register uint8_t duree asm("r5"); // durée de remplissage sauvegardée
int main() __attribute__ ((optimize("O3"
,"no-move-loop-invariants" // cpse r5, r4; rjmp .-2 // Enables the loop invariant motion pass in the RTL loop optimizer. Enabled at level -O1
,"no-tree-loop-optimize" // rjmp .-4 // Perform loop optimizations on trees. This flag is enabled by default at -O and higher
// ,"no-unsafe-loop-optimizations"
// ,"no-reschedule-modulo-scheduled-loops"
// ,"no-aggressive-loop-optimizations"
// ,"no-gcse"
// ,"no-rerun-cse-after-loop"
// ,"no-prefetch-loop-arrays"
)));
int main() {
set(DDRD, 4); // L1 en sortie
TCCR0B = bit(CS02, CS00); // diviseur du timer0: clk/1024 (64µs)
TIMSK0 = bit(TOIE0); // enable timer0 overflow interrupt
sei();
while (1) {
if (P1on) { // P1? mesure du temps...
L1on;
while (P1on); // attend que P1 soit relaché
duree = cnt; // sauvegarde la durée
}
if (P2on) { // P2? remplissage...
L1on;
// attend la durée sauvegardée
while ( duree != cnt ) ;
// while (duree != *((volatile uint8_t*)(0x0004))) ;
// while (duree != getCnt());
// asm ("cpse %0, %1" "\n\t" "rjmp .-4"::"r"(cnt), "r"(duree));
}
L1off;
cnt = 0; // réinitialise le compteur
}
}
ISR(TIMER0_OVF_vect, ISR_NAKED) { // tous les 16.384ms (256x64µs)
cnt++; // incrémente le compteur
reti();
}
while ( duree != cnt ) ;
#define getCnt() ({ \
__asm__ volatile ("" : "=r"(cnt)); \
cnt; \
})
# ...
while (duree != getCnt());
register uint8_t cnt asm("r4");
# ...
while (duree != *((volatile uint8_t*)(0x0004))) ;
asm ("cpse %0, %1" "\n\t" "rjmp .-4"::"r"(cnt), "r"(duree));
register uint8_t cnt asm("r4");
register uint8_t duree asm("r5"); // durée de remplissage sauvegardée
int main() __attribute__ ((optimize("O3"
,"no-move-loop-invariants" // cpse r5, r4; rjmp .-2 // Enables the loop invariant motion pass in the RTL loop optimizer. Enabled at level -O1
,"no-tree-loop-optimize" // rjmp .-4 // Perform loop optimizations on trees. This flag is enabled by default at -O and higher
// ,"no-unsafe-loop-optimizations"
// ,"no-reschedule-modulo-scheduled-loops"
// ,"no-aggressive-loop-optimizations"
// ,"no-gcse"
// ,"no-rerun-cse-after-loop"
// ,"no-prefetch-loop-arrays"
)));
#...
while ( duree != cnt ) ;