这是使用 ADC 更新全局变量的正确方法吗?

Is this the right way to update global variable using ADC?

我目前正在做一个小项目。我正在尝试创建一个记忆游戏。我有两个 LED 显示一些顺序,播放器需要重复它。我想用ADC改变延迟值,也就是闪烁速度

我有一个像这样的全局变量延迟函数...

uint16_t n = 500;

void delay(uint16_t n) {
    for(uint16_t i = 0; i < n ; i++) {
        for(uint16_t j = 0; j < 200 ; j++) {
            asm volatile ("NOP");
        }
    }
}

我的 ADC 初始化是这样的

void ADC_Init() {
    ADMUX = (1<<MUX1 | 1<<REFS0);
    // ADEN --> ADC Enable | ADSC --> ADC Start Conversion | ADPS --> ADC Prescaler Select Bits (16)
    ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADPS2);    
}

根据ADC读数,我想改变我到处使用的全局变量(“n”)的值。换句话说,我想从这里给全局变量一个新值

void NewDelayValue(n) {
    while (ADCSRA & (1<<ADIF)) {
    }
    if (n < 100) {
        n = 200;
    }
    else if (n > 200 && n < 300) {
        n = 300;
        return;
    }
    else if (n > 300 && n < 400) {
        n = 400;
        return;
    }
    else if (n > 500 && n < 600) {
        n = 500;
        return;
    }
    else if (n > 700 && n < 800) {
        n = 600;
        return;
    }
    else if (n > 900) {
        n = 700;
        return;
    }
    else {
        return;
    }
}

这样做正确吗?我应该如何更改我的代码来实现它? 希望我说的有道理,有什么想问的都可以问。

我的全部代码

#define F_CPU 2000000UL
#include <avr/io.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>

// Global
uint8_t Game[8];
int i;

uint16_t n = 500;
/*
void ADC_Init() {
    ADMUX = (1<<MUX1 | 1<<REFS0);
    // ADEN --> ADC Enable | ADSC --> ADC Start Conversion | ADPS --> ADC Prescaler Select Bits (16)
    ADCSRA = (1<<ADEN)|(1<<ADSC)|(1<<ADPS2);    
}
*/
/*
void NewDelayValue() {
    while (ADCSRA & (1<<ADIF)) {
    }
    if (n < 100) {
        n = 200;
    }
    else if (n > 200 && n < 300) {
        n = 300;
        return;
    }
    else if (n > 300 && n < 400) {
        n = 400;
        return;
    }
    else if (n > 500 && n < 600) {
        n = 500;
        return;
    }
    else if (n > 700 && n < 800) {
        n = 600;
        return;
    }
    else if (n > 900) {
        n = 700;
        return;
    }
    else {
        return;
    }
}
*/
void delay(uint16_t time_ms) {
    for(uint16_t i = 0; i < time_ms ; i++) {
        for(uint16_t j = 0; j < 200 ; j++) {
            asm volatile ("NOP");
        }
    }
}

void RandomNumber() {
    
    srand((unsigned int)time(NULL));
    for(unsigned int i = 0; i < sizeof(Game)/sizeof(Game[0]); i++) {
        int v = rand() % 2;
        Game[i] = v;
    }
}

void PlayDemo() {
    int i;
    for(i = 0; i < 8; i++) {
        if(Game[i] == 1) {
            PORTA = 0x80;
            delay(n);
            PORTA = 0x00;
            delay(n);
        }
        else if (Game[i] == 0) {
            PORTA = 0x01;
            delay(n);
            PORTA = 0x00;
            delay(n);
        }
        else {
            PORTA = 0x00;
        }
    }
}

uint8_t isButtonPressed(uint8_t PortValue) {
    if(PortValue & 0x08) {
        return 0;
    } else if(PortValue & 0x20) {
        return 1;
    }
    return 3;
}

int waitForPress() {

    uint8_t x = PINF;

    while(!(x & 0x20) && !(x & 0x08)) {
        x = PINF;
    }

    uint8_t ButtonPressed = isButtonPressed(x);
    delay(n);
    if(ButtonPressed == 1) {
        return 1;   
    } else if(ButtonPressed == 0) {
        return 0;
    }
    return 3;
}


int main(void) {
    MCUCR |= 0x80;
    MCUCR |= 0x80;
    DDRA = 0xFF;
    // 0x20 / 0x08 --> Joystick
    PORTF = 0x28;
    
    RandomNumber();
    PlayDemo();
    
    while(1)
    {
        /*
        if(isRightButtonPressed(PINF)) {
            PORTA = 0x01;
        } else {
            PORTA = 0x00;   
        }
        
        if(isLeftButtonPressed(PINF)) {
            PORTA = 0x80;
        } else {
            PORTA = 0x00;   
        }
        */
        
        for(uint8_t index = 0; index < 8; index++) {
            if(isButtonPressed(PINF) == 0) {
                PORTA = 0x01;
                int userInput = waitForPress();
                if(userInput != Game[index]) {
                    PORTA = 0xFF;
                    delay(n);
                    PORTA = 0x00;
                    delay(n);
                    break;
                } else if(userInput == Game[index]) {
                    PORTA = 0xFF;
                    delay(n);
                    PORTA = 0x00;
                    delay(n);
                }
            } else if(isButtonPressed(PINF) == 1) {
                PORTA = 0x80;
                int userInput = waitForPress();
                if(userInput != Game[index]) {
                    PORTA = 0xFF;
                    delay(n);
                    PORTA = 0x00;
                    delay(n);
                    break;
                } else if(userInput == Game[index]) {
                    PORTA = 0xFF;
                    delay(n);
                    PORTA = 0x00;
                    delay(n);
                } 
                }
        }
    }
}

也许这有帮助:

unsigned int NewDelayValue() {
    // Use the single conversion bit to check if the ADC has finished if you
    // only use it one time. It helds 1 until the converstion has finished
    while (ADCSRA & (1<<ADSC));

    // It is not necessary that the ADC uses 10 Bit so you should configure
    // left adjustment (ADLAR = 1)

    // Read the ADC value:
    unsigned char data = ADCH;

    // Create a number 1 - 8
    // 0   - 31  = 0 + 1 = 1 * 100 = 100
    // 32  - 63  = 1 + 1 = 2 * 100 = 200
    // ...
    // 224 - 255 = 7 + 1 = 8 * 100 = 800
    //
    return 100UL * ((data>>5) + 1);

    // If there is a potentiometer connected to your ADC channel you can use
    // the whole length between 0 - End (0-255) to generate the numbers...
}

// Short form of your delay function
void delay(unsigned int n) {
  // Can be included with -> #include <util/delay.h>
  _delay_ms(n);
}


// Call the function

unsigned int d = NewDelayValue();
delay(d);

// Or short form
delay(NewDelayValue());

配置ADLAR寄存器:

void ADC_Init() {
    ADMUX = (1<<MUX1) | (1<<REFS0) | (1<<ADLAR);
    // ...
}

Global Variables that are changed by functions in c is a bad practice. Sometimes it is necessary (e.g. interrupts) but should be avoided.

让我知道这是否有效...