#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() .. Вы пробовали установить точку останова непосредственно перед переключением, убедитесь, что регистры/переменные соответствуют вашим ожиданиям. В противном случае закомментируйте весь некритичный код, т. е. оцените только кнопку. Попробуйте дать государству какое-то фиктивное значение и посмотрите, что произойдет.