Incrementar el valor y mostrar en C

3

como mi principal cosa con la electrónica es el hardware, tengo algunas dificultades para aprender a programar. Desafortunadamente, mi universidad en la que estudio no ofrece este tipo de curso, así que para mi proyecto este año decidí incorporar algunos, para forzarme a aprenderlo, sin embargo, ¡estoy luchando por entender algo de eso! He estado creando partes separadas de mi código y la mayoría está funcionando, sin embargo, estoy tratando de mostrar un recuento en una pantalla LCD, y cada vez que se presiona un botón, quiero que se incremente en 1.

Logré hacer esto exitosamente en un Arduino (ya que hay muchos bocetos de ejemplo) pero quiero hacer mi proyecto usando un Núcleo STM (F103RB). Intenté transferir el código de ejemplo y editarlo con los comandos que el IDE de mbed en línea entendería, pero no funcionaría. Luego encontré algunos ejemplos diferentes y cada uno me dio resultados diferentes. Finalmente encontré mi propio código siguiendo una guía para agregar / presentar en el libro 'Programación en C: un enfoque mordaz'. El código que he encontrado está aquí:

#include "mbed.h"
#include "TextLCD.h"

DigitalIn ip(D7);
TextLCD lcd(A0, A1, A2, A3, A4, A5);

int i =0;

int main() {
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("COUNT:");
    lcd.locate(0,1);
    lcd.printf("%d",i);
    while(1) {
    if (ip ==1) {
    lcd.locate(0,1);
    lcd.printf("%d", ++i);
        }
    }

Y finalmente, el conteo comenzó a responder cuando presioné el botón. Sin embargo, el problema que tengo es que el conteo se incrementa todo el tiempo que tengo presionado el botón, por lo que incluso una pequeña pulsación aumentará el conteo en 50-80 (dependiendo de la rapidez con la que lo presione) y quiero que aumente 1 cada pulsación.

He intentado estructurarlo de forma diferente, con la frase 'while' al principio, etc., pero eso solo provocó que la pantalla LCD oscilara de forma extraña.

¡He estado estancado en esto por aproximadamente 6 horas antes de llegar a este punto! ¡Realmente apreciaría si alguien me pudiera dar algunos consejos en la dirección correcta!

En caso de que alguien lo necesite, mi esquema (simplificado) está aquí:

simular este circuito : esquema creado usando CircuitLab

Así que puedes ver que realmente es muy simple. Pero tengo un conocimiento nulo de la programación en C y nunca me han enseñado cómo hacerlo correctamente, ¡por lo que será necesario explicar cualquier solución!

    
pregunta MCG

2 respuestas

2

La razón principal por la que su contador aumenta tan rápidamente es que probablemente lo mantenga presionado durante aproximadamente 1 segundo y el bucle while se ejecuta unas 100 veces durante ese tiempo. Así aumentará el contador en aproximadamente 100.

Lo que realmente quieres es aumentar el contador solo una vez cada vez que se presiona. Una solución se muestra a continuación. El bucle while recuerda el último estado del botón. La cláusula if solo se ejecuta si el estado va de 0 a 1. Ya no se ejecutará cuando el valor anterior sea 1, es decir, el estado del botón no ha cambiado, solo se mantuvo presionado .

#include "mbed.h"
#include "TextLCD.h"

DigitalIn ip(D7);
TextLCD lcd(A0, A1, A2, A3, A4, A5);

int i = 0;
int lastButtonValue = 0;

int main() {
    lcd.cls();
    lcd.locate(0,0);
    lcd.printf("COUNT:");
    lcd.locate(0,1);
    lcd.printf("%d",i);

    while(1) {
        if (lastButtonValue == 0 && ip == 1) {
            lcd.locate(0,1);
            lcd.printf("%d", ++i);
        }
        lastButtonValue = ip;
    }
}
    
respondido por el Codo
1

Por lo general, no desea realizar un ciclo de ocupado cuando espera a que se presione el botón, sino que debe esperar a que ocurra una interrupción en el botón y luego cambiar el contador. Con Mbed OS, puede usar la clase InterruptIn para esto, y poner una devolución de llamada en el método fall . Aquí hay una demostración en el simulador de Mbed .

Debido a que esto se ejecuta en una ISR (rutina de servicio de interrupción), desea regresar a su hilo principal para actualizar la pantalla LCD (consulte here ).

Por ejemplo, esto funcionaría:

#include "mbed.h"
#include "TextLCD.h"

TextLCD lcd(A0, A1, A2, A3, A4, A5);
InterruptIn btn(D7);

EventQueue ev_queue;

int i = 0;

// This is now executed on the event loop, thus it's safe to block here...
void btn_press() {
    lcd.locate(0, 0);
    lcd.printf("COUNT: %d", ++i);
}

int main() {
    Thread ev_thread;
    ev_thread.start(callback(&ev_queue, &EventQueue::dispatch_forever));

    lcd.cls();
    lcd.locate(0, 0);
    lcd.printf("COUNT: %d", i);

    btn.fall(ev_queue.event(&btn_press));

    wait(osWaitForever);
}

Tenga en cuenta que, si necesita realizar rebotes en el software, consulte DebounceInterruptIn , solo cambie InterruptIn en un DebounceInterruptIn .

    
respondido por el Jan Jongboom

Lea otras preguntas en las etiquetas