Не удается переключаться между состояниями переключения в моем коде при запуске (ATmega328P)

#c #arduino-uno

Вопрос:

При запуске кода он должен находиться в режиме ожидания до тех пор, пока не будет нажата кнопка, которая переводит его в следующее состояние, в котором работают все мои цифровые выходы (светодиоды). Однако, как только я загружу код в ATmega328P, он запустится в рабочем режиме и не изменится. Кнопка подключена к контакту на Arduino, в который встроен небольшой светодиод, поэтому я знаю, что он определенно переключается.

Любая помощь была бы признательна, у меня та же проблема с другим кодом, поэтому я знаю, что это то, что я определенно делаю неправильно.

 #include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <util/delay.h>

#define SET_BIT(reg, pin)           (reg) |= (1 << (pin))
#define CLEAR_BIT(reg, pin)       (reg) amp;= ~(1 << (pin))
#define WRITE_BIT(reg, pin, value)   (reg) = (((reg) amp; ~(1 << (pin))) | ((value) << (pin)))
#define BIT_VALUE(reg, pin)       (((reg) >> (pin)) amp; 1)
#define BIT_IS_SET(reg, pin)         (BIT_VALUE((reg),(pin))==1)

//uart definitions
#define BAUD (9600)
#define MYUBRR (F_CPU/16/BAUD-1)

// These buffers may be any size from 2 to 256 bytes.
#define  RX_BUFFER_SIZE  64
#define  TX_BUFFER_SIZE  64


//uart definitions
unsigned char rx_buf;

static volatile uint8_t tx_buffer[TX_BUFFER_SIZE];
static volatile uint8_t tx_buffer_head;
static volatile uint8_t tx_buffer_tail;
static volatile uint8_t rx_buffer[RX_BUFFER_SIZE];
static volatile uint8_t rx_buffer_head;
static volatile uint8_t rx_buffer_tail;


// Functions declaration
void setup(void);
void process(void);
void uart_init(unsigned int ubrr);
void valve_pot_init(void);

// Uart functions
void uart_putchar(uint8_t c);
uint8_t uart_getchar(void);
uint8_t uart_available(void);
void uart_putstring(unsigned char* s);
void uart_getLine(unsigned char* buf, uint8_t n);

// ADC functions
uint16_t adc_read(uint8_t channel);
void adc_init();

// Global Variables amp; Defines for Puush Button Debouncing
#define PButton 0b00010000 // Location of pushbutton input in Port B
volatile uint8_t pushbuttons_db = 0;
volatile uint8_t reg1;
volatile uint8_t reg2;

// Setting up switch statement within process function
enum {
    standby,
    running,
    };
    
void digital_io_init( void ){
    
    // LED Setup    
    SET_BIT(DDRB,PB0); // Red LED, valve is operational, Unsafe to touch
    SET_BIT(DDRB,PB1); // Green LED, valve is non-operational, Safe to touch
    SET_BIT(DDRB,PB2); // Red LED, valve is fully open
    SET_BIT(DDRB,PB3); // Green LED, valve is fully closed
    SET_BIT(DDRD,PD2); // Back Light LED
    
    // Push Button Setup
    CLEAR_BIT(DDRB,PB4);
    
}

void debounce_init(void) {
    cli();
    
    // Setting Clear Time Compare on Timer0
    SET_BIT(TCCR0A,WGM01);
    CLEAR_BIT(TCCR0A,WGM00);
    
    // Setting Prescalar of 256 on Timer0
    SET_BIT(TCCR0B,CS02);
    CLEAR_BIT(TCCR0B,CS01);
    CLEAR_BIT(TCCR0B,CS00);
    
    // Setting 2ms period on Timer0
    CLEAR_BIT(OCR0A,7);
    SET_BIT(OCR0A,6);
    SET_BIT(OCR0A,5);
    SET_BIT(OCR0A,4);
    SET_BIT(OCR0A,3);
    SET_BIT(OCR0A,2);
    CLEAR_BIT(OCR0A,1);
    SET_BIT(OCR0A,0);
    
    // Enabling Interupt on Output Compare Match A 
    CLEAR_BIT(TIMSK0,OCIE0B);
    SET_BIT(TIMSK0,OCIE0A);
    CLEAR_BIT(TIMSK0,TOIE0);

    sei();
}

//main loop
int main() {
    
    // Digital I/O initialise
    digital_io_init();
    
    // Pot for valve, ADC initialise
    valve_pot_init();
    
    // Push button amp; debouncing initialise
    debounce_init();

    for ( ;; ) {
        process();
        // _delay_ms(1);
    }
}

//initialises ADC and UART port
void valve_pot_init(void) {

    //init uart
    uart_init(MYUBRR);

    // Initialise adc
    SET_BIT(ADCSRA,ADEN);
    
    // ADC Enable and pre-scaler of 128: ref table 24-5 in datasheet
    SET_BIT(ADCSRA,ADPS2);
    SET_BIT(ADCSRA,ADPS1);
    SET_BIT(ADCSRA,ADPS0);
    // ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);

   // Selecting channel and ref input voltage
    SET_BIT(ADMUX,REFS0);
    CLEAR_BIT(ADMUX,MUX0);
    CLEAR_BIT(ADMUX,MUX1);
    CLEAR_BIT(ADMUX,MUX2);
    CLEAR_BIT(ADMUX,MUX3);
    CLEAR_BIT(ADMUX,REFS1);

}


void process(void) {

    // For Push Button amp; Debouncing
    uint8_t pb_now = 0;
    uint8_t pb_prev = 0;
    uint8_t pb_pressed;
    
    // Determining whether push button has been pressed
    pb_now = pushbuttons_db;
    pb_pressed = pb_now amp; (pb_now ^ pb_prev);
    pb_prev = pb_now;

    char temp_buf[64];

   // Start single conversion by setting ADSC bit in ADCSRA
    ADCSRA |= (1 << ADSC);

    // Wait for ADSC bit to clear, signalling conversion complete.
     while ( ADCSRA amp; (1 << ADSC) ) {}

    // Result now available in ADC
    uint16_t pot = ADC;
    uint16_t valve_position = pot / 10.23; // This will give an output range of 0 to 100%
    
    // convert uint16_t to string
    itoa(valve_position, (char *)temp_buf,10);
    
    // Send serial data
   uart_putstring((unsigned char *) temp_buf);
   uart_putchar('t');

    static uint8_t state = standby ;
        
        switch (state){
            
            // This state is for no one is in the sauna, system on standby
            case standby:   // Clearing Light Outputs
                            CLEAR_BIT(PORTB,PB0); // Red LED, valve is operational, Unsafe to touch
                            CLEAR_BIT(PORTB,PB1); // Green LED, valve is non-operational, Safe to touch
                            CLEAR_BIT(PORTB,PB2); // Red LED, valve is fully open
                            CLEAR_BIT(PORTB,PB3); // Green LED, valve is fully closed
                            CLEAR_BIT(PORTD,PD2); // Back Light LED
                    
                            // Turning On Green LED on to say sauna is safe
                            SET_BIT(PORTB,1); // Green LED, valve is non-operational, Safe to touch
                    
                            // Button pressed means someone has entered sauna, go to running state
                            if ( pb_pressed amp; PButton ) {
                                state = running;
                            }
            
            // This state is for when someone is using the sauna, system is on
            case running:   // Cleaing Light Outputs
                            CLEAR_BIT(PORTB,PB0); // Red LED, valve is operational, Unsafe to touch
                            CLEAR_BIT(PORTB,PB1); // Green LED, valve is non-operational, Safe to touch
                            CLEAR_BIT(PORTB,PB2); // Red LED, valve is fully open
                            CLEAR_BIT(PORTB,PB3); // Green LED, valve is fully closed
                            CLEAR_BIT(PORTD,PD2); // Back Light LED
                    
                            // Turning On Red LED amp; LCD Back Light
                            SET_BIT(PORTD,PD2); // Back Light LED, turn on
                            SET_BIT(PORTB,PB0); // Red LED, valve is operational, Unsafe to touch
                            
                            // Physical indication of valve being fully open
                            if ( valve_position == 100 ){
                                SET_BIT(PORTB,2); // Red LED, valve is fully open
                            }
                            
                            // Physical indication of valve being fully closed
                            if ( valve_position == 0 ){
                                SET_BIT(PORTB,3); // Green LED, valve is fully closed
                            }
                            
                            // Button pressed means someone is going into sauna, go to next state
                            if ( pb_pressed amp; PButton ){
                                state = standby;
                            }
                            
            default: state = standby;
        } // Switch Statement
}




