C 如果我们同时使用两个传感器,为什么它会向我们的电脑发送错误的数据?

C 如果我们同时使用两个传感器,为什么它会向我们的电脑发送错误的数据?,c,avr,C,Avr,我们必须读取两个传感器的数据。温度传感器和光传感器。我们使用的是带有atmel 328P处理器的arduino uno。它必须用普通C编码,而不是用arduino草图。目标是通过usb将传感器的两个读数发送到我们的电脑。代码如下: main.c: #include "AVR_TTC_scheduler.h" #include <avr/io.h> #include <avr/delay.h> #include <avr/interrupt.h> #includ

我们必须读取两个传感器的数据。温度传感器和光传感器。我们使用的是带有atmel 328P处理器的arduino uno。它必须用普通C编码,而不是用arduino草图。目标是通过usb将传感器的两个读数发送到我们的电脑。代码如下:

main.c:

#include "AVR_TTC_scheduler.h"
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/sfr_defs.h>
#include <util/delay.h>
#define F_CPU 16E6
#define UBBRVAL 51
#include "CFile1.c"
#include "CFile2.c"
// The array of tasks
sTask SCH_tasks_G[SCH_MAX_TASKS];


/*------------------------------------------------------------------*-

  SCH_Dispatch_Tasks()

  This is the 'dispatcher' function.  When a task (function)
  is due to run, SCH_Dispatch_Tasks() will run it.
  This function must be called (repeatedly) from the main loop.

-*------------------------------------------------------------------*/

void SCH_Dispatch_Tasks(void)
{
   unsigned char Index;

   // Dispatches (runs) the next task (if one is ready)
   for(Index = 0; Index < SCH_MAX_TASKS; Index++)
   {
      if((SCH_tasks_G[Index].RunMe > 0) && (SCH_tasks_G[Index].pTask != 0))
      {
         (*SCH_tasks_G[Index].pTask)();  // Run the task
         SCH_tasks_G[Index].RunMe -= 1;   // Reset / reduce RunMe flag

         // Periodic tasks will automatically run again
         // - if this is a 'one shot' task, remove it from the array
         if(SCH_tasks_G[Index].Period == 0)
         {
            SCH_Delete_Task(Index);
         }
      }
   }
}

/*------------------------------------------------------------------*-

  SCH_Add_Task()

  Causes a task (function) to be executed at regular intervals 
  or after a user-defined delay

  pFunction - The name of the function which is to be scheduled.
              NOTE: All scheduled functions must be 'void, void' -
              that is, they must take no parameters, and have 
              a void return type. 

  DELAY     - The interval (TICKS) before the task is first executed

  PERIOD    - If 'PERIOD' is 0, the function is only called once,
              at the time determined by 'DELAY'.  If PERIOD is non-zero,
              then the function is called repeatedly at an interval
              determined by the value of PERIOD (see below for examples
              which should help clarify this).


  RETURN VALUE:  

  Returns the position in the task array at which the task has been 
  added.  If the return value is SCH_MAX_TASKS then the task could 
  not be added to the array (there was insufficient space).  If the
  return value is < SCH_MAX_TASKS, then the task was added 
  successfully.  

  Note: this return value may be required, if a task is
  to be subsequently deleted - see SCH_Delete_Task().

  EXAMPLES:

  Task_ID = SCH_Add_Task(Do_X,1000,0);
  Causes the function Do_X() to be executed once after 1000 sch ticks.            

  Task_ID = SCH_Add_Task(Do_X,0,1000);
  Causes the function Do_X() to be executed regularly, every 1000 sch ticks.            

  Task_ID = SCH_Add_Task(Do_X,300,1000);
  Causes the function Do_X() to be executed regularly, every 1000 ticks.
  Task will be first executed at T = 300 ticks, then 1300, 2300, etc.            

-*------------------------------------------------------------------*/

unsigned char SCH_Add_Task(void (*pFunction)(), const unsigned int DELAY, const unsigned int PERIOD)
{
   unsigned char Index = 0;

   // First find a gap in the array (if there is one)
   while((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))
   {
      Index++;
   }

   // Have we reached the end of the list?   
   if(Index == SCH_MAX_TASKS)
   {
      // Task list is full, return an error code
      return SCH_MAX_TASKS;  
   }

   // If we're here, there is a space in the task array
   SCH_tasks_G[Index].pTask = pFunction;
   SCH_tasks_G[Index].Delay =DELAY;
   SCH_tasks_G[Index].Period = PERIOD;
   SCH_tasks_G[Index].RunMe = 0;

   // return position of task (to allow later deletion)
   return Index;
}

/*------------------------------------------------------------------*-

  SCH_Delete_Task()

  Removes a task from the scheduler.  Note that this does
  *not* delete the associated function from memory: 
  it simply means that it is no longer called by the scheduler. 

  TASK_INDEX - The task index.  Provided by SCH_Add_Task(). 

  RETURN VALUE:  RETURN_ERROR or RETURN_NORMAL

-*------------------------------------------------------------------*/

unsigned char SCH_Delete_Task(const unsigned char TASK_INDEX)
{
   // Return_code can be used for error reporting, NOT USED HERE THOUGH!
   unsigned char Return_code = 0;

   SCH_tasks_G[TASK_INDEX].pTask = 0;
   SCH_tasks_G[TASK_INDEX].Delay = 0;
   SCH_tasks_G[TASK_INDEX].Period = 0;
   SCH_tasks_G[TASK_INDEX].RunMe = 0;

   return Return_code;
}

/*------------------------------------------------------------------*-

  SCH_Init_T1()

  Scheduler initialisation function.  Prepares scheduler
  data structures and sets up timer interrupts at required rate.
  You must call this function before using the scheduler.  

-*------------------------------------------------------------------*/

void SCH_Init_T1(void)
{
   unsigned char i;

   for(i = 0; i < SCH_MAX_TASKS; i++)
   {
      SCH_Delete_Task(i);
   }

   // Set up Timer 1
   // Values for 1ms and 10ms ticks are provided for various crystals

   // Hier moet de timer periode worden aangepast ....!
   OCR1A = (uint16_t)625;                // 10ms = (256/16.000.000) * 625
   TCCR1B = (1 << CS12) | (1 << WGM12);  // prescale op 64, top counter = value OCR1A (CTC mode)
   TIMSK1 = 1 << OCIE1A;             // Timer 1 Output Compare A Match Interrupt Enable
}

/*------------------------------------------------------------------*-

  SCH_Start()

  Starts the scheduler, by enabling interrupts.

  NOTE: Usually called after all regular tasks are added,
  to keep the tasks synchronised.

  NOTE: ONLY THE SCHEDULER INTERRUPT SHOULD BE ENABLED!!! 

-*------------------------------------------------------------------*/

void SCH_Start(void)
{
      sei();
}

/*------------------------------------------------------------------*-

  SCH_Update

  This is the scheduler ISR.  It is called at a rate 
  determined by the timer settings in SCH_Init_T1().

-*------------------------------------------------------------------*/

ISR(TIMER1_COMPA_vect)
{
   unsigned char Index;
   for(Index = 0; Index < SCH_MAX_TASKS; Index++)
   {
      // Check if there is a task at this location
      if(SCH_tasks_G[Index].pTask)
      {
         if(SCH_tasks_G[Index].Delay == 0)
         {
            // The task is due to run, Inc. the 'RunMe' flag
            SCH_tasks_G[Index].RunMe += 1;

            if(SCH_tasks_G[Index].Period)
            {
               // Schedule periodic tasks to run again
               SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
               SCH_tasks_G[Index].Delay -= 1;
            }
         }
         else
         {
            // Not yet ready to run: just decrement the delay
            SCH_tasks_G[Index].Delay -= 1;
         }
      }
   }
}

// ------------------------------------------------------------------


int main()
{
    DDRB = 0xff;
    DDRD = 0xff;
    PORTD = 0xff;
    setup();
    setup2();
    SCH_Init_T1();

    SCH_Add_Task(commando, 0, 1);
    SCH_Add_Task(send_lux, 0, 100);
    SCH_Add_Task(send_temp, 0, 100);

    SCH_Start();

    while (1) {
        SCH_Dispatch_Tasks();
    }
    return 0;
}
void setup()
{
    UBRR0H = 0;
    UBRR0L = UBBRVAL;
    UCSR0A = 0;
    UCSR0B = _BV(TXEN0) | _BV(RXEN0);
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);

    ADMUX=(1<<REFS0);// For Aref=AVcc;
    ADCSRA=(1<<ADEN)|(1<<ADPS0);
}


