这是使用 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.
让我知道这是否有效...
我目前正在做一个小项目。我正在尝试创建一个记忆游戏。我有两个 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.
让我知道这是否有效...