簡體   English   中英

如何停止循環並等待直到從串行接收到不同的值

[英]how to stop looping and wait until different value received from serial

您好,我打算使用C和codevision在AVR上使用串行作為控制觸發信號進行多伺服控制

但是當觸發器為真時,伺服器會瘋狂循環,返回到原始位置(0度),而不是停留在所需位置,我的老師給了我提示,請使用“ wait ...直到”語句與舊數據進行比較但是我還沒有找到在Google上利用它的方法

因為利用休息 在結束時,如果芯片凍結,直到復位

和舊代碼(連續運行伺服器來回運行)

 while (1)
      {           
      while(UCSRA & (1<<RXC))  
          {
      // Place your code here
           //data=UDR;

           PORTC=UDR;
           data=UDR;
           //PORTB=data;
           } ;

          if (data== 0x0A || data== 0x0B)
          {     
                if (data== 0x0A)
                  {     
                        old_data=data;

                        PORTA=0x00;
                        PORTA.1=1;
                        movservo0(90,7);
                        movservo1(15,3);



                   }    

                if (data== 0x0B)
                  {     
                        old_data=data;

                        PORTA=0x00;
                        PORTA.1=1;
                        movservo0(15,3);
                        movservo1(90,7);


                   } 


           }
}

至於movservo0(另一個movservo()幾乎具有相同的代碼)

void set_servo1(unchar derajat)
{   unchar n;

    servo2=1;
    delay_us(750);
    for(n=0; n<derajat; n++)
    {
        delay_us(12);

    };
    servo2=0;
    delay_ms(10);
}

void movservo0(unsigned char sudut, unsigned char speed)
{
     unchar i;
    set_servo1(sudut);
    for (i=1;i<=sudut;i+=speed){
    set_servo1(i);
    delay_ms(100/speed);
    }
}

這段新代碼要好一些。

這樣, while(UCSRA & (1<<RXC))循環的頂部很好。 僅當有要讀取的字符時,才輸入循環體。 (盡管如此,我不確定您為什么期望閱讀'\\ n'或垂直標簽。)

一個小問題是讀取UDR的方式。 讀取UDR的操作將擦除內容。 所以你應該使用

data=UDR;    
PORTC=data;

伺服器的跳躍似乎在moveservo()函數中。 此功能始終將角度設置為1,然后逐漸增加伺服角度,直到達到所需角度。

setservo()似乎是嘗試執行PWM以驅動伺服器,但是它無法正常工作。 為了使伺服器保持在所需的角度,您必須在正確的時間將引腳從0切換到1,而不僅僅是此功能一次。 您是否看過計時器的PWM功能? 您只需設置這些,它們就會在后台運行。 一種替代方法是使用計時器將中斷設置為喚醒並根據需要切換引腳。

如果要在不中斷的情況下進行引腳切換,則應在while(1)循環本身中使用延遲。 只需使用setservo()函數來更改一些變量。

while(1)
{
    // read the UART if ready and set the target values
    // this part only runs occasionally
    while(UCSRA & (1<<RXC))  
    {
        // etc
    }

    // The rest of the loop body runs every time

    // adjust the servo values toward the target values
    // use a counter to determine if to adjust during this loop iteration
    // e.g., a slow speed counts to a higher number before adjusting

    delay(750);

    for(int i = 0; i < NUM_INTERVALS; ++i)
    {
        // decide whether to set pins to 1 or 0 based on the servo values
        delay(INTERVAL);
    }
} 

我不了解您的特定伺服器,但是通常情況下,它們的周期通常是引腳為0的大部分時間,然后是引腳為1的較短時間。您需要調整NUM_INTERVALS和INTERVAL以及750總計正確的時間長度。


此摘要有很多錯誤,很難開始。 很難說出為什么要移動伺服系統,因為每次都只會“移動”到相同的值。 (除非您省略了一些將其設置為其他值的代碼。)

通常,當接收UART時,處理器應等待直到收到字符為止。 這是通過完成

while(UCSRA & (1<<RXC) == 0);

注意; 創建while循環的空主體。 這可能是您的導師的意思。 設置標志后,循環將退出,並且可以讀取數據了。

while(UCSRA & (1<<RXC) == 0);
data = UDR;

接下來,您將看到一個塊,看起來像您打算成為while循環的一部分,但事實並非如此。 循環的主體是上面的單個語句。 每次都會執行該塊。

  {
     if(data=0x0a)
     {
        olddata=data;
        movservo0(90,7); //move servo to certain degree
      }
  }

另一個錯誤是if語句中的條件。 似乎您正在嘗試測試data是否為0x0A,但這不是正在發生的情況。 而是將data設置為0x0A,然后每次執行內部部分。 您可能想要的條件是if(data == 0x0A) 注意==而不是=

所以你的代碼相當於

while(1)
{
  while(ucsra & (1<<RXC)) data=udr; // maybe read UDR into data

  data=0x0a; // set data anyway

  olddata=data;
  movservo0(90,7); //move servo to certain degree
}

再次,對於跳躍伺服,我懷疑這里省略了一些代碼,每次也會運行。 否則, moveservo()函數本身就有問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM