การเชื่อมต่อแป้นพิมพ์ชนิดเมทริกซ์กับไมโครคอนโทรลเลอร์ เอวีอาร์. หลักสูตรการฝึกอบรม ขั้นตอนการสแกนคีย์บอร์ด การมอบหมายงานในห้องปฏิบัติการ

คุณสมบัติที่โดดเด่น:

  • คีย์บอร์ด 64 คีย์ในรูปแบบเมทริกซ์ 8 x 8
  • ไม่จำเป็นต้องใช้ส่วนประกอบภายนอก
  • ออกจากโหมดสลีปโดยการกดปุ่ม
  • บูรณาการกับแอปพลิเคชันอื่นได้ง่าย
  • การบริโภคต่ำ
  • อัลกอริธึมซอฟต์แวร์ป้องกันการตีกลับ
  • รองรับฟังก์ชั่นปุ่มทางเลือกซึ่งสามารถลบออกได้อย่างง่ายดายเพื่อลดขนาดโปรแกรม
  • รหัสโปรแกรมสามารถใช้ได้กับไมโครคอนโทรลเลอร์ AVR ใด ๆ ที่มีพอร์ตอินพุต / เอาท์พุตอย่างน้อย 17 บรรทัดและมีการขัดจังหวะในการเปลี่ยนสถานะของบรรทัด (ปัจจุบันมีเพียง ATmega162 และ ATmega169 เท่านั้น)
  • โค้ดสามารถแก้ไขได้อย่างง่ายดายเพื่อใช้ในไมโครคอนโทรลเลอร์อื่นๆ ที่ใช้การขัดจังหวะทั่วไป (ดูตัวอย่างการใช้งาน "AVR240: ปุ่มกด 4 x 4 - การปลุกเมื่อกดปุ่ม")

การแนะนำ

ใน ในตัวอย่างนี้แอปพลิเคชันอธิบายโปรแกรมไดรเวอร์อินเทอร์เฟซเมทริกซ์แป้นพิมพ์ 8 x 8 ตัวอย่างแอปพลิเคชันได้รับการออกแบบมาเพื่อใช้ในอุปกรณ์ที่ขับเคลื่อนด้วยตนเอง ไมโครคอนโทรลเลอร์ AVR ใช้เวลาส่วนใหญ่ในโหมดสลีป โดยจะทำงานเฉพาะเมื่อกดปุ่มบนคีย์บอร์ดเท่านั้น หลังจากนั้นเมทริกซ์ของแป้นพิมพ์จะถูกสแกนข้อมูลจะถูกประมวลผลและกลับสู่โหมดการบริโภคต่ำ

อุปกรณ์ที่อธิบายในตัวอย่างแอปพลิเคชันนี้ยังรองรับฟังก์ชันอื่นที่ผู้ใช้ตั้งโปรแกรมได้ เช่น แคปล็อค, Ctrl-, Shift- และ Alt- แอปพลิเคชันทดสอบรองรับเมทริกซ์แป้นพิมพ์ขนาด 4 x 4 โดยแต่ละคีย์แทนตัวเลขหนึ่งตัวและสัญลักษณ์สามตัว ปุ่มสำรองทำให้คุณสามารถเลือกฟังก์ชั่นของปุ่มที่คุณกดได้

รูปที่ 1. ทดสอบแอปพลิเคชัน

อุปกรณ์นี้เหมาะสำหรับทุกแอปพลิเคชันที่ใช้แป้นพิมพ์เมทริกซ์ เช่น รีโมทคอนโทรล การควบคุมระยะไกล, โทรศัพท์มือถือและระบบเตือนภัยและระบบควบคุมการเข้าออก อัปเดต ซอฟต์แวร์ทำได้ง่ายมากเนื่องจากมีฟังก์ชันการเขียนโปรแกรมด้วยตนเองและการเขียนโปรแกรมในระบบอยู่ในไมโครคอนโทรลเลอร์ของตระกูล ATmega คุณสมบัติเหล่านี้มีประโยชน์อย่างยิ่งเมื่อใช้ไมโครคอนโทรลเลอร์เหล่านี้ในรีโมทคอนโทรลสากล

อุปกรณ์ที่อธิบายไว้ในตัวอย่างแอปพลิเคชันนี้ใช้ไมโครคอนโทรลเลอร์ ATmega162 อย่างไรก็ตามหลังจากนั้น การเปลี่ยนแปลงเล็กๆ น้อยๆรหัสโปรแกรมสามารถใช้ในไมโครคอนโทรลเลอร์ ATmega169

หลักการทำงาน

การเชื่อมต่อของปุ่มเมทริกซ์แป้นพิมพ์ 8 x 8 จะแสดงในรูปที่ 2 เมื่อคุณกดปุ่ม แถวและคอลัมน์ที่เกี่ยวข้องจะเชื่อมต่อกัน เมื่อคุณคลิกที่ปุ่มซ้ายบน คอลัมน์ซ้ายสุดและแถวบนสุดจะถูกปิด


รูปที่ 2 การเชื่อมต่อเมทริกซ์คีย์บอร์ด

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

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


รูปที่ 3 การถอดรหัสที่ผิดพลาดเมื่อกดปุ่มพร้อมกัน

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

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

ปุ่มทางเลือก

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

ปุ่มสำรองจะถูกนำมาพิจารณาเมื่อมีการกดปุ่มหลักเท่านั้น ในกรณีนี้ ปุ่มทางเลือกจะเรียกว่า "one-shot"

นอกจากนี้ยังสามารถใช้ปุ่ม "ทริกเกอร์" ซึ่งเมื่อกดครั้งแรกจะเปิดใช้งานฟังก์ชันทางเลือก และเมื่อกดอีกครั้งจะปิดใช้งานฟังก์ชันเหล่านั้น ในกรณีนี้ จะมีการใช้ฟังก์ชันทางเลือกสำหรับปุ่มที่กดในภายหลังทั้งหมด ปุ่ม Caps Lock บนปุ่มมาตรฐานมีฟังก์ชันเหล่านี้ แป้นพิมพ์คอมพิวเตอร์- ตัวอย่างการใช้งานนี้ใช้ทั้งปุ่มช็อตเดียวและปุ่มทริกเกอร์

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

ติดต่อเด้ง

รูปที่ 4 แสดงการเด้งของหน้าสัมผัสเมื่อกดปุ่ม อย่างที่คุณเห็น มีการจำลองการคลิกหลายครั้ง เพื่อหลีกเลี่ยงการถอดรหัสที่ไม่ถูกต้อง รหัสสแกนจะถูกอ่านเป็นระยะเวลาหนึ่งหลังจากที่เกิดการเปลี่ยนแปลงสถานะขัดจังหวะ นอกจากนี้ อัลกอริธึมนี้เรียกว่าการป้องกันการตีกลับยังช่วยให้คุณหลีกเลี่ยงการเตือนที่ผิดพลาดเมื่อสัมผัสกับเสียงรบกวน การดีเด้งหน้าสัมผัสสามารถทำได้โดยใช้ฮาร์ดแวร์หรือตัวกรองดิจิทัล แต่วิธีการที่ใช้ในตัวอย่างการใช้งานนี้มีราคาถูกที่สุด


รูปที่ 4 ติดต่อตีกลับ

การนำไปปฏิบัติ

การใช้งานนี้ใช้ไมโครคอนโทรลเลอร์ ATmega162 คำแนะนำสำหรับการอัพเกรดเป็นไมโครคอนโทรลเลอร์ ATmega169 แสดงอยู่ท้ายเอกสารนี้

แป้นพิมพ์เชื่อมต่อกับพอร์ต 8 บิตสองพอร์ตของไมโครคอนโทรลเลอร์ AVR พอร์ตหนึ่งพอร์ต (พอร์ต D) ได้รับการกำหนดค่าให้ใช้งานทุกบรรทัดเป็นเอาต์พุตและเชื่อมต่อกับแถวของเมทริกซ์แป้นพิมพ์ พอร์ตอื่น (พอร์ต C) ได้รับการกำหนดค่าให้ใช้งานทุกบรรทัดเป็นอินพุตและเชื่อมต่อกับคอลัมน์ของเมทริกซ์แป้นพิมพ์ ซึ่งสามารถดูรายละเอียดเพิ่มเติมได้ในรูปที่ 2 เมื่อสแกนเมทริกซ์ของแป้นพิมพ์ พอร์ตที่ใช้เป็นเอาต์พุตจะต้องคงเอาต์พุตไว้ต่ำ และพอร์ตที่ใช้เป็นอินพุตจะต้องมีตัวต้านทานแบบดึงขึ้นกำลังในตัว

อุปกรณ์ที่อธิบายไว้ใช้บรรทัดแรกของพอร์ต E เพื่อสร้างรหัสซีเรียลที่สอดคล้องกับรหัสของปุ่มกด ข้อมูลจะถูกส่งโดยใช้ UART ในตัว การใช้งานตามที่อธิบายไว้ในตัวอย่างแอปพลิเคชัน AVR306

เมื่อกดตามปกติรหัสสแกนจะถูกสร้างขึ้นโดยค่าจะอยู่ในช่วงตั้งแต่ 0 ถึง 63 (8 แถว * 8 คอลัมน์) การกดปุ่มเพื่อเรียกใช้ฟังก์ชันทางเลือกจะสร้างโค้ดสแกนปกติด้วย แต่จะมีการตั้งค่าแฟล็กที่สอดคล้องกันของฟังก์ชันทางเลือกด้วย ค่าสถานะเหล่านี้ถูกเก็บไว้ในตัวแปรส่วนกลาง

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

ตัวแปรส่วนกลางอื่นใช้เพื่อส่งรหัสสแกนพร้อมกับแฟล็กไปยังแอปพลิเคชัน หกบิตที่มีนัยสำคัญน้อยที่สุดใช้ในการส่งรหัส (ตั้งแต่ 0 ถึง 63) และบิตที่สำคัญที่สุด (MSB) บ่งชี้ถึงการเปลี่ยนแปลงในสถานะ ไดรเวอร์แป้นพิมพ์จะตั้งค่าบิตนี้เมื่อกดปุ่ม แอปพลิเคชันจะสำรวจบิตนี้และรีเซ็ตหลังจากอ่านโค้ดสแกนแล้ว ไบต์สากลและคำสแกนแสดงในรูปที่ 5


รูปที่ 5 รหัสสแกนขั้นสูง

โปรแกรมไดรเวอร์แป้นพิมพ์ถูกนำมาใช้เป็นโปรแกรมตัวจัดการการขัดจังหวะ โปรแกรมหลักทำให้ไมโครโปรเซสเซอร์เข้าสู่โหมดสลีป เมื่อกดปุ่ม ไดรเวอร์แป้นพิมพ์จะปลุกไมโครคอนโทรลเลอร์ AVR รับโค้ดสแกนและอัปเดตไบต์ทั่วโลก หลังจากใช้งานฟังก์ชั่นของปุ่มกดแล้วโปรแกรมหลักจะทำให้ไมโครคอนโทรลเลอร์เข้าสู่โหมดสลีปอีกครั้ง

โมดูลการเริ่มต้นและโปรแกรมหลัก

รูปที่ 6 แสดงโมดูลการเริ่มต้นและโปรแกรมหลัก การรีเซ็ตแฟล็กของฟังก์ชันทางเลือกและตัวแปรโกลบอล ตลอดจนการเริ่มต้นพอร์ตมีอธิบายไว้ข้างต้น หากไม่จำเป็นต้องประมวลผล ระบบจะเลือกโหมดสลีปว่าง


รูปที่ 6 โมดูลการเริ่มต้นและโปรแกรมหลัก

โมดูลหลักของตัวถอดรหัสคีย์บอร์ด ตัวถอดรหัสคีย์บอร์ดเป็นรูทีนย่อยการประมวลผลอินเตอร์รัปต์สำหรับการเปลี่ยนสถานะพอร์ต ขั้นแรก ให้เลือกโหมดสลีปว่างเพื่ออนุญาต ไมโครคอนโทรลเลอร์ AVRเปิดใช้งานเมื่อตัวจับเวลาล้นซึ่งเป็นไปไม่ได้เมื่อไมโครคอนโทรลเลอร์อยู่ในโหมดสลีปปิดเครื่อง ตัวจับเวลาถูกตั้งค่าให้สร้างการขัดจังหวะหลังจาก 5 ms ซึ่งเพียงพอสำหรับการยุติกระบวนการชั่วคราวของสัญญาณที่พิน ในระหว่างช่วงเวลาหน่วงนี้ โปรแกรมหลักจะควบคุมได้อีกครั้งและสามารถเปิดใช้งานโหมดสลีปได้ เมื่อสิ้นสุดเวลาหน่วง จะเรียกกระบวนการประมวลผลการกดปุ่ม ฟังก์ชันนี้ทำให้การกำหนดรหัสปุ่มกดเสร็จสมบูรณ์ ในตอนท้ายบรรทัดพอร์ตของทุกบรรทัดจะถูกตั้งค่าไว้ที่ระดับต่ำและเปิดใช้งานโหมดสลีปปิดเครื่องซึ่งสามารถออกได้โดยการกดปุ่ม แผนภาพบล็อกของโมดูลซอฟต์แวร์นี้แสดงในรูปที่ 7

รูปที่ 7 บล็อกไดอะแกรมของโมดูลซอฟต์แวร์หลักของตัวถอดรหัสคีย์บอร์ด

การสแกนแป้นพิมพ์ (การประมวลผลการกดปุ่ม) รูปที่ 8 แสดงบล็อกไดอะแกรมของขั้นตอนการสแกนแป้นพิมพ์ ขั้นแรก ผลลัพธ์จะถูกสแกนทีละคอลัมน์ รหัสสแกน (คอลัมน์) ที่มีนัยสำคัญน้อยที่สุดสามบิตจะเพิ่มขึ้นจนกระทั่งพบระดับต่ำบนบรรทัดคอลัมน์ หลังจากนั้น ทิศทางของเส้นพอร์ตจะกลับด้าน และทำการสแกนซ้ำ ในกรณีนี้ จะทำการค้นหาระดับต่ำบนบรรทัดแถว หลังจากนั้น รูทีนย่อยการประมวลผลโค้ดสแกนจะถูกเรียก


รูปที่ 8 บล็อกไดอะแกรมของขั้นตอนการสแกนแป้นพิมพ์

ขั้นแรก ฟังก์ชันการประมวลผลโค้ดสแกนจะคัดลอกโค้ดสแกนที่สร้างขึ้นไปยังตัวแปรร่วม หลังจากนั้น รหัสสแกนจะถูกเปรียบเทียบกับรหัสของปุ่มของฟังก์ชันทางเลือก และสร้างแฟล็กที่สอดคล้องกันของฟังก์ชันทางเลือก ค่าสถานะเหล่านี้ถูกคัดลอกไปยังตัวแปรส่วนกลาง หากปุ่มกดไม่ใช่ปุ่มทางเลือก ธงของฟังก์ชันทางเลือกแบบช็อตเดียวทั้งหมดจะถูกรีเซ็ต ในที่สุดก็มีการตั้งค่าสถานะใหม่ บล็อกไดอะแกรมของฟังก์ชันนี้แสดงในรูปที่ 9


รูปที่ 9 บล็อกไดอะแกรมของฟังก์ชันการประมวลผลโค้ดสแกน

กรณีทดสอบแอปพลิเคชัน myCellPhone

มีกรณีทดสอบที่ใช้เมทริกซ์แป้นพิมพ์ที่มีลักษณะคล้ายกับแป้นพิมพ์ โทรศัพท์มือถือ- อักขระตัวสุดท้ายในนั้นจะถูกส่งผ่านอินเทอร์เฟซ USART เมื่อใช้เมทริกซ์แป้นพิมพ์ขนาด 4 x 4 คุณสามารถสร้างตัวเลขและสัญลักษณ์ทั้งหมดที่สามารถระบุได้โดยใช้ปุ่มฟังก์ชันทางเลือกเพิ่มเติมอีกสี่ปุ่ม ใช้ปุ่มสามปุ่มเพื่อเลือกฟังก์ชันสำรองสำหรับปุ่มหลักแต่ละปุ่ม และปุ่มที่สี่ทำหน้าที่เป็นปุ่ม Caps Lock (สลับระหว่างตัวพิมพ์ใหญ่และตัวพิมพ์เล็ก)

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

ขนาดรหัส โปรแกรมประยุกต์และพารามิเตอร์เวลา

ขนาดโค้ดรูทีนย่อย ฟังก์ชั่นต่างๆการประมวลผลเมทริกซ์ของแป้นพิมพ์แสดงในตารางที่ 1

ตารางที่ 1. ขนาดของโค้ดรูทีนย่อยสำหรับฟังก์ชันการประมวลผลเมทริกซ์คีย์บอร์ดต่างๆ

ตารางที่ 2 แสดงระยะเวลาของการกระทำต่าง ๆ ที่ทำโดยไมโครคอนโทรลเลอร์ ATmega162 ที่ทำงานที่ความถี่ 8 MHz ต่อไปนี้เป็นลำดับการดำเนินการตั้งแต่ปลุกเมื่อตรวจพบการกดปุ่มเพื่อเข้าสู่โหมดสลีปหลังจากประมวลผลปุ่มกด

ตารางที่ 2. ระยะเวลาของลำดับการกระทำที่ดำเนินการ

หากคุณไม่คำนึงถึงโหมดสลีปปิดเครื่อง คุณจะเห็นว่าส่วนใหญ่ไมโครคอนโทรลเลอร์ทำงานในโหมดสลีปไม่ได้ใช้งาน ไมโครคอนโทรลเลอร์อยู่ในโหมดแอคทีฟเพียง 0.3 มิลลิวินาที ซึ่งคิดเป็นประมาณ 0.5% ของเวลาทั้งหมด เวลาสัมพัทธ์ที่ใช้ในโหมดการทำงานต่างๆ แสดงไว้ในตารางที่ 3

ตารางที่ 3. ปริมาณการใช้และเวลาสัมพัทธ์ที่ใช้โดยไมโครคอนโทรลเลอร์ในโหมดการทำงานต่างๆ

หากเราสมมติว่ามีการกดปุ่มทุกๆ 10 นาที ปริมาณการใช้โดยเฉลี่ยจะอยู่ที่ 2 µA เท่านั้น

การอภิปรายเกี่ยวกับการใช้ไมโครคอนโทรลเลอร์อื่นๆ

ข้อแตกต่างเพียงอย่างเดียวเมื่อใช้ไมโครคอนโทรลเลอร์ ATmega162 และ ATmega169 คือต้องใช้พอร์ตที่แตกต่างกันเพื่อเชื่อมต่อเมทริกซ์ของแป้นพิมพ์ ATmega162 ใช้พอร์ต C ในขณะที่ ATmega169 ต้องใช้พอร์ต E เนื่องจากพอร์ตที่ต่างกันมีการขัดจังหวะสถานะบรรทัด ATmega162 มีฟังก์ชันสร้างการขัดจังหวะเมื่อสถานะของบรรทัดพอร์ต C เปลี่ยนแปลง และ ATmega169 - เมื่อสถานะของบรรทัดพอร์ต E เปลี่ยนแปลง หากคุณต้องการใช้ฟังก์ชันทางเลือกอื่นของพอร์ตเหล่านี้ คุณจะต้องแก้ไขแอปพลิเคชันในลักษณะดังกล่าว วิธีใช้พอร์ตอื่นที่มีฟังก์ชันการสร้างเพื่อเชื่อมต่อการขัดจังหวะเมทริกซ์ของแป้นพิมพ์สำหรับการเปลี่ยนแปลงสถานะของสาย

โปรดทราบว่า ATmega169 ใช้การลงทะเบียน SMCR เพื่อเปิดใช้งานโหมดสลีป

หากใช้ไมโครคอนโทรลเลอร์อื่นๆ จำเป็นต้องมีส่วนประกอบภายนอกเพิ่มเติมและการเปลี่ยนแปลงการขัดจังหวะที่ใช้ การใช้ไมโครคอนโทรลเลอร์ดังกล่าวในการประมวลผลเมทริกซ์แป้นพิมพ์ 4x4 ได้อธิบายไว้ในตัวอย่างแอปพลิเคชัน AVR240 ไม่จำเป็นต้องเปลี่ยนฟังก์ชันที่เหลือของตัวอย่างการใช้งานที่อธิบายไว้

บ่อยครั้งที่พินไมโครคอนโทรลเลอร์ฟรีไม่เพียงพอที่จะเชื่อมต่อปุ่มตามจำนวนที่ต้องการ เมื่อเชื่อมต่อโดยตรงด้วยปุ่ม n คุณจะต้องจัดสรรบรรทัดอินพุต/เอาต์พุตให้เท่ากัน ซึ่งไม่สามารถทำได้เสมอไป เพื่อการใช้เส้นพอร์ตอย่างมีเหตุผลมากขึ้น คุณสามารถใช้ไดอะแกรมการเชื่อมต่อเมทริกซ์ในรูปที่ 1 ในกรณีนี้ เมทริกซ์ที่เชื่อมต่อกับพอร์ต D มีขนาด 4 * 4 = 16 ปุ่ม (4 แถว r0...r3 และ 4 คอลัมน์ c0...c3) เส้น PD0...PD3 ซึ่งเป็นเส้น r0...r3 จะได้รับการกำหนดค่าสำหรับอินพุตเสมอ และจะถูกดึงขึ้นไปที่พาวเวอร์บัสโดยตัวต้านทาน R (ค่าโดยทั่วไป 4.7...10 kOhm) จากนั้นจะอ่านสถานะของปุ่ม SB1-SB16 สัญญาณศูนย์โลจิคัลจะถูกสร้างขึ้นสลับกันบนบรรทัด PD4…PD7 (คอลัมน์ c0…c3) ในตอนแรก ระดับต่ำจะถูกตั้งค่าไว้ที่คอลัมน์ c0 และในคอลัมน์อื่นๆ ทั้งหมด สถานะ Z จะถูกตั้งค่าไว้ ตอนนี้เฉพาะเมื่อกดปุ่มของคอลัมน์นี้ (SB1...SB4) ระดับลอจิกต่ำอาจเกิดขึ้นบนบรรทัดแถว r0...r3 ถัดไป โลจิคัล 0 ถูกตั้งค่าในคอลัมน์ c1 และกลุ่มของปุ่ม SB5...SB8 ฯลฯ จะถูกสแกน อัลกอริธึมการโพลปุ่มเดียวกันนี้ใช้สำหรับแป้นพิมพ์เมทริกซ์อื่นๆ โดยไม่คำนึงถึงจำนวนแถวและคอลัมน์ โดยทั่วไป จำนวนปุ่ม n คือผลคูณของจำนวนแถวและคอลัมน์ ตัวอย่างเช่น เมทริกซ์ 2*2 (4 เส้น) จะมี 4 ปุ่ม แต่ในทางกลับกัน จำเป็นต้องใช้เส้น I/O จำนวนเท่ากันเพื่อเชื่อมต่อปุ่มจำนวนเท่ากันโดยตรง ดังนั้น การประหยัดเอาต์พุตจะเริ่มปรากฏขึ้นเมื่อจำนวนปุ่มเกิน 4...6 และจะมีความสำคัญมากยิ่งขึ้นเมื่อจำนวนปุ่มเพิ่มขึ้น

