สารบัญ:

ดังนั้น คุณโหลด STM32duino Bootloader ใน "Blue Pill" ของคุณแล้วตอนนี้ล่ะ: 7 ขั้นตอน
ดังนั้น คุณโหลด STM32duino Bootloader ใน "Blue Pill" ของคุณแล้วตอนนี้ล่ะ: 7 ขั้นตอน

วีดีโอ: ดังนั้น คุณโหลด STM32duino Bootloader ใน "Blue Pill" ของคุณแล้วตอนนี้ล่ะ: 7 ขั้นตอน

วีดีโอ: ดังนั้น คุณโหลด STM32duino Bootloader ใน
วีดีโอ: การเขียนโปรแกรม STM32 Blue Pill ด้วย LDmicro PLC Ladder Logic 2024, กรกฎาคม
Anonim
ดังนั้น คุณโหลด STM32duino Bootloader ใน Your
ดังนั้น คุณโหลด STM32duino Bootloader ใน Your
ดังนั้น คุณโหลด STM32duino Bootloader ใน Your
ดังนั้น คุณโหลด STM32duino Bootloader ใน Your

หากคุณอ่านคำแนะนำของฉันแล้วอธิบายว่าโหลด STM32duino bootloader หรือเอกสารอื่นใดที่คล้ายคลึงกันอย่างไร คุณลองโหลดตัวอย่างโค้ดและ….อาจจะไม่มีอะไรเกิดขึ้นเลย

ปัญหาคือ หลายๆ ตัวอย่างสำหรับ "Generic" STM32 ทั้งหมดจะไม่ทำงานนอกกรอบ จำเป็นต้องเปลี่ยนแปลงเล็กน้อยเพื่อให้ทำงานในบอร์ด "ยาสีน้ำเงิน" ของ STM32

ฉันจะเลือกตัวอย่างโค้ด 4 ตัวอย่างเพื่ออธิบายว่าต้องเปลี่ยนอะไรและทำไม รหัสคือ: "BlinkWithoutDelay", "Fading", "Dimmer" และ "AnalogInSerial"

หมายเหตุ ฉันไม่ได้เข้ารหัสอะไรเลย ฉันเพิ่งออกการเปลี่ยนแปลงเล็กน้อยในรหัสที่สร้างโดย:

David A. Mellis และดัดแปลงโดย Tom Igoe, Marti Bolivar และบางกรณีโดย Scott Fitzgerald

Tom Igoe และสายแก้ไขโดย Bryan Newbold

ดังนั้น ฉันชอบเก็บชื่อผู้แต่งไว้แม้ในรหัสที่ฉันแก้ไข โดยคงเครดิตการสร้างไว้

ขั้นตอนที่ 1: พินและพิน….ทำไมรหัสถึงใช้งานไม่ได้

พินและพิน….ทำไมรหัสถึงใช้งานไม่ได้
พินและพิน….ทำไมรหัสถึงใช้งานไม่ได้

ให้ดูในพิน STM32 "Blue Pill" หมุดโน้ตถูกระบุว่าเป็น PA1 หรือ PC2 …. บางอย่างเช่นนั้น

หากคุณดูในตัวอย่างโค้ด "BlinkWithoutDelay" หมุดจะถูกประกาศเป็น "33"….ทำไม?

ฉันสงสัยว่าเป็นเพราะคุณ Marti Bolivar ย้ายรหัสนี้สำหรับบอร์ด MAPLE

ฉันคิดว่าไม่ใช่ความตั้งใจของเขาที่จะให้รหัสเข้ากันได้กับกระดาน "Blue Pill"

หมุดมินิบอร์ดของ Maple และ Maple เป็นตัวเลขที่ประกาศเช่น Arduino แม้ว่าจะใช้ตัวเลขเช่น 33, 24 และบางส่วนเช่นนี้

ฉันบอกว่ารหัสไม่ทำงาน? ความผิดพลาดของฉัน. คอมไพล์โค้ดโดยไม่มีข้อผิดพลาดและอัปโหลดไปยัง "Blue Pill" อย่างถูกต้อง ดังนั้นจึงเป็นความเห็นของฉันที่ใช้งานได้จริง แต่เราไม่คาดหวังการใช้เอาต์พุต GPIO อาจจะใช้ไม่ได้ด้วยซ้ำ

ดังนั้นการเปลี่ยนแปลงเล็กน้อยจึงมีความจำเป็นในโค้ดเพื่อให้ทำงานได้ตามที่คาดไว้

ขั้นตอนที่ 2: มา "กำหนด" พินกัน…

Let's
Let's

