[英]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.