ดังนั้น คุณโหลด STM32duino Bootloader ใน "Blue Pill" ของคุณแล้วตอนนี้ล่ะ: 7 ขั้นตอน
ดังนั้น คุณโหลด STM32duino Bootloader ใน "Blue Pill" ของคุณแล้วตอนนี้ล่ะ: 7 ขั้นตอน
ดังนั้น คุณโหลด 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 และให้ความกระจ่างแก่คุณว่าโค้ดที่ถูกต้องสำหรับกระดานเล็กๆ นี้เป็นอย่างไร

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

แนะนำ: