ส่วนของเว็บไซต์
ตัวเลือกของบรรณาธิการ:
- การสร้างทางลัดบนเดสก์ท็อปสำหรับเพื่อนร่วมชั้น
- หากรองเท้าไม่พอดีกับ Aliexpress: การกระทำที่ถูกต้องในกรณีนี้ ผลิตภัณฑ์ Aliexpress มีขนาดที่เหมาะสม
- ข้อพิพาทใน AliExpress เข้าร่วมข้อพิพาทใน AliExpress
- 3 ฐานข้อมูลแบบกระจาย
- ผู้จัดการเนื้อหา - ความรับผิดชอบ เงินเดือน การฝึกอบรม ข้อเสียและข้อดีของการทำงานเป็นผู้เชี่ยวชาญด้านเนื้อหา
- จะป้องกันตัวเองจากการขุดที่ซ่อนอยู่ในเบราว์เซอร์ของคุณได้อย่างไร?
- การกู้คืนรหัสผ่านใน Ask
- วิธีเปิดกล้องบนแล็ปท็อป
- ทำไมเพลงไม่เล่นบน VKontakte?
- วิธีเพิ่มขนาดของไดรฟ์ C โดยเสียค่าใช้จ่ายของไดรฟ์ D โดยไม่สูญเสียข้อมูล
การโฆษณา
จอแสดงผลเจ็ดส่วนแบบไดนามิกบน avr ข้อมูลทางทฤษฎีโดยย่อ |
สำหรับอุปกรณ์ที่ใช้พลังงานจากแบตเตอรี่ โดยทั่วไปการใช้ตัวบ่งชี้แบบ LCD ถือว่าดีกว่าตัวบ่งชี้ไดโอดเปล่งแสง (LED) เนื่องจากการสิ้นเปลืองกระแสไฟสูงของแบบหลัง สมมุติฐานนี้ดูเหมือนว่าฉันจะไม่ชัดเจนเลยด้วยเหตุผลต่อไปนี้: 1) ในตัวบ่งชี้ LCD สมัยใหม่มีไฟแบ็คไลท์ที่กินไฟสูงถึง 100 mA; 2) พวกมันค่อนข้างเปราะบางและกลัวแสงแดดโดยตรง 3) ตัวบ่งชี้ LED ที่ทันสมัย (โดยเฉพาะ superRED และ ultraRED) มีความสว่างเพียงพอแม้จะมีกระแสไฟ 1 mA และด้วยการปรับความสว่างทันทีขึ้นอยู่กับสภาพแสง การใช้กระแสไฟเฉลี่ยของตัวบ่งชี้ 4 หลักจะไม่เกิน 30 mA แม้กลางแจ้ง ซึ่งน้อยกว่าการใช้แสงพื้นหลัง LCD แม้จะมีวงจรการแสดงผลแบบไดนามิกออนไลน์มากมาย แต่ฉันไม่เคยเห็นวงจรที่มีการควบคุมความสว่างของซอฟต์แวร์บน PIC16 บทความนี้แสดงมุมมองที่ต่ำต้อยของฉันเกี่ยวกับการดำเนินงานดังกล่าว มีจุดประสงค์หลักสำหรับนักวิทยุสมัครเล่นที่เริ่มก้าวแรกตั้งแต่การออกแบบซ้ำๆ ไปจนถึงไมโครคอนโทรลเลอร์ที่เขียนโปรแกรมด้วยตนเอง บทความนี้กล่าวถึงวิธีการควบคุมเมทริกซ์ LED ด้วยไมโครคอนโทรลเลอร์ PIC ระดับกลางโดยใช้การขัดจังหวะจากตัวจับเวลา TMR0 และ TMR2 ตัวจับเวลา TMR2 ใช้เพื่อควบคุมกระแสไฟเฉลี่ยผ่านส่วนที่เปิดใช้งาน อัลกอริธึมการจัดองค์กรการทำงานมีดังนี้: 1. การเริ่มต้น เรากำหนดค่าพอร์ตไมโครคอนโทรลเลอร์ตามแผนภาพการเชื่อมต่อตัวบ่งชี้ สำหรับตัวจับเวลา 1 และ 2 โหมดการตอกบัตรภายในจะเปิดใช้งานโดยมีพรีสเกลเลอร์เท่ากับ 16 เปิดใช้งานการขัดจังหวะอุปกรณ์ต่อพ่วงแล้ว 2. เราสร้างตารางตัวสร้างอักขระเพื่อแสดงตัวเลขและตัวอักษรและสัญลักษณ์บางส่วน (ส่วนใหญ่เป็นละติน) บนตัวบ่งชี้ 3. เราสงวนตัวแปรสี่บิตสองตัวไว้ ในที่หนึ่งเราป้อนรหัสดิจิทัลตามลำดับ (สำหรับตัวเลข - เพียงตัวเลข) ของเครื่องหมายที่จำเป็นสำหรับเอาต์พุตตามตารางจากข้อ 2 ค่าที่แปลงจากตารางจะถูกถ่ายโอนไปยังตัวแปรอื่นเพื่อแสดงผลอย่างถาวรบนตัวบ่งชี้ 4. ในการขัดจังหวะจาก TMR0 บิตอักขระจะแสดงตามลำดับตามตาราง ก่อนเปลี่ยนตัวเลข ไฟแสดงจะดับลง การขัดจังหวะแต่ละครั้งจะแสดงหนึ่งหลัก หลังจากนี้ ตัวจับเวลา TMR2 จะถูกรีเซ็ต ค่าสถานะการขัดจังหวะจาก TMR2 จะถูกรีเซ็ต และการขัดจังหวะจากนั้นจะถูกเปิดใช้งาน 5. ในการขัดจังหวะ TMR2 ตัวบ่งชี้จะดับลง และการขัดจังหวะ TMR2 จะถูกปิดใช้งาน 6. ในโปรแกรมหลัก ระยะเวลาขัดจังหวะจาก TMR2 และเวลาที่ตัวบ่งชี้เปิดอยู่ จะถูกปรับโดยการป้อนตัวเลขตั้งแต่ 7 ถึง 255 ในการคำนวณทศนิยมลงในรีจิสเตอร์ PR2 โดยใช้สูตร X(n+1)=2* X(น)+1 ซึ่งส่งผลให้มีการไล่ระดับความสว่างได้หกระดับโดยมีความแตกต่างกัน 2 เท่า ด้วย PR2=255 ระยะเวลาจะสูงสุด (4ms จาก 4ms) โดย PR2=7 ระยะเวลาจะอยู่ที่ประมาณ 0.25ms เพื่อสาธิตหลักการควบคุมนี้ ด้านล่างนี้คือวงจรของ PIC16F628A ราคาไม่แพงและโปรแกรมทดสอบในภาษาแอสเซมบลี ซึ่งจะแสดงคำว่า "ทดสอบ" บนตัวบ่งชี้ เมื่อคุณกดปุ่ม ความสว่างจะปรากฏบนตัวบ่งชี้ (ตามอัตภาพจะเป็นตัวเลขตั้งแต่ 0 ถึง 5) เมื่อกดครั้งต่อๆ ไป ความสว่างจะเปลี่ยนเป็นวงกลม และจะมองเห็นได้ทันทีบนตัวบ่งชี้ ฉันอยากจะเตือนผู้เริ่มต้นทันที: การสร้างแบบจำลองวงจรบนเครื่องจำลองเช่น Proteus จะไม่อนุญาตให้คุณเห็นการเปลี่ยนแปลงของความสว่างเนื่องจากคุณสมบัติของโปรแกรมนี้ (Proteus) จะต้องประกอบต้นแบบของวงจรสำหรับการทดสอบและการทดลองในฮาร์ดแวร์ อย่างไรก็ตาม เพื่อตรวจสอบการจัดวางที่แท้จริงของจอแสดงผลไดนามิก (ยกเว้นการเปลี่ยนแปลงความสว่าง) จะต้องแนบแบบจำลอง Proteus ปริมาณการใช้วงจรที่ความสว่างขั้นต่ำน้อยกว่า 4 mA สูงสุด - ประมาณ 80 mA ไฟล์เก็บถาวรประกอบด้วยโปรแกรมทดสอบในแอสเซมเบลอร์ MPASM เพื่อลดความซับซ้อนของวงจรและเพิ่ม "ขา" สำหรับการดำเนินการต่าง ๆ จะใช้การกำหนดค่าด้วยตัวสร้างภายในและการรีเซ็ตภายใน ในเวลาเดียวกันผู้ที่ใช้โปรแกรมเมอร์ทำเองโดยไม่มีความสามารถในการส่งสัญญาณ MCLR ก่อน Upp อาจประสบปัญหาในการตรวจสอบอ่านและลบในภายหลัง สำหรับผู้ที่ไม่มั่นใจในโปรแกรมเมอร์ และหากต้องการความเสถียรสูงของออสซิลเลเตอร์ คุณสามารถติดตั้งควอตซ์ 4 MHz ตามโครงร่างมาตรฐานโดยมีตัวเลือกในการกำหนดค่า "OSC_XT" หากวงจรสุดท้ายต้องการการขัดจังหวะจากพิน INT0 (RB0) สามารถควบคุมลูกน้ำผ่านพิน RA4 ได้ สำหรับตัวบ่งชี้ที่มี OA ตัวบ่งชี้จะเชื่อมต่อโดยตรงกับพินนี้แม้ว่าจะเปิดอยู่ก็ตาม พินที่ปล่อย RB0 สามารถใช้เพื่อวัตถุประสงค์ที่ต้องการได้ ในโปรแกรมในการขัดจังหวะจาก TMR0 ในกรณีนี้ รหัสจะถูกเพิ่มหลัง "movwf PORTB": และlw b"00000001" bsf PORTA,4 ระงับเครื่องหมายจุลภาค btfsc STATUS,Z โดยคำนึงถึงค่าผกผันใน W bcf PORTA,4 ถ้าบิตที่ 0 = 0, เครื่องหมายจุลภาคไฟ คำอธิบายเล็กๆ น้อยๆ เกี่ยวกับโปรแกรม: หมายเลขเอาต์พุตจะถูกวางไว้ในตัวแปร OUT_ - OUT+3 ตามตัวเลข และจากนั้นในรูทีนย่อย out__ หลังจากการแปลงจะถูกวางไว้ใน OUT_LED แน่นอน คุณสามารถทำได้โดยไม่ต้องใช้ตัวแปร OUT_ และเขียนทุกที่สำหรับเอาต์พุต: Movlw X โทร Table_s movwf OUT_LED อย่างไรก็ตาม ในรูปแบบดั้งเดิม ทุกอย่างเรียบง่ายและชัดเจนกว่ามาก (ฉันวางไว้ใน OUT_ แล้วลืมไป) และด้วยเอาต์พุตหลายรายการจากที่ต่างๆ ในโปรแกรม ทำให้ได้รับการประหยัดโค้ด (4 คำต่อ 1 เอาต์พุต) - ฉันคิดว่ามันเป็น การชดเชยที่ดีสำหรับ RAM พิเศษ 4 ไบต์ เช่นเดียวกับการแสดงเครื่องหมายจุลภาคผ่านตัวแปร comma_ ในรูทีนย่อยของตาราง Table_s มีการใช้มาตรการเพื่อให้แน่ใจว่าการทำงานถูกต้อง เมื่อวางในตำแหน่งใดๆ ในหน่วยความจำโปรแกรมโดยไม่มีข้อจำกัดเกี่ยวกับจุดตัดของบล็อกขนาด 256 ไบต์ ตัวแปร Pause_ ในการขัดจังหวะ TMR0 ใช้เพื่อตั้งค่าช่วงเวลาเป็น 4 ms ฉันคิดว่าที่เหลือชัดเจนจากอัลกอริธึมและความคิดเห็น ป.ล. สำหรับตัวเลข 2 หรือ 3 หลักในโปรแกรมคุณต้องทำการเปลี่ยนแปลงเพียงเล็กน้อยซึ่งฉันคิดว่าเป็นไปได้แม้กระทั่งสำหรับผู้เริ่มต้น ในการควบคุมตัวบ่งชี้ที่มีตัวเลขตั้งแต่ 5 ถึง 8 จำเป็นต้องใช้คอนโทรลเลอร์ที่มีพินจำนวนมากหรือควบคุมตัวเลขเพื่อใช้ตัวถอดรหัส 3 x 8 ในกรณีแรก การเปลี่ยนแปลงในโปรแกรมก็มีเพียงเล็กน้อยเช่นกัน (ใช้พอร์ตอื่นแทนพอร์ต A เป็นต้น) หากใช้ตัวถอดรหัส โปรแกรมที่เกี่ยวข้องกับการขัดจังหวะ TMR0 จะเปลี่ยนไปค่อนข้างจริงจัง
มาดูบทเรียนต่อที่การแสดงผลแบบไดนามิก หากคุณได้ศึกษาตัวบ่งชี้คงที่อย่างละเอียด คุณจะรู้ว่าตัวบ่งชี้ส่วนนั้นเป็นชุดของไฟ LED ในการเชื่อมต่อตัวบ่งชี้คุณต้องมีพินไมโครคอนโทรลเลอร์ 7 ตัว แต่ทันใดนั้น เราจำเป็นต้องใช้ตัวบ่งชี้หลายตัว เช่น 2, 3, 4... จากนั้นเราจะต้องมีขา 14, 21, 28 ขาและมีขาไม่เพียงพอ... จอแสดงผลแบบไดนามิกมาช่วยเราที่นี่ งานหลักของการแสดงผลแบบไดนามิกคือการลดจำนวนพินไมโครคอนโทรลเลอร์ที่ใช้ โปรดทราบว่าในแผนภาพมี 9 ขา ไม่ใช่ 14 ขาที่เกี่ยวข้อง ขาควบคุมทั้งหมดเชื่อมต่อแบบขนาน โดยทั่วไปแล้ว การออกแบบนี้ใช้งานได้ดังนี้ ขั้นแรก การกำหนดค่าหมายเลขแรกจะถูกส่งออกไปยังบัสทั่วไปและเราเปิด PB1 ไฟสัญญาณแรกจะสว่างขึ้นพร้อมหมายเลขที่ต้องการ จากนั้นเราจะปิดมัน ส่งออกการกำหนดค่าของหมายเลขที่สองไปยังบัสข้อมูล ไฟสัญญาณที่สอง แล้วปิด รายละเอียดเพิ่มเติม ในตอนแรกทุกอย่างถูกปิด PORTB=0x00; PORTD=0xFF; เนื่องจากวงจรมีขั้วบวก “+” ทั่วไป ถัดไป การกำหนดค่าของหมายเลขแรก เช่น "0" จะถูกส่งไปยัง PORTD จากการแสดงแบบคงที่เราจำได้ว่า:
กรณีที่ 0: ( PORTD=0xC0; แตก; ) แต่โปรดทราบว่า "+" เชื่อมต่อกับ PORTB.1 เช่น หากต้องการส่องสว่างส่วนใดส่วนหนึ่งคุณต้องเปิดขา PORTB.1=1 ในช่วงเวลาที่สองเราจะปิดทุกอย่างอีกครั้งส่งการกำหนดค่าของหมายเลขที่สองและเปิดตัวบ่งชี้ที่สองในครั้งนี้ ต่อไปเราจะทำซ้ำ ที่ความถี่สูง สายตามนุษย์ไม่สามารถมองเห็นสวิตช์เหล่านี้ได้ และไฟแสดงสถานะจะสว่างตลอดเวลา ไม่แนะนำให้ใช้ความถี่ที่ทวีคูณของ 50Hz ในโปรเจ็กต์ทดสอบของฉัน ฉันใช้ 120Hz ตัวจับเวลาถูกตั้งไว้ที่ความถี่ 1 MHz รหัสถูกประมวลผลในการขัดจังหวะตัวจับเวลา 1 การขัดจังหวะเรียกว่า 240 ครั้งต่อวินาที เนื่องจากมีตัวบ่งชี้สองตัว ดังนั้นเราจึงกด 1,000,000/240=4166 หรือ 0x1046 ลงในรีจิสเตอร์การเปรียบเทียบ ไม่สามารถจับคู่ Proteus กับตัวบ่งชี้แบบไดนามิกได้ แต่จะทำงานได้ทันทีบนฮาร์ดแวร์ ใส่ใจ!!! เมื่อเชื่อมต่อตัวบ่งชี้ ขอแนะนำให้ติดตัวต้านทานจำกัดกระแสเข้ากับแต่ละส่วน แทนที่จะติดตัวต้านทานทั่วไป นอกจากนี้ฉันขอแนะนำให้เชื่อมต่อสายตัวบ่งชี้ทั่วไปผ่านทรานซิสเตอร์ไม่เช่นนั้นคุณอาจไหม้ขาได้ สำหรับวงจรที่มีขั้วบวกร่วม สำหรับวงจรแคโทดทั่วไป ฉันใช้ตัวจับเวลาจากโปรเจ็กต์ก่อนหน้าเป็นเฟิร์มแวร์ทดสอบ วิดีโอแสดงการทำงานของเฟิร์มแวร์ ตัวบ่งชี้มักจะอยู่ในตำแหน่งที่สะดวกสำหรับการดูข้อมูลที่แสดงอยู่ ส่วนที่เหลือของวงจรดิจิทัลสามารถวางอยู่บนแผงวงจรพิมพ์อื่นๆ ได้ เมื่อจำนวนตัวบ่งชี้เพิ่มขึ้น จำนวนตัวนำระหว่างบอร์ดตัวบ่งชี้และบอร์ดดิจิทัลก็จะเพิ่มขึ้น สิ่งนี้นำไปสู่ความไม่สะดวกในการพัฒนาการออกแบบและการทำงานของอุปกรณ์ เหตุผลเดียวกันนี้ทำให้ต้นทุนเพิ่มขึ้น จำนวนตัวนำที่เชื่อมต่อสามารถลดลงได้โดยการทำให้ตัวบ่งชี้ทำงานในโหมดพัลส์ ดวงตาของมนุษย์มีความเฉื่อยและหากคุณบังคับให้ตัวบ่งชี้แสดงข้อมูลทีละตัวด้วยความเร็วสูงเพียงพอ ดูเหมือนว่าตัวบ่งชี้ทั้งหมดจะแสดงข้อมูลอย่างต่อเนื่อง เป็นผลให้สามารถส่งข้อมูลที่แสดงผ่านตัวนำเดียวกันสลับกันได้ โดยปกติอัตราการรีเฟรช 50 Hz ก็เพียงพอแล้ว แต่ควรเพิ่มความถี่นี้เป็น 100 Hz จะดีกว่า ลองดูที่บล็อกไดอะแกรมของไฟ LED แสดงสถานะเจ็ดส่วนที่แสดงในรูปที่ 1 วงจรนี้สามารถให้ตัวบ่งชี้แบบไดนามิกของข้อมูลดิจิตอลเอาท์พุต รูปที่ 1 แผนภาพบล็อกของการบ่งชี้แบบไดนามิก ในแผนภาพที่แสดงในรูปที่ 1 จะแสดงตัวเลขดิจิทัลสี่หลัก แต่ละบิตจะเชื่อมต่อสั้น ๆ กับอินพุตสวิตช์ของตัวเอง ตัวสร้างใช้เพื่อกำหนดความเร็วในการอัปเดตข้อมูลตัวบ่งชี้ ตัวนับไบนารีจะสร้างสถานะสี่สถานะของวงจรตามลำดับ และจ่ายไฟสำรองให้กับตัวบ่งชี้เจ็ดส่วนผ่านปุ่มต่างๆ เป็นผลให้เมื่อสวิตช์ส่งรหัสทศนิยมไบนารีจากอินพุต A ไปยังอินพุตของตัวถอดรหัสเจ็ดส่วน รหัสนี้จะปรากฏบนตัวบ่งชี้ HL1 เมื่อสวิตช์จ่ายรหัสไบนารี่ทศนิยมจากอินพุต B ไปยังอินพุตของตัวถอดรหัสเจ็ดส่วน รหัสนี้จะแสดงบนตัวบ่งชี้ HL2 และต่อๆ ไปเป็นวงจร อัตราการอัพเดตข้อมูลในรูปแบบที่พิจารณาจะน้อยกว่าความถี่ของเครื่องกำเนิดถึงสี่เท่า นั่นคือเพื่อให้ได้ความถี่การกะพริบของตัวบ่งชี้ที่ 100 Hz จำเป็นต้องใช้ความถี่ของเครื่องกำเนิดที่ 400 Hz กี่ครั้งแล้วที่เราลดจำนวนตัวนำเชื่อมต่อลง? ขึ้นอยู่กับตำแหน่งที่เราวาดหน้าตัดของวงจร หากเราปล่อยให้มีเพียงตัวบ่งชี้บนแผงบ่งชี้ การดำเนินการของพวกเขาจะต้องใช้สัญญาณข้อมูล 7 รายการสำหรับเซ็กเมนต์และสัญญาณสวิตช์สี่สัญญาณ มีตัวนำทั้งหมด 11 ตัว ในวงจรแสดงผลแบบคงที่เราจะต้องมีตัวนำ 7 × 4 = 28 ตัว อย่างที่คุณเห็น การชนะนั้นชัดเจน เมื่อใช้หน่วยแสดงผลแบบ 8 บิต อัตราขยายจะยิ่งใหญ่ยิ่งขึ้น จะได้รับมากยิ่งขึ้นหากส่วนตัดขวางของวงจรถูกวาดไปตามอินพุตของตัวบ่งชี้ ในกรณีนี้หน่วยแสดงผลสี่หลักจะต้องมีตัวนำสัญญาณเพียงหกตัวและตัวนำไฟฟ้าวงจรสองตัว อย่างไรก็ตาม จุดตัดขวางของวงจรแสดงผลแบบไดนามิกดังกล่าวมีการใช้งานน้อยมาก ทีนี้มาคำนวณกระแสที่ไหลผ่านแต่ละส่วนของ LED เมื่อมันสว่างขึ้น ในการทำเช่นนี้เราจะใช้วงจรการไหลของกระแสที่เท่ากันผ่านส่วนตัวบ่งชี้ส่วนใดส่วนหนึ่ง แผนภาพนี้แสดงในรูปที่ 2 ตามที่กล่าวไว้ข้างต้น LED ต้องใช้กระแสไฟ 3 ถึง 10 mA สำหรับการทำงานปกติ มาตั้งค่ากระแสไฟ LED ขั้นต่ำเป็น 3 mA อย่างไรก็ตามในโหมดพัลส์ของการทำงาน ความสว่างของตัวบ่งชี้จะลดลง N ครั้ง โดยที่ค่าสัมประสิทธิ์ N เท่ากับรอบการทำงานของพัลส์ปัจจุบันที่จ่ายให้กับตัวบ่งชี้นี้ หากเราจะรักษาความสว่างของการเรืองแสงไว้เท่าเดิม เราต้องเพิ่มขนาดของกระแสพัลส์ที่ไหลผ่านเซ็กเมนต์เป็น N เท่า สำหรับตัวบ่งชี้แปดหลัก ค่าสัมประสิทธิ์ N เท่ากับแปด ให้เราเลือกกระแสคงที่ผ่าน LED เท่ากับ 3 mA ก่อน จากนั้นเพื่อรักษาความสว่างเท่าเดิมของ LED ในตัวบ่งชี้แปดหลักจะต้องใช้กระแสพัลส์: ฉัน seg din = ฉัน seg สถิติ× เอ็น= 3mA×8 = 24mAมีเพียงไมโครวงจรดิจิตอลบางชุดเท่านั้นที่สามารถจ่ายกระแสดังกล่าวได้ยาก สำหรับซีรีย์ไมโครวงจรส่วนใหญ่ จำเป็นต้องใช้แอมพลิฟายเออร์ที่สร้างจากสวิตช์ทรานซิสเตอร์ ตอนนี้เรามาพิจารณากระแสที่จะไหลผ่านสวิตช์ที่จะเปลี่ยนพลังงานไปยังแต่ละบิตของหน่วยแสดงผลแปดบิต ดังที่เห็นได้จากแผนภาพที่แสดงในรูปที่ 2 กระแสจากส่วนใดๆ ของตัวบ่งชี้สามารถไหลผ่านคีย์ได้ เมื่อแสดงหมายเลข 8 จะต้องสว่างทั้งเจ็ดส่วนของตัวบ่งชี้ซึ่งหมายความว่ากระแสพัลส์ที่ไหลผ่านคีย์ในขณะนี้สามารถกำหนดได้ดังนี้: ฉัน cl = ฉัน segดิ๊ง× ไม่มี= 24mA×7 = 168mAกระแสนี้เป็นยังไงบ้างคะ?! ในวงจรวิทยุสมัครเล่นฉันมักจะเจอวิธีแก้ปัญหาที่กระแสสวิตชิ่งถูกนำโดยตรงจากเอาต์พุตของตัวถอดรหัสซึ่งไม่สามารถสร้างกระแสได้มากกว่า 20 mA และฉันถามตัวเองด้วยคำถาม - จะมองหาตัวบ่งชี้ดังกล่าวได้ที่ไหน ในความมืดสนิท? ผลลัพธ์ที่ได้คือ “อุปกรณ์มองเห็นตอนกลางคืน” ซึ่งก็คืออุปกรณ์ที่อ่านค่าได้ซึ่งมองเห็นได้ในที่มืดสนิทเท่านั้น ตอนนี้เรามาดูแผนผังของหน่วยแสดงผลที่ได้ ดังแสดงในรูปที่ 3 รูปที่ 3 แผนผังของหน่วยแสดงผลแบบไดนามิก ตอนนี้เราได้รับวงจรแสดงผลแบบไดนามิกแล้ว เราจึงสามารถหารือเกี่ยวกับข้อดีและข้อเสียของมันได้ ข้อได้เปรียบที่ไม่อาจปฏิเสธได้ของการแสดงผลแบบไดนามิกคือสายเชื่อมต่อจำนวนน้อยซึ่งทำให้ขาดไม่ได้ในบางกรณี เช่น การทำงานกับตัวบ่งชี้เมทริกซ์ ข้อเสียคือการมีกระแสพัลส์ขนาดใหญ่และเนื่องจากตัวนำใด ๆ เป็นเสาอากาศตัวบ่งชี้แบบไดนามิกจึงทำหน้าที่เป็นแหล่งสัญญาณรบกวนที่ทรงพลัง แหล่งที่มาของการรบกวนอีกประการหนึ่งคือแหล่งจ่ายไฟ โปรดทราบว่าขอบนำของพัลส์สวิตชิ่งนั้นสั้นมาก ดังนั้นส่วนประกอบฮาร์มอนิกจึงครอบคลุมช่วงความถี่วิทยุจนถึงคลื่นที่สั้นมาก ดังนั้นการใช้ตัวบ่งชี้แบบไดนามิกทำให้สามารถลดจำนวนสายเชื่อมต่อระหว่างอุปกรณ์ดิจิทัลและตัวบ่งชี้ได้ แต่ในขณะเดียวกันก็เป็นแหล่งสัญญาณรบกวนที่ทรงพลังดังนั้นจึงไม่เป็นที่พึงปรารถนาในการใช้งานในอุปกรณ์รับวิทยุ ตัวอย่างเช่น หากจำเป็นต้องใช้ตัวบ่งชี้เมทริกซ์ ด้วยเหตุผลบางประการ จำเป็นต้องใช้ตัวบ่งชี้แบบไดนามิก จึงต้องดำเนินมาตรการทั้งหมดเพื่อระงับสัญญาณรบกวน มาตรการในการระงับการรบกวนจากตัวบ่งชี้แบบไดนามิก ได้แก่ การป้องกันตัวเครื่อง สายเคเบิลเชื่อมต่อ และแผง ใช้สายเชื่อมต่อที่มีความยาวขั้นต่ำโดยใช้ตัวกรองแหล่งจ่ายไฟ เมื่อทำการป้องกันบล็อก อาจจำเป็นต้องป้องกันตัวบ่งชี้ด้วยตนเอง ในกรณีนี้มักใช้ตาข่ายโลหะ ตารางนี้สามารถเพิ่มความคมชัดของอักขระที่แสดงไปพร้อมๆ กัน วรรณกรรม: พร้อมกับอ่านบทความ "การแสดงผลแบบไดนามิก": ตัวชี้วัดได้รับการออกแบบเพื่อแสดงข้อมูลประเภทต่างๆ แก่บุคคล ข้อมูลประเภทที่ง่ายที่สุดคือ... ตัวบ่งชี้การปล่อยก๊าซใช้เพื่อระบุข้อมูลบิตและเพื่อแสดงข้อมูลทศนิยม เมื่อสร้างตัวบ่งชี้ทศนิยม แคโทด... ปัจจุบันมีการใช้ไฟ LED เกือบทุกที่เพื่อแสดงข้อมูลไบนารี นี่เป็นเพราะ... หลักการทำงานของตัวบ่งชี้ผลึกเหลว... โหมดการทำงานของตัวบ่งชี้ผลึกเหลว... การสร้างภาพสี... |
การแสดงผลแบบไดนามิกเป็นหนึ่งในปัญหาที่โปรแกรมเมอร์ไมโครคอนโทรลเลอร์มือใหม่ต้องเผชิญ มีการพูดถึงเรื่องนี้มากมาย แต่ฉันตัดสินใจสำรองข้อมูลสิ่งที่ทราบด้วยรูปภาพและตัวอย่างซอร์สโค้ดใน C เพื่อให้เชี่ยวชาญวิธีการแสดงผลนี้ได้ง่ายขึ้น 1 พื้นฐานหรือบทนำก่อนอื่น เรามากำหนดคำศัพท์ที่เราจะใช้ตลอดทั้งบทความกันก่อน หากคุณต้องการควบคุมจอแสดงผลที่ประกอบด้วยเจ็ดเซกเมนต์ที่คุ้นเคย ก็ไม่ทำให้เกิดปัญหาใดๆ - สามารถพิจารณาได้ว่าเป็นไฟ LED อิสระ 8 ดวง หากคุณต้องการแสดงข้อมูลมากกว่าอักขระตัวเดียวปัญหาเริ่มต้นขึ้น: 2 ตำแหน่งที่คุ้นเคยประกอบด้วย LED 16 ดวง, สาม - 24 เป็นต้น นั่นคือสำหรับการแสดงผลสามหลักอาจมีพินไมโครคอนโทรลเลอร์ไม่เพียงพอ กล่าวถึงการแสดงตัวเลข 6 หลักขึ้นไป และโดยเฉพาะอย่างยิ่งตัวบ่งชี้เมทริกซ์ เพื่อความง่าย ให้เราตกลงกันว่าตัวชี้วัดทั้งหมดของเรามีแคโทดร่วม วิธีแก้ปัญหานั้นค่อนข้างง่าย: เชื่อมต่อเทอร์มินัลของส่วนตัวบ่งชี้ทั้งหมดเข้าด้วยกัน ตอนนี้ หากคุณต้องการส่งข้อมูลไปยังตำแหน่งแรกที่คุ้นเคย คุณควรใช้ระดับที่ต้องการกับเส้นเซกเมนต์ และเชื่อมต่อเอาต์พุตร่วมของตัวบ่งชี้แรกเข้ากับสายร่วมของวงจร แน่นอนว่าต้องมีระดับสูงที่แคโทดร่วมของตัวบ่งชี้อื่นๆ ทั้งหมด แน่นอนว่าส่วนที่จำเป็นของตัวบ่งชี้แรกจะสว่างขึ้น สำหรับส่งออกไปยังวินาทีที่สาม ฯลฯ ตัวชี้วัดก็ควรทำเช่นเดียวกัน กล่าวคือ ด้วยการใช้ศูนย์ลอจิคัลกับแคโทดทั่วไปตัวใดตัวหนึ่ง เราจะเลือกตัวเลขที่แสดงในปัจจุบัน และสถานะของเส้นเซกเมนต์จะกำหนดสัญลักษณ์ที่มองเห็นได้ เพื่อให้มองเห็นทั้งจอแสดงผลเรืองแสงอย่างต่อเนื่อง ควรเปลี่ยนตัวเลขอย่างรวดเร็ว - มากกว่า 25 ครั้งต่อวินาที อย่างที่คุณเห็น ระดับของเอาต์พุตทั้งหมด (ซึ่งในทางกลับกัน มีขนาดเล็กกว่าแนวทางปกติอย่างมาก) มีการเปลี่ยนแปลงอย่างต่อเนื่อง เช่น ไม่มีระดับคงที่ แต่เป็นระดับไดนามิก ดังนั้นชื่อของวิธีการบ่งชี้ - ไดนามิก รูปภาพที่แสดงแบบไดนามิก 2 ประเภทของการใช้งานฮาร์ดแวร์2.1 เมทริกซ์แบบแบนหากเราแยกจากตัวบ่งชี้เจ็ดส่วน จอแสดงผลของเราสามารถแสดงเป็นเมทริกซ์ของ LED แต่ละดวง ซึ่งแอโนดจะรวมกันเป็นแถวของเมทริกซ์ และแคโทดเป็นคอลัมน์ จริงๆแล้วมันเป็นเช่นนั้นเอง แน่นอนว่า โดยการระบุระดับที่ต้องการให้กับแถวและคอลัมน์ของเมทริกซ์ของเรา เราสามารถทำให้ส่วน LED พื้นฐานใดๆ สว่างขึ้นได้ (หรือที่เรียกว่าพิกเซล ซึ่งเป็นคำแบบดั้งเดิมที่เกี่ยวข้องกับการแสดงผลเมทริกซ์) ขึ้นอยู่กับว่าเราเปลี่ยนระดับของแถวและคอลัมน์อย่างไร เราสามารถรับการแสดงผลแบบไดนามิกได้หลายประเภท:
เราดูตัวเลือกคอลัมน์ในบทที่แล้ว ตัวเลือกแบบแถวต่อแถวจะแตกต่างจากตัวเลือกแถวและคอลัมน์ของเมทริกซ์ของเราเท่านั้นที่สลับกัน วิธีการแบ่งส่วนต่อส่วนหมายความว่าในเวลาใดก็ตาม มีเพียงแถวเดียวและหนึ่งคอลัมน์เท่านั้นที่มีระดับที่จำเป็นในการส่องสว่าง LED นั่นคือในเวลาใดก็ตาม ไฟ LED เดียวของเมทริกซ์ทั้งหมดสามารถสว่างขึ้นได้ (ไม่เหมือนกับตัวเลือกก่อนหน้า เมื่อทั้งแถวหรือทั้งคอลัมน์สามารถสว่างพร้อมกันได้) วิธีนี้ชวนให้นึกถึงการสแกนทีวีเมื่อลำแสงวิ่งไปทั่วทั้งหน้าจอโดยให้แสงฟอสเฟอร์ในตำแหน่งที่เหมาะสม ตัวเลือกแบบผสมตามชื่อที่แนะนำคือระดับ "ที่ใช้งานอยู่" พร้อมกันสามารถปรากฏได้ในหลายแถวและคอลัมน์ในคราวเดียว สองตัวเลือกแรกนั้นใช้งานง่ายมากดังนั้นจึงมีการใช้กันอย่างแพร่หลาย ตัวเลือกที่สามใช้ไม่บ่อยเพราะว่า ต้องการอัตราการอัปเดตข้อมูลที่สูงกว่าในแถวและคอลัมน์ และกระแสเฉลี่ยผ่านส่วน (เช่น ความสว่างของส่วน) ในกรณีนี้จะต่ำกว่าส่วนอื่นๆ อย่างมาก วิธีการผสมครั้งสุดท้ายเป็นวิธีที่พบได้น้อยที่สุดแม้ว่าจะมีคุณสมบัติเชิงบวกหลายประการก็ตาม ประการแรก วิธีนี้กำหนดให้ใช้แหล่งกำเนิดกระแสไฟฟ้าที่เสถียรในวงจรแถวและคอลัมน์ มิฉะนั้น ความสว่างของส่วนที่ส่องสว่างจะขึ้นอยู่กับจำนวนรวมของมันอย่างหลีกเลี่ยงไม่ได้ และการคำนวณการรวมสัญญาณบนแถวและคอลัมน์ไม่ใช่เรื่องง่าย 2.2 เมทริกซ์หลายมิติตัวอย่างที่เราพิจารณาถือว่ามีการใช้จอแสดงผลขาวดำ เช่น ประกอบด้วยไฟ LED สีเดียว จะทำอย่างไรถ้าคุณต้องการรับจอแสดงผลหลายสีเช่นจาก LED RGB? มีสองวิธีที่เป็นไปได้ ประการแรกคือการเพิ่มจำนวนแถว (หรือคอลัมน์) ของเมทริกซ์ของเรา โดยถือว่า LED RGB แต่ละดวงเป็น LED อิสระ 3 ดวง ข้อเสียใหญ่ของวิธีนี้คือจำนวนแถว (หรือคอลัมน์) เพิ่มขึ้น 3 เท่า ตัวอย่างง่ายๆ แสดงให้เห็นได้อย่างง่ายดายว่าสิ่งนี้มีความหมายในทางปฏิบัติอย่างไร: การใช้ไมโครคอนโทรลเลอร์ไมโครคอนโทรลเลอร์ 8 บิตสองตัว เราสามารถมีเมทริกซ์เซกเมนต์ขาวดำ 8x8 หรือเมทริกซ์สี 4x4 ได้ ยอมรับว่าในกรณีที่สอง เป็นไปไม่ได้เลยที่จะแสดงสิ่งที่เข้าใจได้... วิธีที่สองคือการย้ายจากเมทริกซ์ส่วน "แบน" ไปเป็นเมทริกซ์ "หลายมิติ" หากสัญญาณของแต่ละบรรทัดถูกส่งผ่านมัลติเพล็กเซอร์ 1x3 เราสามารถจินตนาการได้ว่าระบบการแสดงผลของ LED RGB เป็นเมทริกซ์อิสระ 3 ตัวของมิติดั้งเดิม: แต่ละเมทริกซ์ประกอบด้วย LED ที่มีสีเดียวกัน และเราเลือกเมทริกซ์ที่ต้องการโดยใช้มัลติเพล็กเซอร์ สัญญาณควบคุม รูปภาพอธิบายสิ่งที่พูด แน่นอนว่าในกรณีของเมทริกซ์หลายมิตินั้น จำเป็นต้องมีบรรทัดควบคุมเพิ่มเติมด้วย อย่างไรก็ตาม จำนวนนี้มีขนาดไม่ใหญ่นัก: บนพอร์ตคอนโทรลเลอร์สองพอร์ตเดียวกัน เราจะได้รับหน้าจอสีขนาด 7x7 ได้!!! 2.3 วิธีลดมิติของเมทริกซ์หากจำนวนพินของไมโครคอนโทรลเลอร์มีจำกัด เราจะต้องหาวิธีลดจำนวนแถวและคอลัมน์ของเมทริกซ์ แน่นอนว่าปาฏิหาริย์จะไม่เกิดขึ้น และในกรณีนี้ เราจะต้องจ่ายเงินโดยใช้ไมโครวงจรเพิ่มเติมนอกเหนือจากไมโครคอนโทรลเลอร์ ดังที่คุณอาจเดาได้ ที่นี่ คุณสามารถใช้วิธีเมทริกซ์ "หลายมิติ" ที่กล่าวไว้ก่อนหน้านี้ได้ - ท้ายที่สุดจะไม่มีใครห้ามเราไม่ให้ใช้ LED สีเดียวจำนวนสามเท่าแทนที่จะเป็น LED RGB สิ่งสำคัญคือการจัดเรียงให้เหมาะสม... ดังนั้น เราสามารถลดขนาดของเมทริกซ์ได้โดยใช้:
เราได้พบกับมัลติเพล็กเซอร์แล้วก่อนหน้านี้ ตัวถอดรหัสอย่างที่คุณเดาได้ มันไม่ได้แตกต่างโดยพื้นฐานจากมัลติเพล็กเซอร์ ควรเพิ่มเพียงว่าโดยการใช้ตัวถอดรหัส/มัลติเพล็กเซอร์สำหรับทั้งแถวและคอลัมน์ เป็นไปได้ที่จะลดขนาดเมทริกซ์ตามทั้งสองมิติพร้อมกัน แต่ในกรณีนี้ อาจจำเป็นต้องใช้เฉพาะตัวบ่งชี้ไดนามิกแบบเซ็กเมนต์ต่อเซกเมนต์เท่านั้น พร้อมข้อเสียทั้งหมด Shift register สามารถช่วยได้ดีกว่าตัวถอดรหัส พิจารณาแผนภาพในรูปด้านล่าง จะเห็นได้ง่ายว่าจำนวนแถวและคอลัมน์ใดๆ ก็ตามจะต้องเพิ่มจำนวนรีจิสเตอร์เท่านั้น และจำนวนสายควบคุมไมโครคอนโทรลเลอร์ที่เกี่ยวข้องจะยังคงเท่าเดิม! ข้อเสียเล็กน้อยของวิธีนี้คือเมื่อจำนวนการลงทะเบียนในห่วงโซ่เพิ่มขึ้น ความเร็วของการส่งออกข้อมูลตามลำดับจะต้องเพิ่มขึ้น ซึ่งไม่ใช่เรื่องง่ายเสมอไปที่จะบรรลุผล ตัวอย่างเช่น ไมโครคอนโทรลเลอร์ทั่วไปในตระกูล เอวีอาร์แทบจะเป็นไปไม่ได้เลยที่จะเกินความเร็วเอาต์พุตอนุกรมที่ 10 เมกะบิต/วินาที ในทางกลับกัน หากคุณใช้ตัวควบคุมอื่นที่สามารถส่งสัญญาณออกได้เร็วขึ้น ปัญหาของลำดับที่แตกต่างกันอาจเกิดขึ้น: การแพร่กระจายของสัญญาณนาฬิกาความถี่สูงไปตามเส้นยาว (และด้วยการลงทะเบียนจำนวนมาก ย่อมเป็นหนึ่งเดียวอย่างหลีกเลี่ยงไม่ได้ ) เกิดขึ้นแตกต่างไปจากความถี่ต่ำอย่างสิ้นเชิง ดังนั้นจึงจำเป็นต้องมีมาตรการพิเศษในการวางแผงวงจรพิมพ์และสิ่งอื่น ๆ ที่เราจะไม่พิจารณาในบทความนี้ 3 วิธีการใช้งานซอฟต์แวร์เราจะไม่พิจารณาการใช้งานซอฟต์แวร์ของตัวเลือกการแสดงผลไดนามิกทั้งหมดที่กล่าวถึง - นี่จะทำให้บทความขยายตัวอย่างไม่มีเหตุผล เราจะจำกัดตัวเองไว้เพียงสามตัวอย่างที่ได้รับความนิยมมากที่สุด: เมทริกซ์แบบเรียบที่ควบคุมแถวและคอลัมน์ได้โดยตรง แบบเดียวกับการใช้ตัวถอดรหัส และสุดท้ายคือตัวแปรที่ใช้ shift register ในทุกกรณี จะมีการให้ความสนใจเป็นพิเศษกับความแตกต่างทั้งหมดของการใช้งานซอฟต์แวร์ นั่นคือรหัส C จะมาพร้อมกับคำอธิบายเฉพาะในกรณีที่สิ่งนี้เกิดขึ้นพร้อมกับความตั้งใจของผู้เขียนเท่านั้น และไม่ใช่เลยกับระดับการฝึกอบรมของคุณ . จากนี้ฉันบอกเป็นนัยว่าคุณควรรู้พื้นฐานของ C โดยไม่มีฉัน สำหรับตัวอย่างทั้งหมด เราจะยอมรับว่าจอแสดงผลของเราสร้างขึ้นจากตัวบ่งชี้เจ็ดส่วนที่มีแคโทดร่วม 3.1 วิธีที่ง่ายที่สุดเห็นได้ชัดว่าโปรแกรมจะสะดวกที่สุดในการมีอาเรย์ที่แน่นอนซึ่งเนื้อหาจะกำหนดได้อย่างชัดเจนว่าส่วนใดที่บริเวณที่คุ้นเคยของจอแสดงผลสว่างขึ้นซึ่งเป็นอะนาล็อกชนิดหนึ่งของ RAM บนหน้าจอ ให้เราแนะนำคำจำกัดความของค่าคงที่ต่อไปนี้: #define SCR_SZ 6 /* จำนวนการแสดงความคุ้นเคย */ #define ROWS PORTB /* แสดงพอร์ต "แถว" เช่น การจัดการส่วน */ #define COLS PORTD /* พอร์ตการจัดการ "คอลัมน์" เช่น แคโทดทั่วไป */ ตอนนี้เรามาประกาศอาร์เรย์ของหน้าจอ: ถ่าน SCR ที่ไม่ได้ลงนาม; ขั้นแรก เราจะถือว่าแต่ละองค์ประกอบของอาเรย์สอดคล้องกับความคุ้นเคยของจอแสดงผล และแต่ละบิตขององค์ประกอบนี้สอดคล้องกับส่วนเฉพาะของตัวบ่งชี้ บิตใดที่สอดคล้องกับเซ็กเมนต์ใด - ในกรณีนี้ไม่สำคัญ เช่นเดียวกับที่ไม่สำคัญว่าบิตเหล่านี้จะถูกตั้งค่าเป็นไบต์ของอาร์เรย์ของเราอย่างไร เราจะถือว่าตอนนี้บิตเหล่านั้นอยู่ที่นั่นแล้ว เพื่อความง่าย เราจะถือว่าแคโทดทั่วไปเชื่อมต่อกับหมุดพอร์ต โคลสตามลำดับ: บิตที่มีนัยสำคัญน้อยที่สุดคือตัวบ่งชี้ด้านขวาสุด จากนั้นบิตที่สอง จากนั้นบิตที่สาม เป็นต้น เราจะทำให้อาร์เรย์นี้ "แสดงผล" บนจอแสดงผลได้อย่างไร? มาเขียนโค้ดต่อไปนี้: < SCR_SZ; pos++){ ROWS = SCR; COLS = ~(1 << pos); } มันจะทำหน้าที่ที่ต้องการได้หรือไม่? ใช่. แต่มันก็ไม่ดี ก่อนอื่น โปรดทราบว่าเราไม่สามารถควบคุมความเร็วในการอัปเดตเนื้อหาของแถวและคอลัมน์ได้ ประการที่สอง โปรดทราบว่าเมื่อถึงเวลาที่มีการพิมพ์องค์ประกอบอาร์เรย์ใหม่ แถวบนเส้น โคลสความหมายเก่ายังคงอยู่! สิ่งนี้จะนำไปสู่อะไร? ยิ่งไปกว่านั้น เพียงเสี้ยววินาที พื้นที่คุ้นเคยจะแสดงส่วนของพื้นที่คุ้นเคยใกล้เคียง เช่น บางส่วนจะถูกส่องสว่างอย่างลวงตา คุณสามารถหลีกเลี่ยงผลกระทบนี้ได้โดยทำสิ่งนี้: ก่อนที่จะอัปเดตเนื้อหา แถวดับสถานที่คุ้นเคยที่เคยอยู่เดิมเสมอ เพื่อไม่ให้กังวลกับการพิจารณาความคุ้นเคยก่อนหน้านี้คุณสามารถดับทุกอย่างได้ในคราวเดียว ดังนั้นโค้ดของเราจึงมีรูปแบบดังนี้: ถ่าน pos ที่ไม่ได้ลงนาม; ในขณะที่ (1) สำหรับ (pos = 0; pos< SCR_SZ; pos++){ COLS = 0xFF; ROWS = SCR; COLS = ~(1 << pos); delay(); } เราได้เพิ่มการเว้นว่างของจอแสดงผลทั้งหมดก่อนที่จะอัปเดตสถานะของเส้นส่วน (โดยการส่งแคโทดทั่วไปให้สูง เราจะปิดตัวบ่งชี้โดยไม่คำนึงถึงสิ่งที่มีอยู่ในขั้วบวก) และทำให้เกิดความล่าช้าเมื่อสิ้นสุดรอบ ตอนนี้จอแสดงผลจะทำงานได้ดีขึ้นมาก แต่เราเขียนโปรแกรมดีแล้วหรือยัง? อนิจจาไม่มี ความจริงก็คือวงจรการแสดงผลที่ไม่มีที่สิ้นสุด ในขณะที่มันจะไม่ยอมให้เราทำอะไรอีก เราจะมีโปรแกรมประเภทไหนที่แสดงผลได้เฉพาะบนอินดิเคเตอร์?! แน่นอนว่าทุกอย่างไม่ได้แย่ 100% เนื่องจากสิ่งที่มีประโยชน์สามารถทำได้โดยใช้การขัดจังหวะ... และแทนที่จะล่าช้า ล่าช้า()คุณสามารถดำเนินการบางอย่างได้... แต่ทั้งหมดนี้คดเคี้ยวมาก: ไม่แนะนำให้ทำสิ่งที่ซับซ้อนและยุ่งยากในตัวจัดการขัดจังหวะ ในทางกลับกัน หากคุณทำสิ่งที่ซับซ้อนและยุ่งยากแทนที่จะล่าช้า เป็นการยากที่จะรับประกันเวลาในการคำนวณเท่ากัน มิฉะนั้นปรากฎว่าสถานที่ที่คุ้นเคยเรืองแสงในช่วงเวลาที่แตกต่างกัน ซึ่งจะดูเหมือนพวกเขาด้วยสายตา เรืองแสงหรือริบหรี่ของความสว่างที่แตกต่างกัน โดยทั่วไป ตัวเลือกนี้สามารถอนุญาตได้เฉพาะเป็นข้อยกเว้น เป็นตัวอย่างการสอนเท่านั้น หรือในกรณี (แต่ขอย้ำอีกครั้ง เป็นเพียงข้อยกเว้นเท่านั้น!) เมื่อปัญหาหลักที่กำลังแก้ไขนั้นง่ายมาก (ซึ่งอาจเป็นได้ เช่น ปัญหาของการวัดโดยใช้ เอดีซีแรงดันไฟฟ้าและแสดงผลบนจอแสดงผล) คุณควรทำอย่างไร? คำตอบนั้นง่ายเช่นเคย: กระบวนการทั้งหมดที่ต้องดำเนินการโดยไม่มีใครสังเกตเห็นโดยการแก้ปัญหาของงานหลัก (และแน่นอนว่าเป็นกระบวนการดังกล่าว) ควรดำเนินการโดยใช้การขัดจังหวะตัวจับเวลา ISR (TIMER0_OVF_vect) ( pos ถ่านที่ไม่ได้ลงนามคงที่ = 0; COLS = 0xFF; ROWS = SCR; COLS = ~ (1<< pos); if(++pos == SCR_SZ) pos = 0; } ความคิดเห็นเล็กน้อย ตัวแปร ตำแหน่งเพื่อระบุจำนวนของเครื่องหมายที่ส่องสว่างในปัจจุบัน เราทำให้มันเป็นตัวแปรคงที่ในเครื่องเพื่อที่จะคงค่าของมันจากการขัดจังหวะหนึ่งไปอีกการขัดจังหวะ ในตอนท้ายของฟังก์ชันเราอิสระ (หลังจากนั้นเราไม่มีการวนซ้ำอีกต่อไป) เพิ่มจำนวนสถานที่ที่คุ้นเคยจนกว่าจะถึงขีด จำกัด - ในกรณีนี้เราจะไปที่จุดเริ่มต้นอีกครั้ง ในโปรแกรมหลักเราจะต้องเริ่มต้นพอร์ตและตัวจับเวลาเท่านั้น (ในกรณีนี้ - ตัวจับเวลา 0) เพื่อให้มันล้นในช่วงเวลาที่เราต้องการและทำให้เกิดการหยุดชะงัก หลังจากนี้ คุณไม่จำเป็นต้องคิดถึงสิ่งบ่งชี้อีกต่อไป เพราะมันจะทำงานอย่างเงียบๆ และสงบสุขด้วยตัวมันเอง แต่จะกำหนดช่วงเวลาโอเวอร์โฟลว์ของตัวจับเวลาที่ต้องการได้อย่างไร? ง่ายมาก สายตามนุษย์รับรู้การกะพริบด้วยความถี่มากกว่า 25 เฮิรตซ์เป็นแสงที่ต่อเนื่องกัน เรามีตัวบ่งชี้ 6 ตัวซึ่งแต่ละตัวควรกะพริบตามความถี่นี้ซึ่งหมายความว่าข้อมูลบนจอแสดงผลควรได้รับการอัปเดตด้วยความถี่ 25 x 6 = 150 Hz หรือมากกว่า ทีนี้มาคำนวณค่าของตัวจับเวลาล่วงหน้า: หารความถี่สัญญาณนาฬิกาของ MK ด้วย 256 ( ตัวจับเวลา 0ทุกคนมี เอวีอาร์แปดบิตซึ่งหมายความว่าจะล้นหลังจากนับถึง 256) - นี่จะเป็นค่าที่ต้องการของพรีสเกลเลอร์ตัวจับเวลา แน่นอนว่าไม่น่าเป็นไปได้ที่ผลลัพธ์จะตรงกับค่าพรีสเกลเลอร์มาตรฐานค่าใดค่าหนึ่ง - นี่ไม่ใช่ปัญหา คุณสามารถใช้ค่าที่เหมาะสมที่น้อยกว่าที่ใกล้ที่สุดได้ จอแสดงผลจะทำงานที่ความถี่ที่สูงขึ้น แต่จะไม่ลดคุณภาพลง! ผลข้างเคียงจะเป็นภาระขนาดใหญ่บนแกน MK สำหรับจอแสดงผล หากสิ่งนี้รบกวนการทำงานของโปรแกรมหลักอย่างมาก คุณจะต้องสลับการแสดงผลเป็นตัวจับเวลาอื่น เช่น 16 บิต เครื่องจับเวลา 1หรือป้อนตัวนับสำหรับตัวจับเวลาล้นที่ข้ามไป: #define SKIP 15 /* จำนวนตัวจับเวลาขัดจังหวะที่จะข้าม */ ISR (TIMER0_OVF_vect) ( char pos ที่ไม่ได้ลงชื่อแบบคงที่ = 0; char ที่ไม่ได้ลงชื่อแบบคงที่ข้าม = SKIP; ถ้า (--ข้าม) กลับ; ข้าม = SKIP; COLS = 0xFF; ROWS = SCR ; COLS = ~(1<< pos); if(++pos == SCR_SZ) pos = 0; } ในตัวอย่างง่ายๆ เหล่านี้ เราถือว่าพอร์ตนั้น โคลสยกเว้นแคโทดทั่วไปของตัวบ่งชี้ ไม่มีสิ่งใดเชื่อมต่อกันอีก อย่างไรก็ตาม ในชีวิตจริง โชคเช่นนี้ไม่ได้เกิดขึ้นบ่อยนัก และมีสิ่งอื่นที่น่าจะเชื่อมโยงกับเส้นทางที่เหลือของท่าเรือนี้ ดังนั้น เมื่อจัดระเบียบจอแสดงผลแบบไดนามิก คุณควรตรวจสอบให้แน่ใจเสมอว่าสถานะของบรรทัดพอร์ตทั้งหมดที่ไม่เกี่ยวข้องโดยตรงกับจอแสดงผลยังคงไม่เปลี่ยนแปลง ทำได้ง่ายมาก: แทนที่จะเขียนค่าใหม่ไปที่พอร์ต คุณควรใช้การปกปิดบิตที่ไม่จำเป็น: COLS |= 0x3F; // ดังนั้นเราจึงดับสถานที่ที่คุ้นเคยทั้งหมด COLS &= ~(1< ตัวดำเนินการทั้งสองไม่เปลี่ยนค่าของบิตที่สำคัญที่สุดของพอร์ต โคลส. ตัวถอดรหัสสามารถใช้เพื่อแปลงอย่างใดอย่างหนึ่ง ฐานสิบหกหรือ บีซีดีโค้ดเป็นสัญลักษณ์เจ็ดส่วน หรือเพื่อเลือกคอลัมน์เมทริกซ์คอลัมน์ใดคอลัมน์หนึ่ง ตัวเลือกทั้งสองจะแตกต่างจากวิธีที่ง่ายที่สุดที่กล่าวถึงก่อนหน้านี้เฉพาะวิธีการจัดระเบียบเอาต์พุตไปยังพอร์ตเท่านั้น แถวและ/หรือ โคลสซึ่งจะเชื่อมต่ออินพุตตัวถอดรหัสเข้าด้วยกัน ISR(TIMER0_OVF_vect)( ถ่าน pos ที่ไม่ได้ลงนามคงที่ = 0; COLS |= 0x3F; ROWS = (ROWS & 0xF0) | (SCR & 0x0F); COLS &= ~(1<< pos);
if(++pos == SCR_SZ) pos = 0;
}
อย่างที่คุณเห็นการเปลี่ยนแปลงมีเพียงเล็กน้อย - ก่อนที่จะแสดง แถวรหัสอักขระจากอาร์เรย์ เอสซีอาร์บิตที่สำคัญที่สุดจะถูกปกปิด หลังจากนั้นบิตที่มีนัยสำคัญน้อยที่สุดจะถูกตั้งค่าตามรหัสอักขระ นั่นคือเราพิจารณาว่าตัวถอดรหัสเชื่อมต่อกับพอร์ตที่มีนัยสำคัญน้อยที่สุด 4 บิต แถว. ฉันหวังว่าจะไม่มีประโยชน์ที่จะยกตัวอย่างการถอดรหัสคอลัมน์ - ทุกอย่างชัดเจนแล้ว แม้ว่าการบ่งชี้แบบไดนามิกโดยใช้ shift register จะไม่แตกต่างโดยพื้นฐานจากวิธีการที่กล่าวถึงก่อนหน้านี้ แต่ก็มีหลายตัวเลือกสำหรับการนำไปปฏิบัติ เราจะพิจารณาสิ่งที่ง่ายที่สุด - ส่งออกบิตโดยซอฟต์แวร์ล้วนๆ และในการนำไปปฏิบัติของผู้อื่น (โดยใช้ USI/USART/เอสพีไอ/ทวิ) คุณสามารถลองด้วยตัวเองได้ สำหรับตัวแปรของการแสดงตำแหน่งที่คุ้นเคย 6 และ 7 ส่วนที่เลือกไว้ก่อนหน้านี้ เราใช้การลงทะเบียนกะ 2 ประเภท 74HC595- รีจิสเตอร์นี้ถูกควบคุมโดยสัญญาณสามสัญญาณ: พัลส์นาฬิกาอินพุตข้อมูลอนุกรม ซีแอลเคข้อมูลจริง ข้อมูลและพัลส์ของเอาต์พุตข้อมูลที่เขียนในรีจิสเตอร์พร้อมกัน ชุด- มาประกาศมาโครที่เกี่ยวข้องกัน (เพื่อความง่าย เราจะส่งสัญญาณทั้งหมดไปยังพอร์ตเดียว): #กำหนด CLK _BV(PB0) #กำหนด DATA _BV(PB1) #กำหนด SET _BV(PB2) #กำหนด REG_PORT PORTB หากต้องการเขียนลงรีจิสเตอร์ จะสะดวกในการเขียนฟังก์ชันแยกต่างหาก: การเปลี่ยนแปลงโมฆะแบบคงที่ (ถ่านที่ไม่ได้ลงนาม d) (ถ่านที่ไม่ได้ลงนาม i; สำหรับ (i=0; i< 8; i++){
// устанавливаем нужный уровень DATA
if(d & 1)
REG_PORT |= DATA;
else
REG_PORT &= ~DATA;
REG_PORT |= CLK; // даем импульс CLK
REG_PORT &= ~CLK;
d >>= 1;
}
}
ขอแนะนำอย่างยิ่งให้ฟังก์ชันนี้เป็นแบบคงที่เพราะว่า มันจะถูกใช้ในตัวจัดการการขัดจังหวะ คอมไพลเลอร์มักจะสร้างฟังก์ชันคงที่ในรูปแบบ แบบอินไลน์- การแทรกเข้าไปในตัวจัดการการขัดจังหวะเช่น จะไม่มีการใช้สแต็กที่ไม่จำเป็น ซึ่งไม่รับประกันสำหรับฟังก์ชันที่ไม่คงที่ ตอนนี้ตัวจัดการขัดจังหวะของเราจะมีลักษณะดังนี้: ISR (TIMER0_OVF_vect) ( char pos ที่ไม่ได้ลงนามคงที่ = 0; shift (SCR); shift (~ (1<< pos));
REG_PORT |= SET; // выдаем импульс SET
REG_PORT &= ~SET;
if(++pos == SCR_SZ) pos = 0;
}
เนื่องจากข้อมูลที่เขียนไปยังรีจิสเตอร์จะปรากฏที่เอาต์พุตพร้อมกัน จึงไม่จำเป็นต้องดับไฟแสดงก่อน ควรจำไว้ว่าเอาต์พุตตามลำดับของซอฟต์แวร์นั้นเป็นกระบวนการที่ค่อนข้างยาว โดยเฉพาะอย่างยิ่งสำหรับเมทริกซ์ที่มีขนาดใหญ่ ดังนั้นจึงควรปรับให้เหมาะสมเพื่อความเร็วให้มากที่สุด ซึ่งสามารถทำได้ดีที่สุดโดยใช้ฮาร์ดแวร์เอาต์พุตแบบอนุกรมที่พบใน MCU ดังนั้น คุณจึงได้คุ้นเคยกับพื้นฐานของการใช้งานการแสดงผลแบบไดนามิกแล้ว แต่ตามปกติแล้ว คำถามไม่ได้ลดลง แต่เพิ่มขึ้น เมื่อคาดการณ์ไว้บางส่วน ฉันจะพยายามให้คำตอบที่จำเป็นทันที ทุกสิ่งที่เราพิจารณาก่อนหน้านี้เกี่ยวข้องกับตัวบ่งชี้ที่มีแคโทดทั่วไป จะทำอย่างไรถ้าคุณต้องการใช้กับขั้วบวกทั่วไป? โดยทั่วไปทุกอย่างยังคงเหมือนเดิมยกเว้นก่อนที่จะส่งออกจำเป็นต้องกลับข้อมูล - การล้างความคุ้นเคยจะดำเนินการโดยการส่งออกค่าศูนย์ใน โคลส, การจุดระเบิด - ตามลำดับ, หน่วย, และส่วนต่างๆ ใน แถวจะถูกรวมไว้ด้วยศูนย์แทนที่จะเป็นศูนย์ ดังนั้นตัวจัดการการขัดจังหวะจะมีลักษณะดังนี้: ISR (TIMER0_OVF_vect) ( pos ถ่านที่ไม่ได้ลงนามคงที่ = 0; COLS &= 0xC0; ROWS = ~SCR; COLS |= (1<< pos);
if(++pos == SCR_SZ) pos = 0;
}
มันง่ายมาก ยกเว้นกรณีที่คุณพยายามเขียนโค้ดสากลที่เหมาะสมสำหรับทั้งแอโนดทั่วไปและแคโทดทั่วไป มีสองวิธีในการทำเช่นนี้: ใช้คำสั่งการคอมไพล์แบบมีเงื่อนไขหรือการใช้ฟังก์ชันการแปลง ฉันจะสาธิตตัวเลือกแรก และแนะนำให้คุณคิดถึงตัวเลือกที่สองด้วยตัวเอง #define COMMON_ANODE 1 ISR(TIMER0_OVF_vect)( char pos ที่ไม่ได้ลงนามแบบคงที่ = 0; #if COMMON_ANODE != 1 COLS &= 0xC0; ROWS = ~SCR; COLS |= (1<< pos);
#else
COLS |= 0x3F;
ROWS = SCR;
COLS &= ~(1 << pos);
#endif
if(++pos == SCR_SZ) pos = 0;
}
แม้ว่าจะยุ่งยากเล็กน้อย แต่หลังจากเขียนเพียงครั้งเดียวแล้ว คุณสามารถใช้มันกับทุกโปรเจ็กต์ได้โดยแทบไม่มีการเปลี่ยนแปลงเลย ในหลายกรณี จอแสดงผลไม่เพียงแต่ใช้เป็นวิธีการแสดงข้อมูลที่มาจากภายในอุปกรณ์เท่านั้น แต่ยังใช้เพื่อแสดงข้อมูลที่ผู้ใช้ป้อนอีกด้วย และในกรณีนี้จำเป็นต้องสามารถแยกสิ่งที่ไม่เปลี่ยนแปลงออกจากสิ่งที่เปลี่ยนแปลงได้บนจอแสดงผล วิธีที่ง่ายที่สุดในการทำเช่นนี้คือการทำให้สถานที่ที่คุ้นเคย (หรือสถานที่ที่คุ้นเคยหลายแห่ง) กะพริบ มันง่ายมากที่จะทำ เรามาแนะนำตัวแปรโกลบอลกัน ซึ่งแต่ละหน่วยบิตจะแสดงสัญลักษณ์ที่กะพริบ: ตอนนี้เรามาปรับเปลี่ยนตัวจัดการการขัดจังหวะเล็กน้อย: ISR(TIMER0_OVF_vect)( char pos ที่ไม่ได้ลงชื่อแบบคงที่ = 0; รายการถ่านแบบคงที่ที่ไม่ได้ลงชื่อ = 0; COLS |= 0x3F; if(!(blink & (1< อย่างที่คุณเห็น มีการเพิ่มตัวแปรคงที่เพียงตัวเดียวเท่านั้น - ตัวนับอินพุตไปยังตัวจัดการการขัดจังหวะ รายการและผู้ดำเนินการทดสอบสภาวะ ตรรกะนั้นง่าย: เอาต์พุตของความคุ้นเคยถัดไปจะดำเนินการเฉพาะในบิตที่เกี่ยวข้องเท่านั้น กระพริบตาศูนย์หรือบิตที่สำคัญที่สุดของตัวนับ รายการเท่ากับ 1 ถ้า สมมุติว่า กระพริบตามีศูนย์ทั้งหมด จากนั้นตรงตามเงื่อนไขนี้เสมอ - สถานที่ที่คุ้นเคยทั้งหมดจะปรากฏขึ้น ถ้า กระพริบตามี 1 ในบิตของมัน ดังนั้นเครื่องหมายที่เกี่ยวข้องจะสว่างเฉพาะในเวลาที่บิตที่สำคัญที่สุดของตัวนับเท่ากับ 1 เนื่องจากตัวนับจะเพิ่มขึ้นในแต่ละครั้งที่ป้อนตัวจัดการการขัดจังหวะ เครื่องหมายที่เกี่ยวข้องจะ การสั่นไหวด้วยความถี่น้อยกว่าความถี่ขัดจังหวะ 128 เท่า ฉันเขียนเกี่ยวกับการปรับความสว่างในบทความแยกต่างหากซึ่งเรียกว่าอย่างนั้น ได้มีการกล่าวก่อนหน้านี้ว่าความสุขของการอุทิศพอร์ต MK ทั้งหมดเพื่อจัดแสดงนั้นค่อนข้างหายาก แต่จะยิ่งยากกว่าที่จะได้รับการติดตามแผงวงจรพิมพ์ที่สะดวกหากใช้พอร์ตหนึ่งสำหรับแถวทั้งหมด และอีกพอร์ตใช้สำหรับคอลัมน์ของเมทริกซ์การแสดงผล บ่อยครั้งที่การติดตามที่เหมาะสมที่สุดจะเกิดขึ้นก็ต่อเมื่อมีการผสมแถวและคอลัมน์ระหว่างพอร์ตไมโครคอนโทรลเลอร์สองพอร์ตขึ้นไป คุณจะไม่ต้องเสียสละความสวยงามของแผงวงจรพิมพ์หากคุณจัดระเบียบซอฟต์แวร์เพื่อจัดเรียงบิตใหม่ระหว่างการแสดงผล ลองดูตัวอย่างที่เป็นนามธรรม ให้การติดตามที่ดีที่สุดมีการกระจายสัญญาณต่อไปนี้ตามแนวของพอร์ต MK: ส่วน ก ส่วน B ส่วน H ส่วน C ส่วนง ส่วน G ส่วน E ส่วน F อย่างที่คุณเห็น เส้นเมทริกซ์ผสมกันระหว่างสามพอร์ต และบรรทัดที่ไม่ได้ใช้ทั้งหมดของพอร์ตเหล่านี้ไม่ควรเปลี่ยนระดับในระหว่างกระบวนการแสดงผลโดยธรรมชาติ วิธีที่ดีที่สุดคือเริ่มพัฒนาฟังก์ชันบ่งชี้แบบไดนามิกสำหรับกรณีนี้โดยการกระจายส่วนต่างๆ ไปตามบิตสัญลักษณ์ เมื่อก่อนเราเชื่ออย่างนั้นในอาเรย์ เอสซีอาร์เราจัดเก็บมาสก์บิตอักขระ เช่น ที่อยู่ในไบต์บ่งบอกถึงส่วนที่ส่องสว่าง เราไม่ได้คิดว่าบิตใดจะสอดคล้องกับส่วนใด ตอนนี้เป็นเวลาที่จะคิดเกี่ยวกับมัน สะดวกในการทาสีจุดประสงค์ของเส้นพอร์ตในรูปแบบแผ่นสามแผ่น: 1
ก
0
4
ชม
3
2
บี
เอฟ
อี
5
ช
ดี
ค
เราต้องรวบรวมเซกเมนต์ทั้งหมดเป็นหนึ่งไบต์ การดำเนินการนี้จะต้องทำในการดำเนินการกะ ดังนั้นคุณควรพยายามกระจายการทำงานเพื่อให้มีกะน้อยที่สุด มาคุยกันเถอะ ถ้าส่วนบิต FEGDCทิ้งไว้ในสัญลักษณ์ให้ตกไป พอร์ตดีโดยไม่มีการเปลี่ยนแปลง จากนั้นจึงแบ่งกลุ่ม ชมยังสามารถคงอยู่ในบิตที่ 6 ของสัญลักษณ์ได้ และไม่จำเป็นต้องเลื่อนก่อนเอาท์พุตอีกด้วย พอร์ตซีแต่สำหรับกลุ่ม กและ ในบิต 7 และ 3 จะยังคงอยู่ นั่นคือส่วนใหญ่เป็นเซ็กเมนต์ ในจะต้องเลื่อน 3 ตำแหน่งก่อนเอาท์พุตและเซ็กเมนต์ ก- ภายใน 6 ฉันจะมุ่งเน้นไปที่ตัวเลือกนี้และคุณสามารถค้นหากะขั้นต่ำต่อไปได้ (การเปลี่ยนหลายตำแหน่งไม่ใช่การดำเนินการที่รวดเร็วดังนั้นจึงแนะนำให้ลดจำนวนให้เหลือน้อยที่สุด) ดังนั้นในกรณีของเรา การกระจายบิตเหนือไบต์อักขระจะเป็นดังนี้: ก
ชม
เอฟ
อี
บี
ช
ดี
ค
มาทำเครื่องหมายบิตมาสก์สำหรับเอาต์พุตไปยังพอร์ตที่เกี่ยวข้อง: ดี
0
0
1
1
0
1
1
1
0x37
บี
1
0
0
0
0
0
0
0
0x80
ค
0
1
0
0
1
0
0
0
0x48
การใช้มาสก์เหล่านี้โดยใช้การดำเนินการ "bitwise AND" เราจะเลือกบิตที่จำเป็นสำหรับเอาต์พุตไปยังพอร์ต มาประกาศค่าคงที่ของมาสก์: #กำหนด MASKD 0x37 #กำหนด MASKB 0x80 #กำหนด MASKC 0x48 ก่อนหน้านี้เราส่งออกสัญลักษณ์ไปยังพอร์ตเดียว แถวตอนนี้ขั้นตอนนี้จะแบ่งออกเป็นสามส่วน: PORTD = (PORTD & ~MASKD) | (SCR & หน้ากาก); PORTB = (PORTB & ~ MASKB) | ((SCR & MASKB) >> 6); PORTC = (PORTC & ~ MASKC) | ((SCR & _BV(6)) | (((SCR & _BV(3)) >> 3); พอร์ตซีโปรดทราบว่าสำหรับการถอนเงินไปที่ หนึ่งบิตจะต้องเป็นเอาต์พุตโดยไม่มีการเปลี่ยนแปลงและบิตที่สอง - ด้วยการเปลี่ยนแปลงดังนั้นแทนที่จะเป็นมาส์กซี ฉันต้องใช้มาโครแยกต่างหาก. _บีวี() ตอนนี้ยังคงต้องตัดสินใจว่าจะดับและจุดไฟในสถานที่คุ้นเคยที่เกี่ยวข้องอย่างไร มาประกาศค่าคงที่ที่สอดคล้องกับบิตควบคุมความคุ้นเคยกัน: #กำหนด COM0 _BV(0) #กำหนด COM1 _BV(3) #กำหนด COM2 _BV(4) #กำหนด COM3 _BV(5) #กำหนด COM4 _BV(7) #กำหนด COM5 _BV(3) #กำหนด COM_D (COM5) #define COM_C (COM2 | COM3 | COM4) #define COM_B (COM0 | COM1) หากต้องการดับคนรู้จักทั้งหมด คุณต้องส่งออกค่าคงที่ที่สอดคล้องกันไปยังพอร์ต: COM_x พอร์ตดี |= COM_D; พอร์ตซี |= COM_C; พอร์ตบี |= COM_B; ตำแหน่งแต่ในการเปิดความคุ้นเคยคุณจะต้องยุ่งยาก (ไม่มีประเด็นในการส่งออกไปยังพอร์ตทั้งสามพอร์ตเนื่องจากจะมีเพียงบิตเดียวเท่านั้นที่จะใช้งานในพอร์ตเฉพาะขึ้นอยู่กับค่า ) เช่น การใช้โอเปอเรเตอร์: สวิตช์ Switch(pos)( case 0: PORTB &= ~COM0; break; case 1: PORTB &= ~COM1; break; case 2: PORTC &= ~COM2; break; case 3: PORTC &= ~COM3; break; case 4: PORTC &= ~COM4; กรณีที่ 5: PORTD &= ~COM5; มันไม่ใช่วิธีที่สวยที่สุด แต่ได้ผล ดังนั้นตัวจัดการการขัดจังหวะของเราจึงมีรูปแบบดังต่อไปนี้:<< pos)) || (++entry & 0x80)) {
switch(pos){
case 0: PORTB &= ~COM0; break;
case 1: PORTB &= ~COM1; break;
case 2: PORTC &= ~COM2; break;
case 3: PORTC &= ~COM3; break;
case 4: PORTC &= ~COM4; break;
case 5: PORTD &= ~COM5; break;
}
}
if(++pos == SCR_SZ) pos = 0;
}
ISR (TIMER0_OVF_vect) ( char pos ที่ไม่ได้ลงชื่อแบบคงที่ = 0; รายการถ่านที่ไม่ได้ลงชื่อแบบคงที่ = 0; // ระงับ PORTD |= COM_D; PORTC |= COM_C; PORTB |= COM_B; // พิมพ์ PORTD = (PORTD & ~MASKD) | ( SCR & MASKD); PORTB = (PORTB & ~MASKB) | ((SCR & MASKB) >> 6); PORTC = (PORTC & ~MASKC) |. / กะพริบถ้า(!(กะพริบ & (1 ตอนนี้ยังคงต้องหาวิธีอธิบายสัญลักษณ์สำหรับเอาต์พุตได้สะดวกยิ่งขึ้น... ฉันเสนอให้ทำสิ่งต่อไปนี้: กำหนดค่าคงที่ที่สอดคล้องกับบิตของเซ็กเมนต์จากนั้น "สร้าง" สัญลักษณ์ที่จำเป็นจากค่าคงที่เหล่านี้: // ส่วนประถมศึกษา #define _A _BV(7) #define _B _BV(3) #define _C _BV(0) #define _D _BV(1) #define _E _BV(4) #define _F _BV(5) #define _G _BV (2) #define _H _BV(6) // สัญลักษณ์หลัก #define d_0 (_A | _B | _C | _D | _E | _F) #define d_1 (_B | _C) #define d_2 (_A | _B | _G | _D | _E) // และอื่นๆ ดังนั้น หากคุณต้องการแสดงศูนย์ที่ตำแหน่งขวาสุดของจอแสดงผล คุณเพียงแค่ต้องเขียนในตำแหน่งที่ถูกต้อง: เอสซีอาร์ = d_0; ฉันต้องใช้มาโครแยกต่างหากสำหรับเซ็กเมนต์เบื้องต้น และสัญลักษณ์ทั้งหมดจะถูก "จัดแจง" โดยอัตโนมัติ สำหรับกรณีที่ง่ายที่สุดที่อธิบายไว้ตอนต้น คุณไม่จำเป็นต้องทำอะไรเลย แต่สำหรับตัวเลือก "การจัดเรียงบิตใหม่" แน่นอนว่าคุณจะต้องคนจรจัด เนื่องจากการขาดแคลนหมุด MK แบบดั้งเดิม ปัญหาของปุ่มจำนวนมากซึ่งแทบทุกอุปกรณ์สามารถทำได้หากไม่มีนั้นรุนแรงมาก มีการใช้การรวมเมทริกซ์ต่างๆ ฯลฯ อย่างไรก็ตาม ด้วยการทำให้ฟังก์ชันการแสดงผลแบบไดนามิกซับซ้อนขึ้นเล็กน้อย คุณจึงสามารถมีปุ่มได้มากเท่าที่คุณต้องการได้อย่างง่ายดายเหมือนกับที่คุ้นเคยในจอแสดงผล ขณะเดียวกันก็จำเป็นต้องใช้พอร์ตไมโครคอนโทรลเลอร์เพียงพอร์ตเดียวเท่านั้น จริงอยู่ที่คุณยังต้องติดตั้งไดโอดในแต่ละปุ่ม สิ่งนี้แสดงไว้ในแผนภาพ และโปรแกรมมีลักษณะดังนี้: #define keypin() (!(PIND & _BV(KEY))) ISR(TIMER0_OVF_vect)( char pos ที่ไม่ได้ลงชื่อแบบคงที่ = 0; รายการถ่านแบบคงที่ที่ไม่ได้ลงชื่อ = 0; ถ่านแบบคงที่ที่ไม่ได้ลงชื่อ tmp_key = 0; ROWS = 0; if(keypin( )) tmp_key |= 1<< pos;
COLS |= 0x3F;
if(!(blink & (1<< pos)) || (++entry &0x80)){
ROWS = (ROWS & 0xF0) | (SCR & 0x0F);
COLS &= ~(1 << pos);
}
if(++pos == SCR_SZ){
pos = 0;
key = tmp_key;
tmp_key = 0;
}
}
ที่นี่ สำคัญ- นี่คือมาโครที่ตั้งค่าบิตของพอร์ตที่เลือกซึ่งมีปุ่มทั้งหมด "เชื่อมต่อ" มาโคร คีย์พิน()ส่งกลับค่าตรรกะ TRUE หากพินที่เลือกมีตรรกะต่ำ ในตัวอย่างนี้มีการเชื่อมต่อกับปุ่มต่างๆ พอร์ตดี. แต่ละครั้งที่มีการขัดจังหวะตัวจับเวลาเกิดขึ้น ทุกส่วนจะถูกดับลงก่อน ซึ่งจำเป็นเพื่อให้กระแสไฟฟ้าที่ผ่าน LED ไม่ทำให้ตรวจไม่พบปุ่มกดอย่างผิดพลาด หลังจากนี้ อินพุตของปุ่มจะถูกสำรวจ - หากระดับต่ำ หมายความว่ามีการกดปุ่มที่เชื่อมต่อกับแคโทด pos ที่เกี่ยวข้อง ในตัวแปร tmp_keyสถานะของปุ่มจะถูกสะสมและเขียนใหม่เป็นตัวแปรส่วนกลาง สำคัญหลังจากสิ้นสุดรอบการแสดง สิ่งที่คุณต้องทำคือวิเคราะห์ความหมายเป็นครั้งคราว สำคัญและประมวลผลการคลิกที่ตรวจพบ: ถ่านที่ไม่ได้ลงนามคงที่ get_key())( ถ่านที่ไม่ได้ลงนาม tmp = 0; tmp = key; _delay_ms(10); if(key == tmp) return tmp; else return 0; ) ฟังก์ชันง่ายๆ นี้ช่วยให้แน่ใจว่าปุ่มต่างๆ จะไม่เด้งกลับ แม้ว่าเนื่องจากลักษณะ "ไดนามิก" ของการโพลปุ่ม ความน่าจะเป็นของการเด้งจึงต่ำอยู่แล้ว ดังนั้น คุณจึงเชี่ยวชาญเทคนิคทั่วไปในการใช้งานการแสดงผลแบบไดนามิกแล้ว ฉันคิดว่านี่จะเพียงพอสำหรับคุณในครั้งแรก และอาจตลอดชีวิตของคุณด้วยซ้ำ ในท้ายที่สุดสิ่งสำคัญคือการเข้าใจเทคนิคและอัลกอริธึมและคุณสามารถเพิ่มรายละเอียดปลีกย่อยและความแตกต่างได้ด้วยตนเอง แต่มีอะไรอีกที่สามารถรอ "ปิด" ให้กับจอแสดงผลไดนามิกได้? ดังที่ฉันได้กล่าวไว้ก่อนหน้านี้ คุณสามารถเพิ่มได้ถึงการควบคุมที่เป็นอิสระของแต่ละส่วน คุณสามารถคิดถึงความเหมาะสมที่สุดของตัวจัดการการขัดจังหวะ - เพื่อวัตถุประสงค์ทางการศึกษาฉันเขียนโค้ดที่ค่อนข้างหยาบเช่นฉันใช้ทุกที่ เอสซีอาร์แม้ว่าจะเป็นการเหมาะสมกว่าหากอ่านค่าลงในตัวแปรท้องถิ่นเพียงครั้งเดียว จากนั้นจึงดำเนินการตามค่าของมัน แม้ว่าเครื่องมือเพิ่มประสิทธิภาพจะช่วยในแนวทางของฉันได้อย่างแน่นอน แต่สำหรับการฝึกฝนก็คุ้มค่าที่จะลองและปรับตัวเองให้เหมาะสม โดยตรวจสอบตัวเองในแง่ของขนาดของโค้ดผลลัพธ์และ/หรือความเร็วของโปรแกรม คุณสามารถนึกถึงแนวคิดที่น่าสนใจในการปรับความสว่างของจอแสดงผลโดยอัตโนมัติตามระดับแสงโดยรอบ ดังที่คุณทราบ ไฟ LED จะมองเห็นได้น้อยลงเมื่อมืดลง - เพียงแต่พร่ามัว ดังนั้นในความมืดจึงสมเหตุสมผลที่จะลดความสว่างของตัวบ่งชี้โดยเพิ่มขึ้นในช่วงเวลากลางวัน สิ่งที่ง่ายที่สุดคือการใช้โฟโตรีซีสเตอร์หรือ LED แยกต่างหากเป็นเซ็นเซอร์วัดแสง แต่คุณสามารถทำได้แตกต่างออกไป: เป็นที่ทราบกันดีว่า LED ก็สามารถทำงานเป็นโฟโตไดโอดได้เช่นกัน ดังนั้นหากคุณใช้พอร์ตที่เชื่อมต่อกับอินพุตเพื่อบ่งชี้ เอดีซีจากนั้น หากต้องการ คุณสามารถวัดแรงเคลื่อนไฟฟ้าภาพถ่ายของส่วนที่ไม่ส่องสว่างของตัวบ่งชี้ และใช้ค่านี้เพื่อปรับความสว่าง... คุณสามารถคิดถึงการใช้ฮาร์ดแวร์เอาต์พุตแบบอนุกรมซึ่งฉันได้บอกเป็นนัยไปแล้ว เวอร์ชันที่น่าสนใจของแนวทางสากลในการแสดงผลแบบไดนามิกซึ่งฉันแนะนำให้ทำความคุ้นเคยได้รับการเสนอโดย โมลเชค- โดยสรุปสาระสำคัญ: การกระจายเซกเมนต์ด้วยบิตสัญลักษณ์การกำหนดพอร์ตสำหรับควบคุมตัวบ่งชี้และแม้แต่ประเภทของตัวบ่งชี้ - กล่าวโดยย่อคือพารามิเตอร์ทั้งหมดทั้งหมดทั้งหมด - จะถูกระบุไว้ในรูปแบบของตารางการกำหนดค่าใน อีพรอม- จากตารางนี้ ทุกอย่างจะถูกจัดระเบียบโดยทางโปรแกรม: จากการผกผันขึ้นอยู่กับประเภทของตัวบ่งชี้ ไปจนถึงการจัดเรียงบิตใหม่บนพอร์ตต่างๆ ในกรณีนี้ ซอร์สโค้ดของโปรแกรมแสดงผลไดนามิกจะยังคงไม่เปลี่ยนแปลงเสมอ และผู้ใช้จะรวบรวมตารางการกำหนดค่าขึ้นอยู่กับความชอบของผู้ใช้ วิธีการนี้เป็นสากลและยืดหยุ่นอย่างแท้จริง แต่เกี่ยวข้องกับการใช้หน่วยความจำโปรแกรมที่เพิ่มขึ้น |
3 โพสต์โดย ยาต้านไวรัส, เวลา 06:48 08/25/2010 มิชาถ้าฉันเป็นคุณฉันจะไม่กล่าวคำเด็ดขาดเช่น "คุณทำไม่ได้" "ไม่มีใครเขียน" หรือ "ลิขสิทธิ์" เพราะประการแรกมันไม่สุภาพและประการที่สอง: 1. ฉันสร้างเส้นคืบคลานบนเมทริกซ์ 10x16 เมื่อนานมาแล้ว (นั่นคือสิ่งที่เป็นอยู่) - คุณสามารถดูวิดีโอการทำงานของมันได้ในบันทึกนี้ http://site/content/view/160/38/ 2. ฉันเขียนบทความ (คุณจะพบได้ในข่าว - บทความสุดท้ายของวันนี้) เกี่ยวกับวิธีสร้างสัญลักษณ์บนจอ LCD หากคุณทำให้สมองของคุณเครียดเล็กน้อยการทำซ้ำอัลกอริธึมเพื่อส่งออกไปยังเมทริกซ์นั้นไม่ใช่เรื่องเล็ก 3. ในเว็บไซต์ของฉันไม่มีบทความใดที่คัดลอกมาจากที่ใดที่หนึ่ง (การคัดลอกและวางไม่ใช่ลิขสิทธิ์ คุณพิมพ์ผิด) เนื้อหาทั้งหมดเป็นต้นฉบับโดยสมบูรณ์ เว็บไซต์หลายแห่งมีสำเนาของเนื้อหาเหล่านี้โดยได้รับอนุญาตจากฉัน (หรือได้รับอนุญาตจากผู้เขียนเนื้อหาซึ่งมีสิทธิ์ทุกประการในการเผยแพร่เนื้อหาของตนในหลาย ๆ ที่พร้อมกัน) |
เฉพาะผู้ใช้ที่ลงทะเบียนเท่านั้นที่สามารถแสดงความคิดเห็นได้
กรุณาลงทะเบียนหรือเข้าสู่ระบบบัญชีของคุณ
ดีในการแสดงตัวเลขหลายหลักบนตัวบ่งชี้ คุณต้องดำเนินการจัดการที่ยุ่งยากก่อน ซึ่งประกอบด้วยการแบ่งตัวเลขออกเป็นส่วนประกอบต่างๆ ตัวอย่างเช่น ฉันจะแสดงหมายเลข 1234 บนตัวบ่งชี้เจ็ดส่วนรูปสี่เหลี่ยมที่มีขั้วบวกทั่วไป
หากต้องการแสดงตัวเลขสี่หลัก คุณต้องสร้างตัวแปรทั่วไปหนึ่งตัวแปรโดยให้ตัวเลขที่คุณต้องการแสดงอยู่ (ตัวแปร ว) ตัวแปรสี่ตัวที่จะจัดเก็บข้อมูลสำหรับแต่ละเครื่องหมาย (เอ็น) และตัวแปรอีกสี่ตัวสำหรับการแปลงระดับกลาง (ม) เพื่อไม่ให้กระทบกับตัวแปรหลัก ตัวแปรจะต้องสอดคล้องกับค่าที่จะเก็บไว้ในนั้นฉัน. ดังนั้นสำหรับตัวแปรวประเภทจะเพียงพอจำนวนเต็ม เนื่องจากตัวแปรประเภทนี้สามารถจัดเก็บได้เปลี่ยนค่าจาก -32768 เป็น +32767 (หรือคำ เว้นแต่คุณวางแผนที่จะใช้จำนวนลบ) ในตัวแปรเอ็นจะมีตัวเลขตั้งแต่ 0 ถึง 9 ดังนั้นการใช้ตัวแปรเช่นไบต์ - และในตัวแปรม จะเป็นค่าเดียวกันกับในตัวแปรวดังนั้นเราจึงกำหนดประเภท จำนวนเต็ม .
หรี่ W เป็นจำนวนเต็ม
หรี่ N1 เป็นไบต์
หรี่ N2 เป็นไบต์
หรี่ N3 เป็นไบต์
หรี่ N4 เป็นไบต์
หรี่ M1 เป็นจำนวนเต็ม
Dim M2 เป็นจำนวนเต็ม
หรี่ M3 เป็นจำนวนเต็ม
Dim M4 เป็นจำนวนเต็ม
หลังจากประกาศตัวแปรแล้ว เราจะกำหนดค่าพอร์ตเอาต์พุตซึ่งจะใช้ในการเชื่อมต่อตัวบ่งชี้:
DDRC = &B11111111
DDRD = &B11111111
DDRC =&B 00001111 และ DDRD =&B 01111111 (สี่ขาแรกของท่าเรือ Cสำหรับแอโนดและหกพอร์ตแรก D สำหรับเซ็กเมนต์)
จากนั้นเราก็กำหนดให้กับตัวแปรว ค่าที่เราจะแสดงบนตัวบ่งชี้:
ส=1234
"แอเรียล", "ซานเซอริฟ""> ในลูปหลักของโปรแกรม เรากำหนดค่าของตัวแปรให้กับตัวแปร Mฉันทำสิ่งนี้:
M1 = ว
M2 = M1
M3 = M1
M4 = M1
"แอเรียล", "ซานเซอริฟ""> นี่ไม่ใช่อาการหวาดระแวง)) ทำเช่นนี้โดยมีเป้าหมายให้ตัวแปร M ทั้งหมดมีจำนวนเท่ากัน เนื่องจากในระหว่างการดำเนินการกำหนด การขัดจังหวะสามารถบุกรุกเข้าไปได้ง่าย (ถ้ามีและไม่ได้ปิดใช้งาน) ในตัวจัดการที่ ตัวแปรว อาจมีการเปลี่ยนแปลง และถ้างานเป็นดังนี้: M1=ว , ม 2= ว , ม 3= ว , ม 4= ว ตัวแปร M จะมีค่าที่แตกต่างกัน ซึ่งจะทำให้การอ่านยุ่งเหยิง
หลังจากกำหนดค่าให้กับตัวแปรแล้วเราก็เริ่มทำงานด้วย
แต่ละคนก็แปรสภาพไปจนกลายเป็นตัวแปรเอ็น ตีค่าที่จะเป็น
แสดงบนตัวบ่งชี้: ในตัวแปรเอ็น 1 ควรเป็น "1" ใน N 2 – “2” ใน N 3 – “3” และใน N 4 – “4”
M1 = M1 / 1,000 " M1 = 1234/1,000 = 1.234
N1 = หน้าท้อง (m1) " N1 = หน้าท้อง (1.234) = 1
หน้าท้อง – ฟังก์ชันที่คืนค่าจำนวนเต็มให้กับตัวแปรเอ็น ตี 1 ครั้ง ซึ่งก็ตรงตามที่ต้องการ
เพื่อกำหนดสองให้กับตัวแปรเอ็น การดำเนินการ 2 จะซับซ้อนขึ้นเล็กน้อย:
M2= M2 Mod 1,000 " M2 =1234 Mod 1,000 = 234
M2 = M2 / 100 " M2 = 234 / 100 = 2.34
N2= หน้าท้อง (m2) " N2 = หน้าท้อง (2.34) = 2
"แอเรียล", "ซานเซอริฟ""> เริ่มต้นด้วยฟังก์ชั่นมด
เราคืนค่าสามตัวแรกให้กับตัวแปร
หลักของตัวเลข (ส่วนที่เหลือหารด้วย 1,000) จากนั้นทุกอย่างจะเป็นเช่นในกรณีแรก
เกือบจะเหมือนกันกับตัวเลขสองตัวสุดท้าย:
M3 = M3 Mod100
M3 = M3 / 10
N3 = หน้าท้อง (m3)
M4 = M4 มด 10
N4= หน้าท้อง (m4)
ตอนนี้ตัวแปรของเรามีค่าที่เราต้องการแสดง ถึงเวลาที่ไมโครคอนโทรลเลอร์จะต้องเตะเท้าและแสดงค่าเหล่านี้บนตัวบ่งชี้ เพื่อทำเช่นนี้เราจะเรียกรูทีนย่อยการประมวลผลการแสดงผล:
"แอเรียล", "ซานเซอริฟ"">
โกซับ นำ
"แอเรียล", "ซานเซอริฟ""> โปรเซสเซอร์จะข้ามไปยังรูทีนย่อยที่มีป้ายกำกับนำ:
นำ:
พอร์ตc = &B00001000
"แอเรียล", "ซานเซอริฟ""> ที่นี่เราให้บริการระดับสูงของพอร์ตซี .3 เรามีขั้วบวกประเภทแรกที่เชื่อมต่อกับขานี้ จากนั้นเราเลือกว่าส่วนใดที่ต้องสว่างเพื่อแสดงค่าของตัวแปรแรก เธอเป็นหนึ่งเดียวสำหรับเรา ดังนั้นศูนย์จะอยู่บนเท้าของเธอพอร์ต .1 และพอร์ต .2 ซึ่งสอดคล้องกับส่วนต่างๆตัวบ่งชี้ B และ C
เลือกกรณี N1
สิ้นสุดการเลือก
รอ 5
"แอเรียล", "ซานเซอริฟ""> หลังจากส่วนที่จำเป็นสว่างขึ้นแล้ว ให้รอ 5 ms และดำเนินการแสดงตัวเลขต่อไปนี้:
พอร์ตc = &B00000100
เลือกกรณี N2
กรณีที่ 0 : พอร์ตd = &B11000000
กรณีที่ 1 : พอร์ตd = &B11111001
กรณีที่ 2 : พอร์ตd = &B10100100
กรณีที่ 3 : พอร์ตd = &B10110000
กรณีที่ 4 : พอร์ตd = &B10011001
กรณีที่ 5 : พอร์ตd = &B10010010
กรณีที่ 6 : พอร์ตd = &B10000010
กรณีที่ 7 : พอร์ตd = &B11111000
กรณีที่ 8 : พอร์ตd = &B10000000
กรณีที่ 9 : พอร์ตd = &B10010000
สิ้นสุดการเลือก
รอ 5
พอร์ตc = &B00000010
เลือกกรณี N3
กรณีที่ 0 : พอร์ตd = &B11000000
กรณีที่ 1 : พอร์ตd = &B11111001
กรณีที่ 2 : พอร์ตd = &B10100100
กรณีที่ 3 : พอร์ตd = &B10110000
กรณีที่ 4 : พอร์ตd = &B10011001
กรณีที่ 5 : พอร์ตd = &B10010010
กรณีที่ 6 : พอร์ตd = &B10000010
กรณีที่ 7 : พอร์ตd = &B11111000
กรณีที่ 8 : พอร์ตd = &B10000000
กรณีที่ 9 : พอร์ตd = &B10010000
สิ้นสุดการเลือก
รอ 5
พอร์ตc = &B00000001
เลือกกรณี N4
กรณีที่ 0 : พอร์ตd = &B11000000
กรณีที่ 1 : พอร์ตd = &B11111001
กรณีที่ 2 : พอร์ตd = &B10100100
กรณีที่ 3 : พอร์ตd = &B10110000
กรณีที่ 4 : พอร์ตd = &B10011001
กรณีที่ 5 : พอร์ตd = &B10010010
กรณีที่ 6 : พอร์ตd = &B10000010
กรณีที่ 7 : พอร์ตd = &B11111000
กรณีที่ 8 : พอร์ตd = &B10000000
กรณีที่ 9 : พอร์ตd = &B10010000
สิ้นสุดการเลือก
รอ 5
"แอเรียล", "ซานเซอริฟ""> หลังจากแสดงข้อมูลบนตัวบ่งชี้แล้ว คุณจะต้องกลับไปที่ลูปโปรแกรมหลัก โดยคุณจะต้องวนลูปให้เสร็จและระบุจุดสิ้นสุดของโปรแกรม
"แอเรียล", "ซานเซอริฟ""> นี่คือสิ่งที่เราได้รับในที่สุด:
"แอเรียล", "ซานเซอริฟ"">
"แอเรียล", "ซานเซอริฟ""> เนื่องจากความล่าช้าในการสลับเล็กน้อย การสลับจึงไม่สามารถมองเห็นได้ด้วยตามนุษย์ และเราจะเห็นจำนวนเต็ม 1234
คุณสามารถดาวน์โหลดแหล่งที่มาและโครงการใน Proteus ด้านล่าง:"แอเรียล", "ซานเซอริฟ"">
อ่าน: |
---|
ใหม่
- หากรองเท้าไม่พอดีกับ Aliexpress: การกระทำที่ถูกต้องในกรณีนี้ ผลิตภัณฑ์ Aliexpress มีขนาดที่เหมาะสม
- ข้อพิพาทใน AliExpress เข้าร่วมข้อพิพาทใน AliExpress
- 3 ฐานข้อมูลแบบกระจาย
- ผู้จัดการเนื้อหา - ความรับผิดชอบ เงินเดือน การฝึกอบรม ข้อเสียและข้อดีของการทำงานเป็นผู้เชี่ยวชาญด้านเนื้อหา
- จะป้องกันตัวเองจากการขุดที่ซ่อนอยู่ในเบราว์เซอร์ของคุณได้อย่างไร?
- การกู้คืนรหัสผ่านใน Ask
- วิธีเปิดกล้องบนแล็ปท็อป
- ทำไมเพลงไม่เล่นบน VKontakte?
- วิธีเพิ่มขนาดของไดรฟ์ C โดยเสียค่าใช้จ่ายของไดรฟ์ D โดยไม่สูญเสียข้อมูล
- สาเหตุของการทำงานผิดพลาดบนเมนบอร์ด หากชิปเซ็ตบนเมนบอร์ดเกิดไฟไหม้