เป็นแนวทางปฏิบัติที่ดีในการประกาศทรัพยากรว่าระบุหรือหมายถึงตัวแปรหรือค่าคงที่ได้ง่าย มันจะช่วยให้คุณเขียนโค้ดได้ง่ายขึ้นเพื่อทำความเข้าใจและแก้ไขปัญหา

ฉันใช้ประกาศพิน Arduino เช่นนี้:

const int ledPin =13;

…"

ถ้าคุณชอบฉัน คุณอาจจะถามตัวเองว่า "ฉันจะประกาศหมุดที่มีชื่อเหมือน PC13 ได้อย่างไร"

คำตอบคือ: ใช้คำสั่ง "#define" C

ดังนั้น จากการดึงพินออก PC13 คือพินที่เรามี LED บนบอร์ดใน "BluePill" ในการใช้งาน ฉันจะประกาศแบบนี้หลังจากนิยามไลบรารี่ (#include…) และก่อนสิ่งอื่นใด:

#define LedPin PC13

…"

โปรดทราบว่าไม่มี ";" การยกเลิกบรรทัด NOR "=" การมอบหมาย

เปรียบเทียบทั้งสองรหัส หนึ่งคือตัวอย่างดั้งเดิมที่โหลดจาก IDE ประการที่สองคือสิ่งที่ฉันปรับให้ทำงานกับ "BluePill"

ฉันขอแนะนำอย่างยิ่งให้ประกาศพินทั้งหมดที่คุณต้องการใช้ในโค้ด แม้แต่ผู้ที่ตั้งใจจะใช้เป็นอินพุต ADC (เพิ่มเติมเกี่ยวกับเรื่องนี้ในภายหลัง)

นี้จะทำให้ชีวิตของคุณง่าย

ขั้นตอนที่ 3: PinMode()…คุณจะใช้พินของคุณอย่างไร…

ก่อนดำเนินการต่อ มาทำความเข้าใจฟังก์ชัน PinMode()

เช่นเดียวกับ Arduino พิน STM32 มีหลายฟังก์ชัน วิธีที่ง่ายที่สุดในการเลือกอย่างใดอย่างหนึ่งคือการใช้คำสั่ง pinMode()

Arduino มีเพียง 3 โหมดเท่านั้นคือ INPUT, OUTPUT หรือ INPUT_PULLUP

ในทางกลับกัน STM32 มี pinMode() หลายรสชาติ พวกเขาคือ:

OUTPUT -เอาต์พุตดิจิตอลพื้นฐาน: เมื่อพินสูง แรงดันไฟฟ้าจะอยู่ที่ +3.3v (Vcc) และเมื่อต่ำ พินจะถูกดึงลงมาที่พื้น

OUTPUT_OPEN_DRAIN - ในโหมด open drain หมุดระบุว่า "ต่ำ" โดยยอมรับกระแสไหลลงสู่พื้นและ "สูง" โดยเพิ่มอิมพีแดนซ์

INPUT_ANALOG -โหมดนี้เป็นโหมดพิเศษเมื่อจะใช้พินสำหรับการอ่านแบบอะนาล็อก (ไม่ใช่แบบดิจิทัล) เปิดใช้งานการแปลง ADC กับแรงดันไฟฟ้าที่พิน

INPUT_PULLUP - สถานะของพินในโหมดนี้มีการรายงานในลักษณะเดียวกับ INPUT แต่แรงดันพินจะถูก “ดึงขึ้น” ไปทาง +3.3v อย่างนุ่มนวล

INPUT_PULLDOWN - สถานะของพินในโหมดนี้มีการรายงานในลักษณะเดียวกับ INPUT แต่แรงดันพินจะถูก "ดึงลง" เบาๆ ไปที่ 0v

INPUT_FLOATING -คำพ้องความหมายสำหรับ INPUT

PWM -โหมดนี้เป็นโหมดพิเศษเมื่อจะใช้พินสำหรับเอาต์พุต PWM (กรณีพิเศษของเอาต์พุตดิจิทัล)

PWM_OPEN_DRAIN -เช่นเดียวกับ PWM ยกเว้นว่าแทนที่จะสลับรอบ LOW และ HIGH แรงดันไฟฟ้าบนพินประกอบด้วยรอบการสลับ LOW และลอย (ตัดการเชื่อมต่อ)

(หมายเหตุ: ดึงมาจาก

ฉันเพิ่งเปิดวงเล็บนี้เพราะเมื่อคุณเริ่มสร้างโค้ดของคุณเอง โปรดใช้ความระมัดระวังในการใช้ pinMode() ที่ถูกต้องสำหรับความต้องการของคุณ

ขั้นตอนที่ 4: AnalogWrite () กับ PwmWrite ()…เอาต์พุตแบบอะนาล็อกใน 2 รสชาติ

AnalogWrite() กับ PwmWrite()…เอาต์พุตแบบอะนาล็อกใน 2 รสชาติ
AnalogWrite() กับ PwmWrite()…เอาต์พุตแบบอะนาล็อกใน 2 รสชาติ
AnalogWrite() กับ PwmWrite()…เอาต์พุตแบบอะนาล็อกใน 2 รสชาติ
AnalogWrite() กับ PwmWrite()…เอาต์พุตแบบอะนาล็อกใน 2 รสชาติ

ก่อนใช้หมุด GPIO "Blue Pill" จำเป็นต้องประกาศพฤติกรรมเช่นวิธีการทำงาน นั่นคือสิ่งที่ฟังก์ชัน pinMode() ทำ

ดังนั้น เรามาโฟกัสกันถึงวิธีการตั้งค่าเอาต์พุตแอนะล็อกให้ถูกต้อง สามารถประกาศเป็นโหมด OUTPUT หรือโหมด PWM

ในทำนองเดียวกัน ค่าแอนะล็อกสามารถระบุแอตทริบิวต์ของ GPIO ได้ 2 วิธี: analogWrite() หรือ pwmWrite(), แต่, analogWrite() จะใช้งานได้ก็ต่อเมื่อ pinMode()= OUTPUT ในทางกลับกัน pwmWrite() จะใช้งานได้ก็ต่อเมื่อ pinMode()=PWM

ลองใช้ PA0 ตัวอย่างเช่น: มันเป็นตัวเลือกเอาต์พุตแอนะล็อก/pwm

analogWrite(): สิ่งนี้ประกาศด้วยวิธีนี้:

….

#define ledPin PA0

โหมดพิน (ledPin, เอาต์พุต);

analogWrite (ledPin, <จำนวน>);

……"

โดยที่ตัวเลขต้องอยู่ระหว่าง 0 ถึง 255 เช่น Arduino อันที่จริงมันเข้ากันได้กับ Arduino รุ่นเก่า

pwmWrite(): ประกาศด้วยวิธีนี้:

#define ledPin PA0

โหมดพิน (ledPin, PWM);

pwmWrite(ledPin, <หมายเลข>);

…."

โดยที่ตัวเลขต้องอยู่ระหว่าง 0 ~ 65535 ความละเอียดสูงกว่า Arduino มาก

ในภาพสามารถเปรียบเทียบระหว่าง 2 รหัส คุณยังสามารถดูรหัสต้นฉบับได้

ขั้นตอนที่ 5: การสื่อสารแบบอนุกรม STM32

การสื่อสารแบบอนุกรม STM32
การสื่อสารแบบอนุกรม STM32

เรามาดูกันว่ามีการจัดเรียงอินเตอร์เฟส USART ใน STM32 อย่างไร ใช่ อินเตอร์เฟสเป็นพหูพจน์…..

"Blue Pill" มี 3 USART (RX/ TX 1~3) และหากคุณใช้ bootloader อนุญาตให้คุณใช้ USB อุปกรณ์นั้นจะไม่ได้เชื่อมต่อกับสิ่งใด

ขึ้นอยู่กับว่าคุณใช้หรือไม่ใช้ USB คุณต้องประกาศพอร์ตอนุกรมไม่ทางใดก็ทางหนึ่งในรหัสของคุณ

กรณีที่ 1: การใช้ USB:

ด้วยวิธีนี้ สเก็ตช์จะถูกดาวน์โหลดโดยตรงผ่าน USB ไม่จำเป็นต้องย้ายจัมเปอร์ BOOT0 ไปที่ 1 ตำแหน่งและกลับไปที่ 0

ในกรณีนี้ ทุกครั้งที่คุณประกาศ "ซีเรียล" โดยไม่มีดัชนี หมายถึงการสื่อสารผ่าน USB

ดังนั้น Serial1 หมายถึง TX/ RX 1 (พิน PA9 และ PA10); Serial2 หมายถึง TX/ RX 2 (พิน PA2 และ PA3) และ Serial 3 หมายถึง TX/ RX 3 (พิน PA10 และ PA11)

นี่คือวิธีที่เราทำงานด้วย ฉันจะนำเสนอการเปลี่ยนแปลงในตัวอย่างสำหรับวิธีการเขียนโค้ดนี้

อีกสิ่งหนึ่ง: "Serial USB" ไม่จำเป็นต้องเริ่มต้น กล่าวอีกนัยหนึ่ง "…Serial.begin(15200);" ไม่จำเป็น.

เป็นไปได้ที่จะเรียกใช้ฟังก์ชัน Serial ใดๆ (Serial.read(), Serial.write() เป็นต้น) โดยไม่ต้องเริ่มต้นใดๆ

หากมีอยู่ในโค้ดด้วยเหตุผลบางประการ คอมไพเลอร์จะไม่สนใจมัน

กรณีที่ 2: การใช้ TTL ซีเรียลกับอะแดปเตอร์ USB:

ด้วยวิธีนี้ bootloader จึงไม่รองรับการสื่อสารแบบ Native STM32 USB ดังนั้นคุณต้องใช้ USB กับอะแดปเตอร์อนุกรมที่เชื่อมต่อกับ TX/ RX 1 (พิน PA9 และ PA10) เพื่ออัปโหลดสเก็ตช์

ในกรณีนี้ เมื่อใดก็ตามที่ "ซีเรียล" ที่ไม่มีดัชนีคือโค้ด หมายถึง TX/ RX1 (พอร์ตที่ใช้ในการอัปโหลดโค้ด) ดังนั้น Serial1 หมายถึง TX/ RX 2 (พิน PA2 และ PA3) และ Serial2 หมายถึง TX/ RX 3 (พิน PA10 และ PA11) ไม่มี Serial3

ขั้นตอนที่ 6: การส่งค่าไปยังไมโครคอนโทรลเลอร์

การส่งค่าไปยังไมโครคอนโทรลเลอร์
การส่งค่าไปยังไมโครคอนโทรลเลอร์

ตัวอย่าง Dimmer เป็นวิธีที่ง่ายในการแสดงวิธีการส่งค่าไปยังไมโครคอนโทรลเลอร์

มันควรจะส่งค่าจาก 0 ถึง 255 เพื่อควบคุมความสว่างของ LED

มันจะไม่ทำงานตามที่คาดไว้ใน Blue Pill เนื่องจาก:

  1. ในการใช้ฟังก์ชัน pwmWrite() ต้องประกาศ pinMode() เป็นโหมด PWM
  2. คุณจะไม่ได้รับตัวเลข 3 หลักทั้งหมด ฟังก์ชัน Serial.read() จับเฉพาะเนื้อหาบัฟเฟอร์ ซึ่งก็คือ "BYTE" หากคุณพิมพ์ "100" และกด "Enter" เฉพาะ "0" สุดท้ายเท่านั้นที่จะถูกดักจับจากบัฟเฟอร์ และค่าของมันจะเป็น "48" (ค่า ASCII ทศนิยมสำหรับ "0") หากต้องการออกค่า "100" ให้พิมพ์ "d" ดังนั้นจึงถูกต้องที่จะบอกว่ามันจะแปลงค่าทศนิยมของสัญลักษณ์ ASCII เป็นความสว่าง LED ใช่ไหม….เอ่อ…
  3. ปัญหา ค่าแผนที่โดยตรงจากฟังก์ชัน Serial.read() เป็นการหลอกลวง มันเกือบจะได้รับค่าที่ไม่คาดคิด วิธีที่ดีกว่าคือเนื้อหาบัฟเฟอร์หน่วยเก็บข้อมูลในตัวแปรชั่วคราวและ THAN แมป

เช่นเดียวกับที่ฉันอธิบายก่อนหน้านี้ในข้อ 2 รหัสที่ฉันแนะนำการเปลี่ยนแปลงจะอนุญาตให้ป้อนสัญลักษณ์ ASCII และจะควบคุมความสว่างของ LED ตามค่าทศนิยม ASCII…ตัวอย่างเช่น "ช่องว่าง" คือค่า 32 (จริง ๆ แล้วเป็นอักขระที่พิมพ์ได้ต่ำสุดที่คุณสามารถป้อนได้) และ "}" เป็นค่าสูงสุดที่เป็นไปได้ (ค่า 126) อักขระอื่นไม่สามารถพิมพ์ได้ ดังนั้นเทอร์มินัลจะไม่เข้าใจหรือเป็นไปได้ว่าอักขระผสม (เช่น "~" เป็นคีย์ที่ไม่ทำงานในแป้นพิมพ์ของฉันและจะทำงานไม่ถูกต้อง) ซึ่งหมายความว่า อักขระผสมนี้ เมื่อเข้าสู่เทอร์มินัล จะส่งอักขระเองและอย่างอื่น ปกติพิมพ์ไม่ได้ และรหัสสุดท้ายนี้จะถูกดักจับหรือไม่ นอกจากนี้ โปรดทราบว่าเทอร์มินัลของคุณ ในกรณีนี้ ไม่ควรส่ง "Carriage Return" หรือ "Line Feed" คุณต้องใส่ใจกับสิ่งนี้เพื่อให้โค้ดทำงานได้อย่างถูกต้อง

หากล้มลงจะสับสนเล็กน้อย เลวร้ายที่สุด…..

ขั้นตอนที่ 7: และถ้าฉันต้องการพิมพ์สามหลัก…. หรือมากกว่านั้น??

และถ้าฉันอยากจะพิมพ์สามหลัก…. หรือมากกว่านั้น??
และถ้าฉันอยากจะพิมพ์สามหลัก…. หรือมากกว่านั้น??

รับอักขระหลายตัวจากการสื่อสารแบบอนุกรมไม่ใช่เรื่องง่าย

บัฟเฟอร์อนุกรมคือกองอักขระไบต์ FIFO ทุกครั้งที่มีการเรียกใช้ฟังก์ชัน Serial.read() ถ่านตัวแรกที่ส่งจะถูกลบออกจากกองและเก็บไว้ในที่อื่น โดยปกติแล้วจะเป็นตัวแปรถ่านในโค้ด หมายเหตุ ขึ้นอยู่กับฮาร์ดแวร์ โดยปกติจะมีระยะหมดเวลาสำหรับวิธีที่บัฟเฟอร์บันทึกสามารถเก็บข้อมูลได้

หากคุณต้องการป้อนตัวเลขมากกว่าหนึ่งหลักผ่านซีเรียล คุณจะต้อง "เขียน" อักขระสตริงทีละอักขระ เนื่องจากจะเข้าสู่บัฟเฟอร์ UART

นี่หมายถึงการวนซ้ำอ่านบัฟเฟอร์แต่ละอัน เก็บไว้ในตัวแปร temp โหลดในตำแหน่งแรกของสตริงอาร์เรย์ ย้ายไปยังตำแหน่งถัดไปและเริ่มต้นใหม่ จนกระทั่ง… แล้วแต่แอปพลิเคชัน มี 2 วิธีในการสิ้นสุดรอบ:

  1. ใช้อักขระ "end mark" เช่น "carriage Return" หรือ "Line Feed" ทันทีที่พบถ่าน "end Mark" การวนซ้ำจะสิ้นสุดลง
  2. อีกทางหนึ่ง จำนวนของอักขระในสายโซ่สตริงสามารถถูกจำกัดได้ เช่นเดียวกับจำนวนรอบการโต้ตอบ เมื่อถึงขีด จำกัด สมมติว่า 4 รับกิจวัตรประจำวันด้วยตัวเอง

มาดูตัวอย่างง่ายๆ ว่าทำอย่างไร:

  • ตั้งค่าอักขระ "สิ้นสุด" เช่น '\n' (นี่หมายถึงการป้อนบรรทัด ASCII ถ่าน)
  • วนซ้ำในขณะที่ Serial.available() เป็นจริง
  • การจัดเก็บ Serial.read() ส่งผลให้ตัวแปรถ่านชั่วคราว ข้อควรจำ: ทันทีที่ Serial.read() บัฟเฟอร์ "อ่าน" จริง ๆ มันก็สะอาดและโหลดอักขระตัวต่อไปในนั้น
  • เพิ่มตัวแปรสตริงด้วย char. นี้
  • หากอักขระตัวสุดท้ายคือ "สิ้นสุด" ให้ออกจากลูป

โดยปกติรูทีนสำหรับรับอาร์เรย์อักขระแบบอนุกรมจะดูเหมือนรูปภาพ

มีพื้นฐานมาจากการดัดแปลงโค้ดต้นฉบับของ Mr. David A. Mellis อย่างกว้างขวาง

ใช้งานและทดลองใช้งานได้ฟรี ข้อควรจำ: ค่าต้องป้อนในรูปแบบ 3 หลัก

นี้สำหรับตอนนี้ ฉันจะไม่ขยายตัวเองในรายละเอียดการสื่อสารแบบอนุกรมเพิ่มเติม มันซับซ้อนเกินไปที่จะครอบคลุมที่นี่และสมควรได้รับ Intructables ของตัวเอง

ฉันหวังว่ามันจะช่วยให้คุณใช้ตัวอย่างใน Blue Pill และให้ความกระจ่างแก่คุณว่าโค้ดที่ถูกต้องสำหรับกระดานเล็กๆ นี้เป็นอย่างไร

พบคุณในคำแนะนำอื่น ๆ

แนะนำ: