อะไรเป็นสาเหตุทำให้โปรแกรมไมโครคอนโทรลเลอร์ของ LED หยุดทำงาน


11

ดังนั้นฉันสมบูรณ์และเป็นมือใหม่ในการเขียนโปรแกรม ฉันได้ทำสิ่งพื้นฐานบางอย่างเกี่ยวกับ Arduinos (แท้จริงแล้วเปลี่ยนเป็น LED และแสดงบางอย่างบนจอ LCD) และฉันพยายามสอนตัวเองเกี่ยวกับวิธีการโปรแกรมใน C. ฉันเป็นวิศวกรฮาร์ดแวร์โดยการค้า แต่มันรบกวนจิตใจฉันว่าฉันไม่สามารถ ทำด้านใดด้านหนึ่งของเฟิร์มแวร์ / ซอฟต์แวร์และไม่มีหลักสูตรภาคค่ำที่จะสอนมันและฉันต้องการที่จะเลือกอาชีพของฉันต่อไป ฉันพยายามที่จะเข้าใจว่าคำสั่งเหล่านี้ทำงานร่วมกันได้อย่างไรและพบปัญหาที่ฉันไม่สามารถเข้าใจได้ว่าทำไมมันถึงไม่ทำงาน

ดังนั้นฉันมีอินพุตและเอาต์พุต เอาท์พุทของฉันคือการสลับประตูของ FET ซึ่งเปิดไฟ LED อินพุตมาจากประตู AND ดังนั้นไฟ LED ของฉันจะเปิดอยู่เสมอและเมื่อฉันได้รับสัญญาณอินพุตจากประตูเกต (พบเงื่อนไข 2 ข้อ) ฉันต้องการเอาท์พุท (LED สลับ) ไปที่ LOW (ปิดไฟ LED ขณะที่เอาต์พุตยังเชื่อมต่อกับ หนึ่งในช่องสัญญาณ AND จะทำให้สัญญาณอินพุตต่ำ

สิ่งที่ฉันต้องการจะทำ: ฉันแค่ต้องการอ่านอินพุตเป็น 'เงื่อนไขตรงตาม' และปิดไฟ LED ควรปิดเป็นเวลา 1 วินาทีแล้วเปิดใหม่ หากอินพุตไปที่ HIGH อีกครั้งกระบวนการจะทำซ้ำ ฉันใช้การกดอย่างง่ายเพื่อให้สวิตช์เป็นอินพุต AND gate อื่นและวัดว่าเอาต์พุต (อินพุต MCU) สูงขึ้นเมื่อกดปุ่ม แต่สลับ LED (เอาท์พุท) จะไม่ปิด รหัสของฉันคือ (ฉันคิดว่า) เป็นเรื่องง่ายมาก แต่ชัดเจนฉันไม่เข้าใจบางสิ่งบางอย่างอย่างถูกต้อง

นี่คือรหัสที่ฉันใช้:

#include "mbed.h"

DigitalIn ip(D7);
DigitalOut op(D8);

int main() {
    if (ip == 1){
        op = 0;
        wait (1.0);
        op = 1;
    }else{
        op = 1;
    }
}

และสำหรับฉันดูเหมือนว่ามีเหตุผล ในสถานะปกติผลลัพธ์คือ HIGH หากอินพุตได้รับสัญญาณจากประตู AND ไฟ LED จะดับลง 1 วินาทีจากนั้นเปิดอีกครั้ง

ฉันทำอะไรผิดเพราะดูเหมือนเป็นวิธีที่สมเหตุสมผลและฉันก็ไม่เข้าใจว่าทำไมมันถึงไม่ทำงาน

ถ้ามันช่วยได้ฉันกำลังใช้ Nucleo F103RB เมื่อฉันใช้รหัส 'กะพริบ' และเพียงแค่สลับ LED เปิดและปิดเช่นนั้นมันทำงานได้ดีมันก็แค่เมื่อฉันเพิ่มคำสั่ง 'ถ้า' ว่ามันผิดไป

นี่คือวงจรที่ง่ายขึ้น:

แผนผัง

จำลองวงจรนี้ - แผนผังที่สร้างโดยใช้CircuitLab

PS ฉันรู้ว่าฉันไม่ได้เพิ่มพวกเขาในแผนผัง แต่และประตูจะมีตัวต้านทานแบบเลื่อนลงบนอินพุตและเอาต์พุต


มันใช้งานได้ถ้าคุณใส่ "เงื่อนไขตรง" เข้าโดยตรงใน
ทรานซิสเตอร์

มันไม่ใช่. ฉันติดปุ่มไปที่ IN และยังใช้งานไม่ได้
Curious

1
เป็นความคิดที่ดีที่จะทำเครื่องหมายตัวแปรอินพุตเป็นความผันผวนหรือคอมไพเลอร์อาจทำการปรับให้เหมาะสมแปลก ๆ โดยสมมติว่าไม่มีการเปลี่ยนแปลงจากภายนอกโค้ด
Dirk Bruere

3
@DirkBruere: คุณหวังว่าคำนิยามของอยู่แล้วรวมถึงDigitalIn volatile
MSalters

3
ขอคำแนะนำในครั้งต่อไป: ลองกดปุ่มค้างไว้เมื่อคุณเปิด (หรือรีเซ็ต) CPU (หรือไมโครคอนโทรลเลอร์) ตอนนี้สิ่งที่เกิดขึ้น?
CVn

คำตอบ:


26

ฉันคิดว่าคุณจะต้องวนรอบรหัสของคุณ -

while(1)
{

    if (ip == 1){
       op = 0;
       wait (1.0);
       op = 1;}
    else {
       op = 1;}
}

ก่อนที่คุณจะมีโอกาสกดปุ่มรหัสของคุณจะเสร็จสิ้นและออก คุณต้องใช้ขณะที่เพื่อให้คำสั่ง if ทำงานซ้ำ ๆ


อะไรที่ทำให้ฉันแตกต่าง ฉันเห็น 'ขณะ' แต่ทำอะไรได้บ้าง ขอโทษสำหรับคำถามทั้งหมด แต่ฉันเริ่มต้นจากศูนย์ความรู้จริง ๆ !
อยากรู้อยากเห็น

1
@curious ก่อนที่คุณจะมีโอกาสกดปุ่มรหัสของคุณจะเสร็จสิ้นและออก คุณต้องใช้ขณะที่เพื่อให้คำสั่ง if ทำงานซ้ำ ๆ โดยปกติจะเป็นกรณีนี้เว้นแต่มีบางสิ่งที่แตกต่างเกี่ยวกับไมโครคอนโทรลเลอร์ที่คุณกำลังเขียนโปรแกรมอยู่
HandyHowie

9
"คุณช่วยอธิบายได้ไหมว่าทำไมมันถึงทำงานได้" - ทุกอย่างในขณะที่วนซ้ำไปเรื่อย ๆ จนกว่าสภาพจะเปลี่ยนเป็นศูนย์ เงื่อนไขอะไรที่คุณอาจถาม; นั่นคือส่วนหนึ่งในวงเล็บหลังคำว่า "while" -keyword และอย่างที่คุณเห็นเงื่อนไขถูกตั้งค่าเป็น 1 ดังนั้นมันจะไม่เป็นศูนย์และจะถูกทำซ้ำไปเรื่อย ๆ หากไม่มีการวนลูปในขณะที่รหัสจะถูกดำเนินการเพียงครั้งเดียวและหลังจากที่ซอฟต์แวร์สิ้นสุดลง แต่ด้วยการวนรอบในขณะที่รหัสจะถูกดำเนินการซ้ำ ๆ จนกว่าคุณจะเปิดฮาร์ดแวร์
2560

14
ข้อผิดพลาดของคุณอาจเกิดจากการไป Arduino เพื่อ mbed ใน Arduino คุณมักจะใส่รหัสใบสมัครของคุณได้ในloop()แต่กรอบ Arduino int main() { setup(); while(1) { loop(); } }เพิ่มรหัสที่ประมาณพฤติกรรมเช่น
ris8_allo_zen0

1
@Currour ขอแสดงความยินดีทำงาน น่าเสียดายที่มันทำงานได้อย่างแม่นยำเพียงครั้งเดียวทันทีที่คุณเปิดเครื่อง อาจใช้เวลาหนึ่งไมโครวินาทีในการทำงานและนั่นก็คือ หากคุณต้องการให้มันตรวจสอบอินพุตและตั้งค่าเอาท์พุทคุณต้องบอกให้มันทำต่อไป "while (some_condition)" ทำงานตราบเท่าที่ "some_condition" เป็นจริงซึ่งในภาษา C หมายถึงไม่เป็นศูนย์ ดังนั้น "ในขณะที่ (1)" จะตรวจสอบอินพุตอย่างต่อเนื่องหรืออย่างน้อยก็ตราบใดที่ยังเปิดอยู่
เกรแฮม

21
#include "mbed.h"

DigitalIn ip(D7);
DigitalOut op(D8);

int main() {
    if (ip == 1){
        op = 0;
        wait (1.0);
        op = 1;
    }else{
        op = 1;
    }
    // and now the program ends? What to do?
}

หน่วยประมวลผลดำเนินการคำแนะนำตามลำดับ มันเริ่มต้นด้วยการกระโดดไปmain()จากภายในรหัส initialisation mbed ห้องสมุดและDigitalIn จากนั้นทำการเปรียบเทียบเรียกใช้คำสั่งภายในและจากนั้นสิ้นสุด ... ไม่มีคำแนะนำเพิ่มเติม ... มันทำอะไรได้บ้างDigitalOut
ip == 0{}main()

มันสามารถรีเซ็ตเนื่องจากการค้นหาตัวถูกดำเนินการที่ผิดกฎหมายในหน่วยความจำแฟลชที่ว่างเปล่า หรือมันจะแขวนในตัวจัดการความผิดและกระพริบ SOS เหมือน mbeds ทำ ขึ้นอยู่กับวิธีการนำไปใช้และอาจจะเกินกว่าคุณในขณะนี้
แต่ถ้าคุณอยากรู้ว่าคุณสามารถค้นคว้าการจัดการความผิดของ ARM หรือค้นหาว่าmain()มีการเรียกจากที่ใด

ตอนนี้จะแก้ไขได้อย่างไร

int main() {
    // Add a while(1) infinite loop
    while(1){
        if (ip == 1){
            op = 0;
            wait (1.0);
            op = 1;
        }else{
            op = 1;
        }
    }
    // Program never gets here
}

ขอบคุณมากสำหรับคำอธิบาย ขณะที่ลูปเปิดใช้งานเพื่อให้ทำงานได้ น่าเสียดายที่ฉันไม่สามารถให้ +1 แก่คุณได้เนื่องจากตัวแทนของฉันต่ำเกินไป แต่ฉันซาบซึ้งกับคำตอบและคำอธิบายมาก
Curious

Aha! การ upvote ที่สามในคำถามของฉันให้ฉันโหวตคำตอบของคุณ! ขอขอบคุณอีกครั้ง
อยากรู้อยากเห็น

1
@Curious หากคุณต้องการนี้เป็นที่ชัดเจนกับคุณโปรแกรมเมอร์ที่คุณสามารถเขียนสิ่งที่ต้องการแทนเพียงwhile(1 == 1) while(1)หลังคือสำนวน C แต่ในอดีตนั้นชัดเจนกว่าสำหรับมนุษย์ในฐานะ "มักจะประเมินความจริง" คอมไพเลอร์ที่ดีควรสร้างรหัสไบนารี่เดียวกันสำหรับตัวแปรทั้งสอง
CVn

2
@ MichaelKjörlingฉันจะไม่เห็นด้วยกับมนุษย์ เช่นเดียวกับที่สมองของคุณอ่านคำตามรูปร่างของพวกเขาแทนที่จะเป็นตัวละครไปยังโปรแกรมเมอร์ที่มีประสบการณ์ ด้วยการย้ายออกจากโครงสร้างที่ใช้สำนวนคุณบังคับให้ผู้คนมีส่วนร่วมกับรหัสของคุณในระดับที่ต่ำกว่าที่จำเป็นสำหรับความเข้าใจ ซึ่งเหนือรหัสฐานขนาดใหญ่เพิ่มขึ้นถึงงานจิตที่ไม่จำเป็น
Chuu

1
@Chuu "โดยมนุษย์ [ผู้ไม่ได้เป็นโปรแกรมเมอร์ที่มีประสบการณ์]"
user253751

2

ตามที่ผู้อื่นพูดถึงอย่างถูกต้องการวนซ้ำจะทำให้โค้ดของคุณทำงานซ้ำ ๆ อย่างไรก็ตามมีวิธีการในการทำเช่นนี้สำหรับ Arduino โดยไม่จำเป็นต้องwhileวนซ้ำ สิ่งนี้ทำโดยloopฟังก์ชั่น - การบังคับใช้กับปัญหาของคุณขึ้นอยู่กับว่าคุณใช้ Arduino IDE

ควรมีลักษณะดังนี้:

#include "mbed.h"

DigitalIn ip(D7);
DigitalOut op(D8);

void setup() {
    // any code before loop is run
}

void loop() {
    if (ip == 1){
        op = 0;
        wait (1.0);
        op = 1;
    }else{
        op = 1;
    }
}

ฟังก์ชั่นหลักของคุณถูกซ่อนอยู่และถูกเพิ่มลงในโปรแกรมของคุณเมื่อรวบรวม นี่คือการอภิปรายที่ดีเกี่ยวกับเรื่องนี้: http://forum.arduino.cc/index.php?topic=379368.0


ใช่. ตอนแรกฉันทำสิ่งต่าง ๆ บนอาร์ดิโนรวมถึงสิ่งนี้ดังนั้นเมื่อเปลี่ยนเป็นนิวเคลียสและ mbed IDE ฉันไม่เข้าใจว่าทำไมมันไม่ทำงาน!
อยากรู้อยากเห็น

1
คำตอบนี้ขึ้นอยู่กับการใช้ระบบ Arduino mbed เป็นระบบ / ชุดของไลบรารีที่แตกต่างกันloop()และsetup()ฟังก์ชั่นจาก Arduino ไม่ได้ใช้ในระบบส่วนใหญ่ สำหรับการอ้างอิง Arduino เพียงกำหนดmain()สิ่งนี้:void setup(); void loop(); int main() { setup(); while (true) loop(); }
Cameron Tacklind

0

หากคุณคุ้นเคยกับการชุมนุมสิ่งนี้อาจเพิ่มความสะดวกสบายของคุณได้อีกเล็กน้อย:

int main () {

//A label or function similar to assembly

label:

    if (ip == 1){

        op = 0;

        wait (1.0);

        op = 1;

    }else{

        op = 1;

    }

// Goto used same as "jmp" in assembly

goto label;

// Program never gets here

}


3
โปรดอย่าใช้ gotoในภาษาใด ๆ ข้างต้นการชุมนุม
Jeroen3

ฉันไม่คุ้นเคยกับการชุมนุมฉันกลัว!
อยากรู้อยากเห็น

ฉันรู้ แต่มันเกี่ยวกับมัน!
อยากรู้อยากเห็น

@ Jeroen3 คำถามที่คุณเชื่อมโยงไปถึงได้รับคำตอบด้วย "goto's เหมาะสมในบางสถานที่", "ไม่มีอะไรผิดพลาดกับ goto หากใช้อย่างถูกต้อง" และ "ไม่มีอะไรผิดปกติกับ goto ในตัวเอง" ฉันยอมรับว่าในภาษาที่มีข้อยกเว้น goto ฟุ่มเฟือย แต่โดยเฉพาะอย่างยิ่งใน C มันมีประโยชน์
glglgl

@glglgl: ตามที่ Chuu กล่าวไว้ข้างต้นรหัสควรอ่านได้ goto** ขอ ** แสดงให้เห็น "ความมหัศจรรย์เกิดขึ้นที่นี่" goto cleanup;อาจจะมีข้อยกเว้นของ ในตัวอย่างที่นี่ผู้อ่านจะถูกทิ้งไว้กับคำถามที่ทำให้งง "มีอะไรพิเศษที่คุณไม่ได้ใช้while(1) { }ที่นี่ ???"
MSalters
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.