//PLEASE NOTE THIS VERSION OF UART USES INTERRUPTS

/*  ****** serial uart definitions ************ */
/******************  interrupt based  ********/

// Initialize the UART
void uart_init(unsigned int ubrr) {

    cli();

    UBRR0H = (unsigned char)(ubrr>>8);
    UBRR0L = (unsigned char)(ubrr);
    UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
    UCSR0C = (1 << UCSZ01) | (1 << UCSZ00);
    tx_buffer_head = tx_buffer_tail = 0;
    rx_buffer_head = rx_buffer_tail = 0;

    sei();

}



// Transmit a byte
void uart_putchar(uint8_t c) {
    uint8_t i;

    i = tx_buffer_head   1;
    if ( i >= TX_BUFFER_SIZE ) i = 0;
    while ( tx_buffer_tail == i ); // wait until space in buffer
    //cli();
    tx_buffer[i] = c;
    tx_buffer_head = i;
    UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0) | (1 << UDRIE0);
    //sei();
}

// Receive a byte
uint8_t uart_getchar(void) {
    uint8_t c, i;

    while ( rx_buffer_head == rx_buffer_tail ); // wait for character
    i = rx_buffer_tail   1;
    if ( i >= RX_BUFFER_SIZE ) i = 0;
    c = rx_buffer[i];
    rx_buffer_tail = i;
    return c;
}


// Transmit a string
void uart_putstring(unsigned char* s)
{
    // transmit character until NULL is reached
    while(*s > 0) uart_putchar(*s  );
}


// Receive a string
void uart_getLine(unsigned char* buf, uint8_t n)
{
    uint8_t bufIdx = 0;
    unsigned char c;

    // while received character is not carriage return
    // and end of buffer has not been reached
    do
    {
        // receive character
        c = uart_getchar();

        // store character in buffer
        buf[bufIdx  ] = c;
    }
    while((bufIdx < n) amp;amp; (c != 'n'));

    // ensure buffer is null terminated
    buf[bufIdx] = 0;
}



uint8_t uart_available(void) {
    uint8_t head, tail;

    head = rx_buffer_head;
    tail = rx_buffer_tail;
    if ( head >= tail ) return head - tail;
    return RX_BUFFER_SIZE   head - tail;
}


// Transmit Interrupt
ISR(USART_UDRE_vect) {
    uint8_t i;

    if ( tx_buffer_head == tx_buffer_tail ) {
        // buffer is empty, disable transmit interrupt
        UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
    }
    else {
        i = tx_buffer_tail   1;
        if ( i >= TX_BUFFER_SIZE ) i = 0;
        UDR0 = tx_buffer[i];
        tx_buffer_tail = i;
    }
}

// Receive Interrupt
ISR(USART_RX_vect) {
    uint8_t c, i;

    c = UDR0;
    i = rx_buffer_head   1;
    if ( i >= RX_BUFFER_SIZE ) i = 0;
    if ( i != rx_buffer_tail ) {
        rx_buffer[i] = c;
        rx_buffer_head = i;
    }
}

ISR(TIMER0_COMPA_vect){

    uint8_t pb0;
    uint8_t delta;

    pb0 = ~PINB;
    
    delta = pb0 ^ pushbuttons_db;

    pushbuttons_db ^= (reg2 amp; delta);

    reg2 = (reg1 amp; delta);
    reg1 = delta;

}
 

Комментарии:

1. Подсказка: break или вы провалитесь.

2. @tadman У меня там были перерывы, как и раньше, рука, не работающая ни в одном из сценариев, есть ли что-нибудь еще, что я мог бы попробовать?

3. Они своего рода супер важны, или у вас там весь код выполняется последовательно при определенных условиях. Тебе нужно это исправить. Удаление их-не очень хороший план.

4. Вы, вероятно, тоже хотите вернуть эту задержку, или вы блокируете свой процессор, выполняющий этот цикл.

5. Я не знаю, чувак, этот код довольно сильно нарушен. Например, вы не вызываете setup() и не вызываете adc_init() .. Вы пробовали установить точку останова непосредственно перед переключением, убедитесь, что регистры/переменные соответствуют вашим ожиданиям. В противном случае закомментируйте весь некритичный код, т. е. оцените только кнопку. Попробуйте дать государству какое-то фиктивное значение и посмотрите, что произойдет.