รูปที่ 1 แผนภาพเมทริกซ์สำหรับเชื่อมต่อปุ่ม

องค์ประกอบ VD1...VD4 และ R1...R4 เป็นทางเลือกในแผนภาพ ไดโอดถูกใช้เพื่อป้องกัน ไฟฟ้าลัดวงจรระหว่างเส้นแถวและคอลัมน์ ตัวอย่างเช่นหากคุณกดปุ่ม SB1 (ในขณะที่สแกนคอลัมน์ c0) จู่ๆ แถวบรรทัด r0 จะถูกกำหนดค่าสำหรับเอาต์พุตและมีระดับลอจิคัลสูง กระแสไฟฟ้าขนาดใหญ่ที่ยอมรับไม่ได้จะเริ่มขึ้น ให้ไหลผ่านวงจร c0r0 แม้ว่าลอจิกของโปรแกรมจะไม่อนุญาตให้มีโหมดการทำงานนี้ แต่ด้วยเหตุผลหลายประการก็ยังคงสามารถเกิดขึ้นได้ ดังนั้นอย่างน้อยที่สุดเมื่อทำการดีบั๊กโปรแกรมไดโอดจะไม่ฟุ่มเฟือย หากความจุในการติดตั้งที่อ้างถึงพิน PD3...PD0 ไม่ใหญ่เกินไป ความต้านทานแบบดึงขึ้นของพาวเวอร์บัสจะถูกแทนที่ด้วยตัวต้านทานแบบ "ดึงขึ้น" ภายใน เมื่อต้องการทำเช่นนี้ คุณต้องตั้งค่าบิตที่เหมาะสมในรีจิสเตอร์ PORTD เมื่อมีการกำหนดค่าบรรทัดสำหรับอินพุต

ตัวอย่างขั้นตอนการสแกนแป้นพิมพ์เมทริกซ์

ปุ่ม Def = R16 ; ลงทะเบียนด้วยรหัสของปุ่มที่กด def temp = R17 ; ลงทะเบียนสำหรับการดำเนินการระดับกลาง ldi temp, สูง (RAMEND) ; การเริ่มต้นสแต็กออก SPH, อุณหภูมิ ldi temp, ต่ำ (RAMEND) ออก SPL, อุณหภูมิ<< PD0)|(1 << PD1)|(1 << PD2)|(1 << PD3) out PORTD,temp . rcall btn_pol . ; Подпрограмма опроса матричной клавиатуры; R16 – номер нажатой кнопки на выходе из подпрограммы, ; если ни одна кнопка не нажата, то R16=0; ; если нажаты две и более кнопок, то R16=0xFF ; R17 – регистр для определения номера строки; R18 – регистр для задания номера столбца; R19 – счётчик столбцов; R20 – регистр для промежуточных операций btn_pol: clr R16 ;обнуляем регистры с кодом нажатой clr R19 ;кнопки и номером столбца ldi R18,0x0F ;очищаем регистр данных PORTD порта D out PORTD,R18 ldi R18,0x00010000 bp1: out DDRD,R18 ;настраиваем на вывод линию соответствующего nop ;столбца через регистр DDRD порта D in R17,PIND ;считываем состояние строк из регистра PIND com R17 andi R17,0x0F ;выделяем значение 4-х строк ldi R20,0 ;если ни одна кнопка в столбце не нажата, breq bp5 ;перемещаемся на следующий столбец cpi R17,0x01 ;если нажата кнопка в строке c0, ldi R20,1 ;то вычисляем её номер breq bp2 cpi R17,0x02 ;если нажата кнопка в строке c1, ldi R20,2 ;то вычисляем её номер breq bp2 cpi R17,0x04 ;если нажата кнопка в строке c2, ldi R20,3 ;то вычисляем её номер breq bp2 cpi R17,0x08 ;если нажата кнопка в строке c3, ldi R20,4 ;то вычисляем её номер brne bp3 ;если нажато более одной кнопки, завершаем опрос bp2: tst R16 ;если в предыдущих столбцах были нажаты breq bp4 bp3: ldi R16,0xFF ;кнопки, то завершаем опрос с кодом 0xFF ret bp4: push R19 ;иначе вычисляем номер кнопки, как lsl R19 ;N = 4*column + row + 1 = 4*R19 + R20 + 1 lsl R19 add R20,R19 mov R16,R20 pop R19 bp5: inc R19 lsl R18 cpi R19,4 ;повторяем цикл опроса пока не будут brne bp1 ;опрошены все 4 столбца ret