uint16_t read(uint8_t ch) {
    //Select ADC Channel ch must be 0-7
    //ch=ch&0b00000111;
    ADMUX|=ch;

    //Start Single conversion

    ADCSRA|=(1<<ADSC);

    //Wait for conversion to complete
    while(!(ADCSRA & (1<<ADIF)));

    //Clear ADIF by writing one to it
    ADCSRA|=(1<<ADIF);

    return(ADC);
}

void transmit(uint8_t lux)
{
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = lux;
}

void send_lux()
{   
    float lux;
    lux = read(0b0000);
    lux = lux/10;
    transmit(lux);


     }

void commando()
{
    if bit_is_set(UCSR0A,RXC0)
    {
        PORTB = UDR0;
    }
}
void setup2()
{
    UBRR0H = 0;
    UBRR0L = UBBRVAL;
    UCSR0A = 0;
    UCSR0B = _BV(TXEN0) | _BV(RXEN0);
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);

    ADMUX=(1<<REFS0);// For Aref=AVcc;
    ADCSRA=(1<<ADEN)|(1<<ADPS0);
}


uint16_t read2(uint8_t ch) {
    //Select ADC Channel ch must be 0-7
    //ch=ch&0b00000111;
    ADMUX|=ch;

    //Start Single conversion

    ADCSRA|=(1<<ADSC);

    //Wait for conversion to complete
    while(!(ADCSRA & (1<<ADIF)));

    //Clear ADIF by writing one to it
    ADCSRA|=(1<<ADIF);

    return(ADC);
}

void transmit2(uint8_t temp)
{
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = temp;
}

void send_temp()
{
    float temp;
    temp = read2(0b0001);
    temp = (temp * 5)/1024;
    temp = ((temp -0.5) *100);
    transmit2(temp);

}
#包括“AVR_TTC_scheduler.h”
#包括
#包括
#包括
#包括
#包括
#包括
#定义F_CPU 16E6
#定义UBBRVAL 51
#包括“CFile1.c”
#包括“CFile2.c”
//任务数组
sTask schu_tasks_G[schu MAX_tasks];
/*------------------------------------------------------------------*-
SCH_调度任务()
这是“调度程序”功能。当任务(功能)完成时
即将运行,SCH_Dispatch_Tasks()将运行它。
必须从主循环(重复)调用此函数。
-*------------------------------------------------------------------*/
作废SCHU调度任务(作废)
{
无符号字符索引;
//分派(运行)下一个任务(如果已准备好)
对于(索引=0;索引0)和&(schu任务[Index].pTask!=0))
{
(*SCH_tasks_G[Index].pTask)(;//运行任务
SCH_tasks_G[Index].RunMe-=1;//重置/减少RunMe标志
//定期任务将自动再次运行
//-如果这是“一次性”任务,请将其从阵列中删除
if(SCH_tasks_G[Index].Period==0)
{
SCH_删除_任务(索引);
}
}
}
}
/*------------------------------------------------------------------*-
SCH_添加_任务()
使任务(功能)定期执行
或者在用户定义的延迟之后
pFunction—要调度的函数的名称。
注意:所有计划函数必须为“void,void”-
也就是说,它们必须不带参数,并且具有
无效返回类型。
延迟-任务首次执行前的间隔(滴答声)
PERIOD-如果“PERIOD”为0,则只调用函数一次,
在“延迟”确定的时间。如果周期不为零,
然后每隔一段时间重复调用该函数
由周期值确定(示例见下文
这应该有助于澄清这一点)。
返回值:
返回任务数组中已执行任务的位置
补充。如果返回值为SCH_MAX_TASKS,则该任务可以
无法添加到阵列中(空间不足)。如果
返回值为TCCR1B=(1ADC处理上存在争用条件。建议使用互斥限制每次只能访问一个任务。

ADC处理上存在争用条件。建议使用互斥限制每次只能访问一个任务。

是否需要使用调度程序?看起来您过于复杂了。如果你需要在一个特定的时间间隔内发送数据,然后你可以使用计时器。哪个传感器发送错误的数据
    #include "AVR_TTC_scheduler.h"
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <avr/sfr_defs.h>
#include <util/delay.h>
//#define F_CPU 16E6
#define UBBRVAL 51
//#include "CFile1.c"
//#include "CFile2.c"
// The array of tasks
sTask SCH_tasks_G[SCH_MAX_TASKS];


/*------------------------------------------------------------------*-

  SCH_Dispatch_Tasks()

  This is the 'dispatcher' function.  When a task (function)
  is due to run, SCH_Dispatch_Tasks() will run it.
  This function must be called (repeatedly) from the main loop.

-*------------------------------------------------------------------*/

void SCH_Dispatch_Tasks(void)
{
   unsigned char Index;

   // Dispatches (runs) the next task (if one is ready)
   for(Index = 0; Index < SCH_MAX_TASKS; Index++)
   {
      if((SCH_tasks_G[Index].RunMe > 0) && (SCH_tasks_G[Index].pTask != 0))
      {
         (*SCH_tasks_G[Index].pTask)();  // Run the task
         SCH_tasks_G[Index].RunMe -= 1;   // Reset / reduce RunMe flag

         // Periodic tasks will automatically run again
         // - if this is a 'one shot' task, remove it from the array
         if(SCH_tasks_G[Index].Period == 0)
         {
            SCH_Delete_Task(Index);
         }
      }
   }
}

/*------------------------------------------------------------------*-

  SCH_Add_Task()

  Causes a task (function) to be executed at regular intervals 
  or after a user-defined delay

  pFunction - The name of the function which is to be scheduled.
              NOTE: All scheduled functions must be 'void, void' -
              that is, they must take no parameters, and have 
              a void return type. 

  DELAY     - The interval (TICKS) before the task is first executed

  PERIOD    - If 'PERIOD' is 0, the function is only called once,
              at the time determined by 'DELAY'.  If PERIOD is non-zero,
              then the function is called repeatedly at an interval
              determined by the value of PERIOD (see below for examples
              which should help clarify this).


  RETURN VALUE:  

  Returns the position in the task array at which the task has been 
  added.  If the return value is SCH_MAX_TASKS then the task could 
  not be added to the array (there was insufficient space).  If the
  return value is < SCH_MAX_TASKS, then the task was added 
  successfully.  

  Note: this return value may be required, if a task is
  to be subsequently deleted - see SCH_Delete_Task().

  EXAMPLES:

  Task_ID = SCH_Add_Task(Do_X,1000,0);
  Causes the function Do_X() to be executed once after 1000 sch ticks.            

  Task_ID = SCH_Add_Task(Do_X,0,1000);
  Causes the function Do_X() to be executed regularly, every 1000 sch ticks.            

  Task_ID = SCH_Add_Task(Do_X,300,1000);
  Causes the function Do_X() to be executed regularly, every 1000 ticks.
  Task will be first executed at T = 300 ticks, then 1300, 2300, etc.            

-*------------------------------------------------------------------*/

unsigned char SCH_Add_Task(void (*pFunction)(), const unsigned int DELAY, const unsigned int PERIOD)
{
   unsigned char Index = 0;

   // First find a gap in the array (if there is one)
   while((SCH_tasks_G[Index].pTask != 0) && (Index < SCH_MAX_TASKS))
   {
      Index++;
   }

   // Have we reached the end of the list?   
   if(Index == SCH_MAX_TASKS)
   {
      // Task list is full, return an error code
      return SCH_MAX_TASKS;  
   }

   // If we're here, there is a space in the task array
   SCH_tasks_G[Index].pTask = pFunction;
   SCH_tasks_G[Index].Delay =DELAY;
   SCH_tasks_G[Index].Period = PERIOD;
   SCH_tasks_G[Index].RunMe = 0;

   // return position of task (to allow later deletion)
   return Index;
}

/*------------------------------------------------------------------*-

  SCH_Delete_Task()

  Removes a task from the scheduler.  Note that this does
  *not* delete the associated function from memory: 
  it simply means that it is no longer called by the scheduler. 

  TASK_INDEX - The task index.  Provided by SCH_Add_Task(). 

  RETURN VALUE:  RETURN_ERROR or RETURN_NORMAL

-*------------------------------------------------------------------*/

unsigned char SCH_Delete_Task(const unsigned char TASK_INDEX)
{
   // Return_code can be used for error reporting, NOT USED HERE THOUGH!
   unsigned char Return_code = 0;

   SCH_tasks_G[TASK_INDEX].pTask = 0;
   SCH_tasks_G[TASK_INDEX].Delay = 0;
   SCH_tasks_G[TASK_INDEX].Period = 0;
   SCH_tasks_G[TASK_INDEX].RunMe = 0;

   return Return_code;
}

/*------------------------------------------------------------------*-

  SCH_Init_T1()

  Scheduler initialisation function.  Prepares scheduler
  data structures and sets up timer interrupts at required rate.
  You must call this function before using the scheduler.  

-*------------------------------------------------------------------*/

void SCH_Init_T1(void)
{
   unsigned char i;

   for(i = 0; i < SCH_MAX_TASKS; i++)
   {
      SCH_Delete_Task(i);
   }

   // Set up Timer 1
   // Values for 1ms and 10ms ticks are provided for various crystals

   // Hier moet de timer periode worden aangepast ....!
   OCR1A = (uint16_t)625;                // 10ms = (256/16.000.000) * 625
   TCCR1B = (1 << CS12) | (1 << WGM12);  // prescale op 64, top counter = value OCR1A (CTC mode)
   TIMSK1 = 1 << OCIE1A;             // Timer 1 Output Compare A Match Interrupt Enable
}

/*------------------------------------------------------------------*-

  SCH_Start()

  Starts the scheduler, by enabling interrupts.

  NOTE: Usually called after all regular tasks are added,
  to keep the tasks synchronised.

  NOTE: ONLY THE SCHEDULER INTERRUPT SHOULD BE ENABLED!!! 

-*------------------------------------------------------------------*/

void SCH_Start(void)
{
      sei();
}

/*------------------------------------------------------------------*-

  SCH_Update

  This is the scheduler ISR.  It is called at a rate 
  determined by the timer settings in SCH_Init_T1().

-*------------------------------------------------------------------*/

ISR(TIMER1_COMPA_vect)
{
   unsigned char Index;
   for(Index = 0; Index < SCH_MAX_TASKS; Index++)
   {
      // Check if there is a task at this location
      if(SCH_tasks_G[Index].pTask)
      {
         if(SCH_tasks_G[Index].Delay == 0)
         {
            // The task is due to run, Inc. the 'RunMe' flag
            SCH_tasks_G[Index].RunMe += 1;

            if(SCH_tasks_G[Index].Period)
            {
               // Schedule periodic tasks to run again
               SCH_tasks_G[Index].Delay = SCH_tasks_G[Index].Period;
               SCH_tasks_G[Index].Delay -= 1;
            }
         }
         else
         {
            // Not yet ready to run: just decrement the delay
            SCH_tasks_G[Index].Delay -= 1;
         }
      }
   }
}

// ------------------------------------------------------------------
void setup2()
{
    UBRR0H = 0;
    UBRR0L = UBBRVAL;
    UCSR0A = 0;
    UCSR0B = _BV(TXEN0) | _BV(RXEN0);
    UCSR0C = _BV(UCSZ01) | _BV(UCSZ00);

    ADMUX=(1<<REFS0);// For Aref=AVcc;
    ADCSRA=(1<<ADEN)|(1<<ADPS0);
}


uint16_t read2(uint8_t ch) {
    //Select ADC Channel ch must be 0-7
    //ch=ch&0b00000111;
    ADMUX|=ch;

    //Start Single conversion

    ADCSRA|=(1<<ADSC);

    //Wait for conversion to complete
    while(!(ADCSRA & (1<<ADIF)));

    //Clear ADIF by writing one to it
    ADCSRA|=(1<<ADIF);

    return(ADC);
}

void transmit2(uint8_t send)
{
    loop_until_bit_is_set(UCSR0A, UDRE0);
    UDR0 = send;
}

void send_temp()
{
    float temp;
    temp = read2(0b0001);
    temp = (temp * 5)/1024;
    temp = ((temp -0.5) *100);
    transmit2(temp);_delay_ms(10);

}


void send_lux()
{
    float lux;
    lux = read2(0b0000);
    lux = lux/10;
    transmit2(lux);_delay_ms(10);

}

void commando()
{
    if bit_is_set(UCSR0A,RXC0)
    {
        PORTB = UDR0;
    }
}


int main()
{
    DDRB = 0xff;
    DDRD = 0xff;
    PORTD = 0xff;
    //setup();
    setup2();
    SCH_Init_T1();

    SCH_Add_Task(commando, 0, 500);
    SCH_Add_Task(send_lux, 0, 1000);
    SCH_Add_Task(send_temp, 500, 1000);

    SCH_Start();

    while (1) {
        SCH_Dispatch_Tasks();
    }
    return 0;

}