【问题标题】:Designing a reaction timer for atmega328p microcontroller using C使用 C 为 atmega328p 微控制器设计反应定时器
【发布时间】:2018-07-29 13:26:26
【问题描述】:

我必须做的基本描述:

“反应计时器”是一种嵌入式系统,可测量用户对信号的反应时间,并以三个 LED 的比例显示。当用户按下系统上的“就绪”按钮时,“反应计时器”会关闭系统中的所有 LED,并等待 1 到 10 秒之间的随机时间。在此等待时间到期后,“反应计时器”打开蓝色 LED 并向用户发出信号。然后用户尽快按下系统上的“反应”按钮以对信号作出反应。 “反应计时器”然后关闭用于发出信号的蓝色 LED,并测量信号与用户对信号的反应之间经过的时间。如果用户对信号的反应时间小于 1 秒、大于 1 秒但小于 2 秒或大于 2 秒,“反应计时器”会分别点亮绿色、橙色或红色 LED,以显示用户的表现.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h> //library includes srand(), rand() methods
#include <time.h>           //library include time()
#define F_CPU 4000000UL;    //Define F_CPU as 4MHz

int volatile randomnum;     //Declare volatile variable for random number generation
int volatile speed;         //Declare volatile variable to get the reaction speed

int main(void)
{
DDRB = DDRB | 0b00100111; //Configure PB5,PB0,PB1,PB2 as outputs                        
DDRD = DDRD & 0b11110011; //Configure PD2(INT0), PD3(INT3) as inputs
PORTD = PORTD | 0b00001100;     //Pull-up PD2, PD3
EICRA = (EICRA & 0b11111010) | 0b00001010;      //Set external interrupt on falling edge of INT0,INT1
EIMSK = EIMSK | 0b00000011;                     //Enable external interrupt on INT0,INT1
sei();                                          //Enable interrupts globally
TCCR1B = (TCCR1B & 0b11111101) | 0b00000101;    //Set clock source as F_CPU/1024 
TCNT1 = 0;                                      //Default TCNT value as 0
while (1) 
{

}
return 0;
}

ISR(INT0_vect){
time_t t;                                           //Declare time variable
PORTB = 0;                                          //Switch off all LEDs
srand( (unsigned) time(&t) );                       //Seed the random number using time
randomnum = rand() % 10 + 1;                        //Generate a random number between 1-10
TCNT1 = ( 65535 - (randomnum * 3906.25) ) + 1;      //Assign the value for TCNT to get the delay of random number seconds
TIMSK1 = TIMSK1 | 0b00000001;                       //Enable timer overflow interrupt
}

ISR(TIMER1_OVF_vect){                   //ISR for timer overflow interrupt
PORTB=PORTB|0b00100000;                 //Switch ON LED connected to PB5
}

ISR(INT1_vect){
speed = TCNT1 / 3906.25;                            //Calculate the time taken to react
if(speed > 2)                                       //If reaction time greater than 2s
{                                       
    PORTB = PORTB | 0b00000100;                     //Switch ON LED connected to PB2
}
else if ( (speed<2) && (speed>1) )                  //If reaction time greater than 1s but less than 2s
{
    PORTB = PORTB | 0b00000010;                     //Switch ON LED connected to PB1
}
else if(speed < 1)                                  //If reaction time less than 1s
{
    PORTB = PORTB | 0b00000001;                     //Switch ON LED connected to PB0
}
}

我已经尝试在 C 程序上找到对嵌入式系统进行编码的参考,如上。但失败了,因为所有这些都在 arduino 中。

上面的程序似乎只有在随机数生成为 1 时才有效。我找不到错误在哪里。你能参考我的代码并指出错误在哪里吗?

【问题讨论】:

  • 为了便于阅读和理解:1) 在每个左大括号'{'之后一致地缩进代码缩进。在每个右大括号 '}' 之前不缩进。建议每个缩进级别为 4 个空格。 2)单独的代码块:forifelsewhiledo...whileswitchcasedefault通过单个空行
  • 一般来说,对srand() 的调用应该位于main() 函数的早期,而不是中断处理程序中
  • 关于:ISR(TIMER1_OVF_vect){ //ISR for timer overflow interrupt PORTB=PORTB|0b00100000; //Switch ON LED connected to PB5 } 此 LED 活动未在问题描述中列出。请澄清。
  • 变量t不需要,把srand( (unsigned) time(&amp;t) );改成srand( (unsigned) time( NULL ) );
  • 建议将 (randomnum * 3906.25) 更改为 (int)(randomnum * 3906.25),这样程序就只使用整数而不是双精度数

标签: c embedded atmega


【解决方案1】:

我认为您应该在启用相关中断之前清除溢出标志。 否则,如果标志已经设置(即自启动程序以来已经过去了大约 17 秒),中断将立即触发。 请在启用溢出中断之前试试这个:

TIFR1 = 0b00000001;         // Clear timer overflow flag

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-10-27
    • 1970-01-01
    • 2018-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多