clr temp ; กำหนดค่าพอร์ต D บรรทัดเพื่ออินพุต DDRD, temp ldi temp, (1

ด้วยข้อดีทั้งหมด รูปแบบการเชื่อมต่อเมทริกซ์ก็มีข้อเสียเปรียบเช่นกัน ด้วยความช่วยเหลือนี้ ทำให้เป็นการยากที่จะนำการรวมปุ่มการอ่านไปใช้ หากมีการกดปุ่มสามปุ่มใด ๆ ที่สร้างมุมฉากซึ่งกันและกัน (เช่น SB1, SB2, SB5) บนแป้นพิมพ์ดังกล่าว โปรแกรมโพลจะบันทึกการกดปุ่มผิด ๆ ที่วางอยู่ที่มุมว่างของสี่เหลี่ยม (ใน กรณีนี้ SB6) ในบางสถานการณ์ ปุ่ม "phantom" ดังกล่าวอาจเป็นปุ่มใดก็ได้บนแป้นพิมพ์

รายชื่อธาตุกัมมันตภาพรังสี การกำหนด พิมพ์ นิกาย ปริมาณบันทึกร้านค้า
สมุดบันทึกของฉัน ดีดี1

MK AVR 8 บิต

1 เอทีเมก้า8
ไปยังสมุดบันทึก วีดี1-วีดี4 4 เอทีเมก้า8
ไดโอด อาร์, อาร์, อาร์, อาร์ 4

ตัวต้านทาน

แทบไม่มีผลิตภัณฑ์ใดที่มีไมโครคอนโทรลเลอร์จะสมบูรณ์หากไม่มีปุ่ม หัวข้อนี้ถูกแฮ็กแล้วและเป็นที่รู้จักเป็นส่วนใหญ่ การเขียนบทความนี้ฉันไม่ได้พยายามสร้างวงล้อขึ้นมาใหม่ ฉันเพิ่งตัดสินใจรวบรวมข้อมูลทั้งหมดเกี่ยวกับวงจรเข้าด้วยกัน ฉันคิดว่าวัสดุนี้จะมีประโยชน์สำหรับผู้เริ่มต้น เพื่อไม่ให้คุณสับสนตัวเลขด้านล่างจะไม่แสดงวงจรแหล่งจ่ายไฟรีเซ็ตและนาฬิกาสำหรับไมโครคอนโทรลเลอร์

วิธีที่หนึ่ง - แบบดั้งเดิม

รูปที่1a รูปที่1b

หากมีปุ่มไม่กี่ปุ่มและพิน MC ก็ไม่มีปัญหา เราจะใช้วิธีการเชื่อมต่อแบบเดิม

เมื่อปล่อยปุ่ม เอาต์พุต μ จะเชื่อมต่อผ่านตัวต้านทานเข้ากับ "บวก" ของแหล่งจ่ายไฟ (รูปที่ 1a) เมื่อกดปุ่ม พิน μ จะเชื่อมต่อกับกราวด์ ตัวต้านทานแบบดึงขึ้น R1 จะจำกัดกระแสในวงจรสวิตช์ หากไม่มีอยู่ตรงนั้น เมื่อเรากดปุ่ม เราก็จะลัดวงจรแหล่งจ่ายไฟของเรา

จะเกิดอะไรขึ้นถ้าพินไมโครคอนโทรลเลอร์อยู่ในโหมดเอาท์พุต? ขึ้นอยู่กับสถานะของพินนี้ หากมี "ศูนย์ตรรกะ" ที่เอาต์พุต จะไม่มีอะไรเลวร้ายเกิดขึ้น เพราะในกรณีแรก (รูปที่ 1a) ปริมาณกระแสขาเข้าจะถูกจำกัดโดยตัวต้านทาน R1 และในกรณีที่สอง (รูปที่ 1b) ไม่มีกระแสไฟฟ้า จะไหลเลย เมื่อคุณกดปุ่มจะไม่มีอะไรเกิดขึ้นเนื่องจากความแตกต่างที่อาจเกิดขึ้นระหว่างเอาต์พุตและ "กราวด์" ในกรณีนี้จะเป็นศูนย์

หากมี "ตรรกะ" ที่เอาต์พุตและกดปุ่ม กระแสหลายสิบมิลลิแอมป์จะไหลผ่านเอาต์พุตไมโครคอนโทรลเลอร์ลงกราวด์และเอาต์พุตพอร์ตอาจ "ไหม้" กระแสไฟฟ้าสูงสุดที่อนุญาตสำหรับเอาต์พุตของไมโครคอนโทรลเลอร์ AVR ตามเอกสารประกอบคือ 40 mA ดังนั้น บางครั้งการวางตัวต้านทานที่มีค่าหลายร้อยโอห์ม เช่น 330 ไว้ระหว่างพิน μ กับปุ่มจึงเป็นประโยชน์ (รูปที่ 1c) นี่คือวิธีการเชื่อมต่อปุ่มต่างๆ บนบอร์ดดีบั๊ก STK500 ทำเช่นนี้เพื่อให้แน่ใจว่าผู้ใช้จะไม่เผาไมโครคอนโทรลเลอร์โดยไม่ตั้งใจในระหว่างการทดลอง

สำหรับต้นแบบของคุณเอง คุณสามารถทำได้โดยไม่ต้องใช้ตัวต้านทานนี้

วิธีที่สองคือการใช้ไดโอด

ใช้เมื่อมีปุ่มมากกว่าสองปุ่ม และคุณต้องการประหยัดเงินสำหรับหมุด MC ในกรณีนี้แต่ละปุ่มจะสอดคล้องกับรหัสดิจิทัลของตัวเองและจำนวนปุ่มที่สามารถแขวนได้ด้วยวิธีนี้บนหมุด N mk = 2 N - 1 นั่นคือสามารถแขวนปุ่มได้ 7 ปุ่มบนสามพิน 15 บนสี่ หมุด และอื่นๆ... แต่ฉันจะไม่แขวนเกิน 7 อัน จำนวนส่วนประกอบภายนอกเพิ่มเติมเพิ่มขึ้น วงจรและโปรแกรมของไมโครคอนโทรลเลอร์จึงซับซ้อนมากขึ้น นอกจากนี้สำหรับปุ่มจำนวนมากยังมีรูปแบบการสลับอื่น ๆ ตัวต้านทานแบบดึงขึ้นไม่แสดงในแผนภาพ แต่ถือว่าใช้ตัวต้านทานภายใน

อย่างไรก็ตามผ่านไดโอดคุณสามารถส่งสัญญาณจากปุ่มไปยังเอาต์พุตขัดจังหวะภายนอกของคอนโทรลเลอร์ได้ (รูปที่ 3) เมื่อกดปุ่มใดๆ เอาต์พุตขัดจังหวะภายนอกผ่านไดโอดจะลัดวงจรลงกราวด์และทำให้เกิดการขัดจังหวะ (แน่นอนว่าต้องมีการกำหนดค่าและเปิดใช้งาน) ด้วยวิธีนี้ คอนโทรลเลอร์จะไม่จำเป็นต้องสำรวจปุ่มต่างๆ อย่างต่อเนื่อง ขั้นตอนนี้จะถูกเปิดใช้งานเมื่อมีการขัดจังหวะจากภายนอกเท่านั้น

วงจรนี้ไม่เกี่ยวข้องกับไมโครคอนโทรลเลอร์ AVR ทั้งหมด เนื่องจากในไมโครคอนโทรลเลอร์บางรุ่น อาจมีการขัดจังหวะจากภายนอกเนื่องจากการเปลี่ยนแปลงบนพินใดๆ (เช่นใน ATmega164P)

วิธีที่สามใช้สำหรับแป้นพิมพ์เมทริกซ์

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

พิน PC0, PC1, PC2, PC3 คือแถวของเมทริกซ์ พิน PB0, PB1, PB2 คือคอลัมน์ของเมทริกซ์ สามารถสอบถามปุ่มตามแถวหรือตามคอลัมน์ สมมติว่าเราค้นหาพวกมันทีละคอลัมน์ ขั้นตอนการสำรวจจะมีลักษณะดังนี้ สถานะเริ่มต้นของพินทั้งหมดคืออินพุตที่เปิดตัวต้านทานแบบดึงขึ้นไว้ ตั้งค่าพิน PB0 เป็นโหมดเอาต์พุตและตั้งค่าเป็นศูนย์ ตอนนี้กดปุ่ม S1, S2, S3, S4 จะปิดพิน PC0, PC1, PC2, PC3 เป็น 0 แหล่งจ่ายไฟ เราสอบปากคำผลลัพธ์เหล่านี้และพิจารณาว่ามีการกดปุ่มใดๆ อยู่ในขณะนี้หรือไม่ ตั้งค่าพิน PB0 เป็นโหมดเอาท์พุต และเปิดตัวต้านทานแบบดึงขึ้น เราตั้งค่าพิน PB1 เป็นโหมดเอาต์พุตและตั้งค่าเป็นศูนย์ เราสำรวจพิน PC0, PC1, PC2, PC3 อีกครั้ง ตอนนี้กดปุ่ม S5, S6, S7, S8 จะปิดพิน PC0, PC1, PC2, PC3 เราค้นหาคอลัมน์สุดท้ายของปุ่มในลักษณะเดียวกัน

แถวเมทริกซ์สามารถเชื่อมต่อผ่านไดโอดเข้ากับพินขัดจังหวะภายนอกได้ จากนั้นตรรกะของโปรแกรมก็สามารถสร้างได้เช่นนี้ หากไม่ได้ใช้แป้นพิมพ์เป็นเวลาหลายนาที ไมโครคอนโทรลเลอร์จะเข้าสู่โหมดพลังงานต่ำ ในกรณีนี้ พิน PB0, PB1, PB2 ได้รับการกำหนดค่าเป็นเอาต์พุตที่มีระดับลอจิคัลเป็นศูนย์ เมื่อกดปุ่มใดปุ่มหนึ่ง ขาขัดจังหวะผ่านไดโอดจะสั้นลงจนเหลือศูนย์ สิ่งนี้ทำให้เกิดการขัดจังหวะจากภายนอก ไมโครคอนโทรลเลอร์จะตื่นและเริ่มจับเวลาตามสัญญาณที่สแกนคีย์บอร์ด ในเวลาเดียวกัน ตัวนับเวลาจะเริ่มทำงาน ซึ่งจะถูกรีเซ็ตเมื่อกดปุ่มใดปุ่มหนึ่ง ทันทีที่ล้นไมโครคอนโทรลเลอร์จะเข้าสู่โหมดพลังงานต่ำอีกครั้ง

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

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

สั้น ๆ เกี่ยวกับไฟล์:
keyboard_define.inc— ไฟล์การกำหนดค่าแป้นพิมพ์
ไฟล์นี้เก็บคำจำกัดความของแมโครทั้งหมดที่ใช้โดยแป้นพิมพ์ ที่นี่เรากำหนดว่าพินใดของไมโครคอนโทรลเลอร์จะเชื่อมต่อกับสายใด ความละเอียดอ่อนอย่างหนึ่ง - ส่งออกไปยังคอลัมน์ ( พอร์ตการสแกน) ต้องเป็นชุดบรรทัดตามลำดับของพอร์ตเดียว ตัวอย่างเช่นขา 0,1,2,3 หรือ 4,5,6,7 , หรือ 3,4,5,6 - ไม่ว่าพอร์ตไหนสิ่งสำคัญคือมีความสม่ำเสมอ
ฉันคิดว่าการระบุขาจะไม่มีปัญหา แต่เกี่ยวกับพารามิเตอร์ คีย์มาสค์ฉันอยากจะบอกคุณบางอย่างที่พิเศษ
นี่คือมาสก์ที่ใช้ระบุพอร์ตที่สแกน ควรมี 6 อันและ 0 หนึ่งอัน ศูนย์ถูกตั้งค่าไว้ที่ตำแหน่งขวาสุดของพอร์ตการสแกน

ตัวอย่าง:
พอร์ตการสแกนของฉันค้างที่บิต 7,6,5,4 บิตขวาสุดของพอร์ตการสแกนคือบิต 4 ดังนั้นมาสก์คือ 0b11101111 - ศูนย์อยู่ในตำแหน่งที่ 4 หากเส้นสแกนค้างบนขา 5,4,3,2 หน้ากากจะเป็น 0b11111011 อยู่แล้ว - ศูนย์ในตำแหน่งที่สอง เหตุใดจึงอธิบายทั้งหมดนี้ด้านล่าง

นอกจากนี้ยังมีมาสก์ของพอร์ตการสแกนที่ใช้งานอยู่ - สแกนเอ็มสเค- ในนั้นหน่วยต่างๆ จะตั้งอยู่ตรงข้ามกับเส้นของคอลัมน์เท่านั้น คอลัมน์ของฉันถูกตั้งค่าเป็น tetrad ที่สำคัญที่สุดของพอร์ต ดังนั้นรูปแบบการสแกนจึงดูเหมือน 0b11110000.

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

นี่คือลักษณะของรหัสทดสอบของฉัน:

หลัก:SEI ; เปิดใช้งานการขัดจังหวะ

RCALL KeyScan ; กำลังสแกนแป้นพิมพ์
ดัชนีราคาผู้บริโภค R16.0; หากส่งคืน 0 แสดงว่าไม่มีการกด
BREQ หลัก ; ในกรณีนี้ ให้ไปที่จุดเริ่มต้น
RCALL CodeGen ; หากรหัสสแกนถูกส่งคืนเราจะโอนไปที่
- รหัส ASCII

MOV R17,R16 ; กำลังโหลดลงในรีจิสเตอร์การรับของตัวจัดการ LCD
RCALL DATA_WR ; เราแสดงมันบนหน้าจอ

RJMP หลัก ; มาวนซ้ำทุกอย่างเพื่ออะไร

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

ตอนนี้ฉันจะบอกคุณว่ามันทำงานอย่างไร ขั้นตอนการสแกนคีย์

กำหนด COUNT = R18
คีย์สแกน: นับ LDI,4 ; ลองสแกน 4 คอลัมน์กัน
LDI R16, มาสก์ ; โหลดมาสก์ลงบนการสแกนคอลัมน์ 0

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

คีย์ลูป: ใน R17,COL_PORT ; เราใช้ค่าก่อนหน้าจากพอร์ต
ORI R17,สแกน ; เราตั้งค่าบิตของส่วนที่สแกนเป็น 1


ในการเริ่มต้น กำลังโหลดข้อมูลจากการลงทะเบียนพอร์ตเพื่อให้มีการกำหนดค่าพอร์ตเริ่มต้นอยู่ในมือ นอกจากนี้เรายังต้องตั้งค่าบิตการสแกนทั้งหมดของพอร์ตเป็น 1 ซึ่งทำได้ผ่านการดำเนินการ หรือโดยการสแกนหน้ากาก ในส่วนของหน่วยยืนหลังปฏิบัติการ หรือโดยหน้ากาก 11110000 (ความหมายของฉัน. สแกนมาส์ก) บิตทั้งหมดจะกลายเป็นบิตเดียว และเมื่อมีศูนย์จะยังคงไม่เปลี่ยนแปลง

และ R17,R16 ; การรีเซ็ตบิตของคอลัมน์ที่สแกน
ออก COL_PORT,R17 ; เราส่งออกไบต์ที่สร้างขึ้นจากพอร์ต


ตอนนี้เราซ้อนทับบนไบต์ที่สร้างขึ้น มาสก์คอลัมน์ที่ใช้งานอยู่- ในตอนแรกจะมีศูนย์ในตำแหน่งแรก และที่เหลือทั้งหมดเป็นศูนย์ เป็นผลให้ค่าพอร์ตอื่น ๆ จะไม่เปลี่ยนแปลง แต่ 0 จะปรากฏในคอลัมน์แรก จากนั้นมาสก์จะย้ายและการดำเนินการทั้งหมดจะทำซ้ำอีกครั้ง เป็นผลให้ศูนย์จะอยู่ในคอลัมน์ถัดไปอยู่แล้วและต่อๆ ไป ดังนั้นเราจึงจัดระเบียบศูนย์ "กำลังทำงาน" ในพอร์ตการสแกน ในขณะที่บิตอื่นๆ ที่ไม่เกี่ยวข้องของพอร์ตยังคงไม่เปลี่ยนแปลง จากนั้นหมายเลขที่สร้างขึ้นจะถูกโหลดลงในพอร์ตรีจิสเตอร์ และขาจะยอมรับระดับแรงดันไฟฟ้าที่สอดคล้องกัน

นพ; ความล่าช้าในการเปลี่ยนขา
นพ
นพ
นพ

SBIS ROW0_PIN,ROW0 ; ตรวจสอบว่ากดบรรทัดไหน
RJMP bt0

SBIS ROW1_PIN, ROW1
RJMP bt1

SBIS ROW2_PIN,ROW2
RJMP bt2

SBIS ROW3_PIN, ROW3
RJMP bt3


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

ROL R16 ; การเลื่อนมาสก์การสแกน
นับธันวาคม ; การลดจำนวนตัวนับคอลัมน์
BRNE คีย์ลูป ; หากเรายังไม่ได้ทำทุกอย่าง ให้ทำซ้ำอีกครั้งหนึ่ง

ซีแอลอาร์ R16; ถ้าไม่มีการคลิก เราจะคืนค่า 0
รีต
.undef COUNT

นี่คือตำแหน่งที่มาสก์ถูกเลื่อนไปทางซ้ายโดยใช้คำสั่ง cyclic shift ร.ล- หลังจากนั้นเราจะลดตัวนับการวนซ้ำ (เริ่มแรกเท่ากับ 4 เนื่องจากเรามีสี่คอลัมน์) หากไม่มีการคลิก เมื่อสิ้นสุดการวนซ้ำทั้งสี่ครั้ง เราก็หลุดออกจากวงจรและรีเซ็ตรีจิสเตอร์ ร16และเรากลับมา


BT0: ANDI R16,สแกน ; การสร้างรหัสสแกน
โอริ R16.0x01 ; เราส่งคืนในทะเบียน 16
รีต

และนี่คือหนึ่งในจุดสิ้นสุดที่เป็นไปได้เมื่อกด ที่นี่รหัสสแกนจะถูกสร้างขึ้นซึ่งจะถูกส่งกลับไปยังทะเบียน ร16.ฉันตัดสินใจที่จะไม่กังวล แต่เช่นเคย บีบเป็นสิบไบต์แล้วทำให้มันเร็วและสั้นที่สุดเท่าที่จะเป็นไปได้ แล้วเราจะได้อะไรเมื่อเรามาถึงโค้ดชิ้นนี้ และเรามีหนึ่งในตัวเลือกพอร์ตการสแกน ( 1110,1101,1011,0111 ) และเรายังรู้หมายเลขบรรทัดที่เราได้มาตรงนี้ด้วย ชิ้นส่วนนี้สามารถเข้าถึงได้จากบรรทัดแรกโดยใช้คำสั่งเท่านั้น RJMP bt0.
มาสร้างโค้ดสแกนจากชุดการสแกนและหมายเลขบรรทัดกันเถอะ! พูดไม่ทันทำ! ขั้นแรกเราต้องแยกชุดการสแกนออกจากค่าพอร์ต - มันถูกเก็บไว้ในรีจิสเตอร์ ร16จึงไม่จำเป็นต้องหยิบออกจากพอร์ต เราผลักดันการดำเนินการและความคุ้มค่า ร16ผ่าน สแกนมาส์กและทุกสิ่งที่อยู่ภายใต้สิ่งที่ผ่านไปโดยไม่มีการเปลี่ยนแปลง และเมื่อมีศูนย์ มันก็กลายเป็นศูนย์ อ๊ะ เรามีชิ้นการสแกนแสดงอยู่ ซึ่งเป็นชิ้นที่สำคัญที่สุด ทีนี้มาวางหมายเลขบรรทัดที่นั่น - ด้วยการดำเนินการ หรือ- ครั้งหนึ่งเราได้งานก่อสร้างแบบนี้ [สแกน] [บรรทัด]
ดังนั้นเราจึงทิ้งมันไว้ในทะเบียน ร16และพวกเราเองก็จากไป! เช่นเดียวกับบรรทัดที่เหลือ ดูแหล่งที่มา ฉันจะไม่ทำซ้ำที่นี่

สแกนรหัสถอดรหัส
เยี่ยมเลย มีโค้ดสแกน แต่จะทำยังไงกับมันล่ะ? คุณไม่สามารถติดเขาได้ทุกที่ เรารู้ว่าเรื่องไร้สาระแบบนี้ 01110001 นี่คือรหัสหนึ่ง แต่มีบางส่วน จอแอลซีดีหน้าจอหรือเทอร์มินัลมาตรฐานจะสร้างเรื่องตลกเล็ก ๆ น้อย ๆ ที่น่าขนลุกให้เราและบอกเราทุกอย่างที่เธอคิดเกี่ยวกับระบบสัญกรณ์ของเรา - คุณเห็นไหม แอสกีให้มัน เอาล่ะ มันจะเป็น ASCII

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

โค้ดสแกนเดรัจฉานฟอร์ซ
ดังนั้นเราจึงมีโค้ดสแกนที่ย่อยไม่ได้มากและมีตารางที่เพรียวบาง แอสกีตัวอักษร จะข้ามงูกับเม่นได้อย่างไร? มันง่ายมาก! ลองวางตารางสัญลักษณ์ไว้ในลิงค์ในหน่วยความจำ [รหัสสแกน]:จากนั้นเราจะรันโค้ดสแกนที่จำเป็นแต่ละรายการผ่านตารางนี้ และหากมีค่าที่ตรงกัน ให้แทนที่โค้ดที่ต้องการในเอาต์พุต แอสกีจากมัด ตัวอย่างการเขียนโปรแกรมคลาสสิก - สูญหายไปตามกาลเวลา แต่ได้มาอยู่ในความทรงจำ

นี่คือสิ่งที่ดูเหมือน:

CodeGen:LDI ZH,สูง(Code_Table*2) ; โหลดที่อยู่ตารางโค้ดแล้ว
LDI ZL,ต่ำ(รหัส_ตาราง*2) ; ไบต์สูงและต่ำ

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

เดรัจฉาน: LPM R17,Z+ ; ฉันเอาอักขระตัวแรกจากตาราง - สแกนโค้ด

ดัชนีราคาผู้บริโภค R17.0xFF ; หากอยู่ท้ายตาราง
BREQ CG_ออก ; จากนั้นเราก็ออกไป

ดัชนีราคาผู้บริโภค R16.0; ถ้าเป็นศูนย์
BREQ CG_ออก ; แล้วเราก็ออกไป

ซีพี R16,R17 ; ฉันเปรียบเทียบกับรหัสสแกนของกุญแจ
BREQ เท่ากับ ; ถ้ามันเท่ากันเราก็ไปแทนที่รหัส ASCII

โหลดโค้ดสแกนแรกจากตารางแล้วเขียนลงในรีจิสเตอร์ ร17พร้อมเพิ่มที่อยู่ในทะเบียน ซี(เลือกเซลล์ตารางถัดไป) และก่อนอื่นเปรียบเทียบด้วย เอฟเอฟคือรหัสที่อยู่ท้ายตาราง ถ้าโต๊ะหมดเราก็ออกจากที่นี่ หากเราไม่ได้เรียงลำดับทั้งตาราง เราก็จะเริ่มเปรียบเทียบค่าอินพุต (ใน register ร16) ในตอนแรกด้วยศูนย์ (ไม่ต้องกด) หากออกจากศูนย์ด้วย และมีรหัสสแกนจากตาราง หากการสแกนตารางตรงกับการสแกนอินพุต ให้ไปที่ เท่ากัน.

ลิตรต่อนาที R17,Z+ ; เพิ่ม Z ขึ้น 1
RJMP เดรัจฉาน; ทำซ้ำวงจร

และหากไม่พบสิ่งใดเราจะเรียกคำสั่งอีกครั้ง LPM R17,Z+เพียงเพื่อให้เธอเพิ่มขึ้น ซีทีละคน - เราต้องก้าวข้ามไป แอสกีรหัสและนำรหัสสแกนถัดไปจากตาราง แค่ อิงค์ ซีมันจะไม่ทำงานเพราะว่า ซีกับเรา ไบต์คู่. ZL และ ZH- ในบางกรณีก็เพียงพอแล้ว อิงค์ ZLแต่ในกรณีนี้คือเมื่อเราแน่ใจอย่างแน่นอนว่าที่อยู่นั้นอยู่ใกล้กับจุดเริ่มต้นและไบต์ต่ำจะไม่ล้น (มิฉะนั้น แทนที่จะเป็นที่อยู่ 00000001:00000000 เราจะได้รับ 00000000:0000000 ซึ่งโดยพื้นฐานแล้วไม่ถูกต้อง) และคำสั่ง แอลพีเอ็มจะทำทุกอย่างให้เรา ดังนั้นที่นี่เราจึงประหยัดได้อีกสองสามไบต์ จากนั้นเราจะกลับไปสู่จุดเริ่มต้นของวงจร และจะเป็นเช่นนั้นอีกครั้ง แอลพีเอ็มซึ่งจะดาวน์โหลดโค้ดสแกนถัดไป

เท่ากับ: LPM R16,Z ; กำลังโหลดรหัส ASCII จากหน่วยความจำ
เกษียณ ; กลับไปกันเถอะ

หากมีเหตุบังเอิญก็เป็นผล แอลพีเอ็ม ซี+กับเรา ซีชี้ไปที่เซลล์ถัดไป - ด้วย แอสกีรหัส. เราโหลดมันลงในทะเบียน ร16และออกไปข้างนอก

CG_ออก: CLR R16 ; รีเซ็ต 0 = ส่งคืน 0
เกษียณ ; กลับไปกันเถอะ

และในกรณีที่ผลลัพธ์เป็นศูนย์ เมื่อตารางสิ้นสุดและไม่พบโค้ดสแกน หรือศูนย์อยู่ในรีจิสเตอร์ R16 ที่อินพุต เราจะส่งคืนด้วยศูนย์เดียวกันที่เอาต์พุต เช่นเดียวกับที่



- ข้อมูลแบบคงที่
;========================================
Code_Table: .db 0x71,0x31 ;1
.db 0xB1,0x32 ;2
.db 0xD1,0x33 ;3
.db 0x72,0x34 ;4
.db 0xB2,0x35 ;5
.db 0xD2,0x36 ;6
.db 0x73,0x37 ;7
.db 0xB3,0x38 ;8
.db 0xD3,0x39 ;9
.db 0x74,0x30 ;0
.db 0xFF,0 ;END

มีเพียงตารางข้อมูลคงที่บนขอบหน่วยความจำ อย่างที่คุณเห็น ข้อมูลถูกจัดกลุ่มเป็นสองไบต์ - scancode/ASCII

ต้องขอบคุณความวิปริตดังกล่าว ทำให้โปรแกรมทั้งหมดใช้การประมวลผลแป้นพิมพ์ การถอดรหัสรหัสสแกน การอ่าน/การเขียนไปยังตัวบ่งชี้ LCD และการรีเซ็ต RAM (จำเป็นเพื่อให้แน่ใจว่าหน่วยความจำเป็นศูนย์) เพียง 354 ไบต์- ใครทำได้น้อยกว่ากัน?

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

คีย์บอร์ดทั่วไปคือ 3x4 และ 4x4 พร้อมปุ่ม 12 และ 16 ปุ่มตามลำดับ ฉันมีคีย์บอร์ด 4x4 อยู่ในมือ ลองพิจารณาทำงานกับมันตอนนี้

ฉันบังเอิญมีคีย์บอร์ดตัวนี้ที่มีหน้าสัมผัสแบบเมมเบรน กำลังดีเพราะมีความหนาเพียง 1 มม. และสามารถยึดติดกับพื้นผิวที่ต้องการได้ง่าย

หลังจากจิ้มที่ปุ่มต่างๆ แล้ว ฉันใช้มัลติมิเตอร์เพื่อพิจารณาว่าปุ่มต่างๆ ภายในแป้นพิมพ์เชื่อมต่อกันอย่างไร


มีฟังก์ชั่นพิเศษสำหรับการสแกนคีย์บอร์ดเมทริกซ์ใน Bascom-AVR Getkbd() . คำสั่งนี้ออกแบบมาเพื่อใช้กับแป้นพิมพ์ขนาด 4x4 ดังนั้นจึงใช้พินทั้งหมด 8 พินของพอร์ตไมโครคอนโทรลเลอร์หนึ่งพอร์ต และหากคุณใช้คีย์บอร์ดที่มีปุ่มน้อยกว่า คุณควรคำนึงถึงเรื่องนี้ด้วย

การกำหนดค่าคำสั่งประกอบด้วยการกำหนดพอร์ตที่จะเชื่อมต่อแป้นพิมพ์เวลาในการดีดเด้งของผู้ติดต่อและความล่าช้าหลังจากตรวจพบการกดแป้นพิมพ์

ตัวอย่างเช่น ในบรรทัดต่อไปนี้:

การกำหนดค่า Kbd = พอร์ต เดเด้ง= 20 , ล่าช้า= 100

มีการกำหนดค่าการเชื่อมต่อแป้นพิมพ์กับ PortD เวลาตีกลับตั้งไว้ที่ 20 ms เวลาหน่วงหลังจากกดคือ 100 ms

คำสั่งนี้ใช้เวลาสแกนบรรทัดแป้นพิมพ์ทั้งหมดและส่งคืนตัวแปรตามจำนวนคีย์ที่กดตั้งแต่ 0 ถึง 15 หากไม่ได้บันทึกการกดปุ่มฟังก์ชันจะส่งคืนหมายเลข 16 นอกจากนี้ขึ้นอยู่กับวิธีการ เชื่อมต่อปุ่มแล้วคุณอาจต้องค้นหาสัญลักษณ์ของปุ่มกด

ในตัวอย่างด้านล่าง การสแกนแป้นพิมพ์จะเกิดขึ้นที่ 10 Hz และอยู่ในลูปโปรแกรมหลัก ผลลัพธ์ของการกดจะแสดงบนจอ LCD

$regfile = "m8def.dat"
$คริสตัล = 1000000

"การกำหนดค่าการแสดงผล
การกำหนดค่า จอแอลซีดี = พิน Rs = พอร์ต 0, E = พอร์ต 1, DB4 = พอร์ต 2, DB5 = พอร์ต 3, DB6 = พอร์ต 4, DB7 = พอร์ต 5
การกำหนดค่า จอแอลซีดี= 20 * 4
เคอร์เซอร์ ปิด
Cls

"การกำหนดค่าแป้นพิมพ์
การกำหนดค่า Kbd = พอร์ต เดเด้ง= 20 , ล่าช้า= 100


"ตัวแปร
สลัว คีย์_ชาร์ เช่นไบต์"จำนวนปุ่มที่กด
สลัว คีย์_str เช่นสตริง* 1 “สัญลักษณ์ของการกดปุ่มบนคีย์บอร์ด
สลัว ผลลัพธ์ เช่นสตริง* 20 “ผลจากการกดแป้นพิมพ์

ผลลัพธ์= ""

“วงหลักของโปรแกรม
ทำ

คีย์_ชาร์= Getkbd() "ไม่ได้กดปุ่ม และฟังก์ชันจะคืนค่า 16 ให้กับตัวแปร

ถ้า คีย์_ชาร์<> 16 แล้ว“ถ้าตัวแปรไม่เท่ากับ 16 แสดงว่ากดปุ่มแล้ว
คีย์_str= ค้นหา(key_char, Keyboard_data) “ดึงสัญลักษณ์ปุ่มที่กดออกมา
ผลลัพธ์= ผลลัพธ์ + คีย์_str
จบ ถ้า

ค้นหา 1 , 1

จอแอลซีดี ผลลัพธ์ “แสดงผลการกด

รอ 100

วนซ้ำ

จบ

แป้นพิมพ์_ข้อมูล:
ข้อมูล "1" , "4" , "7" , "*" , "2" , "5" , "8" , "0"
ข้อมูล "3" , "6" , "9" , "#" , "A" , "B" , "C" , "D"

และนี่คือวงจรทดสอบที่ใช้เชื่อมต่อจอแสดงผลและคีย์บอร์ด:

การเพิ่มตัวต้านทานจำกัดกระแสให้กับวงจรบนสายคีย์บอร์ดจะไม่เสียหายด้วยค่าเล็กน้อย 100-150 โอห์ม เผื่อไว้แต่สำหรับการทดสอบก็จะทำได้ (สิ่งสำคัญคือไม่ต้องกดปุ่มหลายปุ่มพร้อมกัน)

เราเชื่อมต่อ, แฟลช, กดปุ่มและดูผลลัพธ์ - สัญลักษณ์ของปุ่มที่กดจะปรากฏบนจอแสดงผล:


ฉันจะเพิ่มวิดีโอสาธิตในภายหลัง ทันทีที่ฉันพบสิ่งที่จะถ่ายในคุณภาพที่เหมาะสม

ในระหว่างนี้ คุณสามารถดาวน์โหลดไฟล์เก็บถาวรที่มีไฟล์สำหรับการจำลองใน Proteus และเฟิร์มแวร์ได้