AVR-C apagando el led después de la cantidad de parpadeos con interrupciones

0

así que lo que estoy tratando de hacer es que intento hacer que el led parpadee un cierto número de veces antes de que se apague. Quiero evitar usar retrasos, así que lo intenté
Utilizando la interrupción y también usé un valor de marcador de posición como x para contar el número de veces que pasa por la interrupción, por lo que al alcanzar ese valor se desactivará. Sin embargo, tengo problemas para hacer que funcione, cualquier idea.

            /*
             * GccApplication3.c
             *
             * Created: 2015-04-01 6:13:58 AM
             *  Author: Bangladesh
             */ 


            #include <avr/io.h>   
            #include <util/delay.h> 
            #include <avr/interrupt.h> 
            #define stp_led PB0 
            #define dir_led PB1
            #define led_port PORTB
            #define led_ddr DDRB
            #define F_CPU 16000000UL 
            int x = 0;


            int main(void)
            { 
                ///////////////////////////////////////////////////////
                led_ddr |= (1 << stp_led); //enable led as an output pin  
                led_ddr |= (1 << dir_led);   
                //led_port |= (1<<stp_led);   
                led_port |= (1<<dir_led); 
                ///////////////////////////////////////////////////////
                TCCR1B |= (1 << WGM12);  // configuring timer 1 for ctc mode
                OCR1A = 15625;
                TIMSK1 |= (1 << OCIE1A); // enable ctc interrupt

                TCCR1B |= ((1 << CS12) | (1<< CS10)); //Start at 1024 prescaler 

                sei(); //Enable global interrupts

                 //Sets ctc compare value to 1hz at 1mhz AVR clock, with prescaler of 64




             while(1)  
                {  

                } 
            } //end of while loop 


            ISR(TIMER1_COMPA_vect)
            {   

                function_details (10, 1);

            }

            void function_details (stp,dir){  

                if (dir == 1){ 
                    led_port |= (1 << dir_led); 
                } 
                else if (dir == 0){ 
                    led_port &= ~ (1 << dir_led);
                }    
            while (1){
                led_port ^= (1 << stp_led);
                if (x == stp){ 
                    led_port &= ~ (1 << stp_led);  
                    return 0;
                    }  
                    x++; 
                }

            }
    
pregunta Redrachet2

3 respuestas

0

Bien, hice un poco de investigación y un amigo me dijo que usara valores booleanos. Así que digamos que si alcanzo un cierto número de incrementos, puedo usar un valor booleano para que el valor de x se incremente. Aquí está el código:

         /*
         * avr_cnc.c
         *
         * Created: 2015-04-01 6:13:58 AM
         *  Author: Alvi
         */ 


        #include <avr/io.h>    
        #include <stdio.h>
        #include <util/delay.h> 
        #include <avr/interrupt.h>  
        //axis bools

        //////////////////
        // x-axis
        #define stp_x_led PB0
        #define dir_x_led PB1  

        ////////////// 
        // y-axis
        #define stp_y_led PD6
        #define dir_y_led PD7 

        ////////////  
        // z-zxis  
        #define stp_z_led PD4 
        #define dir_z_led PD5

        // PORTB 
        #define led_portx PORTB
        //////////// 
        /// PORTD
        #define led_portyz PORTD 
        ///////////  
        // PORTC 
        //#define led_portz PORTC 
        // DDR////////
        #define led_x_ddr DDRB  
        #define led_y_ddr DDRD 
        #define led_z_ddr DDRD
        #define F_CPU 16000000UL 


        int x_counter = 0; 
        int x_boolean = 1; 
        int y_counter = 0; 
        int y_boolean = 1;
        int z_counter = 0; 
        int z_boolean = 1;  


        int x_enable = 1; 
        int y_enable = 1; 
        int z_enable = 1;



        int main(void)
        {  

            ////// DDR setups /////////////////////////////////////////////////
            led_x_ddr |= ((1 << stp_x_led) | (1 << dir_x_led));   
            led_y_ddr |= ((1 << stp_y_led) | (1 << dir_y_led)); 
            led_z_ddr |= ((1 << stp_z_led) | (1 << dir_z_led));
            ///////////////////////////////////////////////////////////

            TCCR1B |= (1 << WGM12);  // configuring timer 1 for ctc mode
            OCR1A = 4678;
            TIMSK1 |= (1 << OCIE1A); // enable ctc interrupt

            TCCR1B |= ((1 << CS12) | (1<< CS10)); //Start at 1024 prescaler 

            sei(); //Enable global interrupts

             //Sets ctc compare value to 1hz at 1mhz AVR clock, with prescaler of 64




         while(1)  
            {  

            } 
        } //end of while loop 


        ISR(TIMER1_COMPA_vect)
        {   
            ///////Define which stepper, direction and how many steps in this code
            x_stepper(1,10, 1);  
            y_stepper(1,20,1); 
            z_stepper(0,30,1); 
            ////////////////////////////////////////////////////////////////////
        }

        void x_stepper (axis_x,stp_x,dir_x){ 

            // checks if user enabled x-axis 
            if (axis_x == x_enable){
                //direction
                if (dir_x == 1){ 
                    led_portx |= (1 << dir_x_led); 
                } 
                else if (dir_x == 0){ 
                    led_portx &= ~ (1 << dir_x_led); 
                } 
                ///////////////////////////////
                //stepper logic
                led_portx ^= (1 << stp_x_led);
                    if (x_counter >= stp_x){ 
                        led_portx &= ~ (1 << stp_x_led);  
                        x_boolean = 0; 
                    }      
                if (x_boolean == 1){
                x_counter ++;
                }   
            //////////////////////////////
            }   
        }


        void y_stepper (axis_y,stp_y,dir_y){ 

            // checks if user enabled y-axis 
            if (axis_y == y_enable){
                //direction
                if (dir_y == 1){ 
                    led_portyz |= (1 << dir_y_led); 
                } 
                else if (dir_y == 0){ 
                    led_portyz &= ~ (1 << dir_y_led); 
                }  
                ///////////////////////////////
                //stepper logic
                led_portyz ^= (1 << stp_y_led);
                    if (y_counter >= stp_y){ 
                        led_portyz &= ~ (1 << stp_y_led);  
                        y_boolean = 0; 
                    }      
                if (y_boolean == 1){
                y_counter ++;
                }   
                //////////////////////////////
            }  
        }

         void z_stepper (axis_z,stp_z,dir_z){ 

            // checks if user enabled z-axis 
            if (axis_z == z_enable){
                //direction
                if (dir_z == 1){ 
                    led_portyz |= (1 << dir_z_led); 
                } 
                else if (dir_z == 0){ 
                    led_portyz &= ~ (1 << dir_z_led); 
                } 
                ///////////////////////////////
                //stepper logic
                led_portyz ^= (1 << stp_z_led);
                    if (z_counter >= stp_z){ 
                        led_portyz &= ~ (1 << stp_z_led);  
                        z_boolean = 0; 
                    }      
                if (z_boolean == 1){
                z_counter ++;
                }   
                //////////////////////////////
            }
        } 
    
respondido por el Redrachet2
3

Prueba algo como esto

     ISR(TIMER1_COMPA_vect)
     {   
           if(led_blink_count < 10)
           {
                //Toggle the led state
                led_blink_count++;
           }             
     }

Haga que el temporizador se dispare a la frecuencia con la que desea que parpadee el led. Establezca led_blink_count en 0 para reiniciar el parpadeo.

    
respondido por el Axis
1

No soy un programador de AVR, pero lo hago para ARM / PIC, así que lo pondré como apenas pseudo-código.

En primer lugar quiero señalar algunas cosas:

-ISR siempre debe ser lo más corto posible y, si se puede evitar, no deben llamar a las funciones.

: el uso de un ISR que bloquea la ejecución hasta que se haga todo en este caso no tiene sentido, si lo haces, obtienes el mismo resultado que no usar una interrupción y usar demoras.

-Su código tiene un bucle que no puedo entender, está invirtiendo el bit de puerto en stp_led, luego lo enmascara X veces ... se realiza en una sola llamada, por lo que todo el ciclo se producirá en una interrupción. / p>

Entonces, trata de hacer algo como esto:

volatile unsigned char currentBlink = 0xFF;

int main(void)
{

    unsigned char processedLastBlink = 255;

    SetupTimer();
    SetupLed();

    ResetBlink();

    while(1)
    {
        if(currentBlink != processedLastBlink)
        {
            LedOutput(currentBlink % 2 ? 0 : 1);
            processedLastBlink = currentBlink
        }

        //You can restart blinking whenever you want with ResetBlink();
    }

    ISR(TIMER1_COMPA_vect)
    {
        if(++currentBlink == 20)
            DisableBlink();
    }

    void SetupTimer(void)
    {
        //Configure timer to fire an interrupt every half a cycle
        //If you want a blink per second configure it to interrupt each 500ms

    }

    void SetupLed(void)
    {
         //Configure GPIO for led as output
         LedOutput(0);
    }

    void ResetBlink(void)
    {
        ResetTimer; //Set timer counter to 0
        currentBlink = 0xFF;
        EnableInterrupts; //sei()?
    }

    inline void DisableBlink(void)
    {
        DisableInterrupts; //sdi()?
    }

    void LedOutput(unsigned char value)
    {
        //Set LED's GPIO to the given value (1 or 0)
    }
}
    
respondido por el Gusman

Lea otras preguntas en las etiquetas