เรารู้จักในสำนักงานห้างสรรพสินค้าและสถานที่อื่น ๆ อีกมากมายที่อนุญาตให้เฉพาะบุคคลที่มีบัตรอนุญาตเข้าห้องเท่านั้น ระบบเหล่านี้ใช้ระบบสื่อสาร RFID RFID ใช้ในห้างสรรพสินค้าเพื่อหยุดการโจรกรรมเนื่องจากผลิตภัณฑ์ถูกติดแท็กด้วยชิป RFID และเมื่อบุคคลออกจากอาคารด้วยชิป RFID สัญญาณเตือนจะดังขึ้นโดยอัตโนมัติ แท็ก RFID ได้รับการออกแบบให้มีขนาดเล็กเท่าส่วนของทราย ระบบตรวจสอบความถูกต้องของ RFID นั้นออกแบบได้ง่ายและมีราคาถูก โรงเรียนและวิทยาลัยในปัจจุบันบางคนใช้ RFID ที่ใช้ระบบการเข้าร่วมประชุม
ในโครงการนี้เราจะออกแบบเครื่องลงคะแนนที่นับเฉพาะคะแนนเสียงที่รับรองความถูกต้องเท่านั้น ทำได้โดยใช้แท็ก RFID (การระบุความถี่วิทยุ) ที่นี่เราจะเขียนโปรแกรมสำหรับ ATMEGA เพื่อให้ผู้ถือแท็ก RFID ที่ได้รับอนุญาตเท่านั้นที่สามารถลงคะแนนได้ (ตรวจสอบโครงการเครื่องลงคะแนนแบบง่ายนี้ด้วย)
ส่วนประกอบที่จำเป็น
ฮาร์ดแวร์: ATMEGA32, แหล่งจ่ายไฟ (5v), AVR-ISP PROGRAMMER, JHD_162ALCD (16x2LCD), ตัวเก็บประจุ 100uF (เชื่อมต่อกับแหล่งจ่ายไฟ), ปุ่ม (ห้าชิ้น), ตัวต้านทาน10KΩ (ห้าชิ้น), ตัวเก็บประจุ 100nF (ห้าชิ้น), LED (สองชิ้น), EM-18 (โมดูลเครื่องอ่าน RFID)
ซอฟต์แวร์: Atmel studio 6.1, progisp หรือ flash magic
แผนภาพวงจรและคำอธิบาย
ในวงจร PORTA ของ ATMEGA32 เชื่อมต่อกับพอร์ตข้อมูลของ LCD ที่นี่อย่าลืมปิดการใช้งานการสื่อสาร JTAG ใน PORTC เป็น ATMEGA โดยการเปลี่ยนฟิวส์ไบต์หากต้องการใช้ PORTC เป็นพอร์ตการสื่อสารปกติ ในจอ LCD 16x2 จะมี 16 พินโดยรวมหากมีแสงสีดำหากไม่มีไฟส่องหลังจะมี 14 พิน หนึ่งสามารถจ่ายไฟหรือปล่อยหมุดไฟด้านหลัง ตอนนี้ใน 14 พินมีพินข้อมูล 8 พิน (7-14 หรือ D0-D7), พินแหล่งจ่ายไฟ 2 พิน (1 & 2 หรือ VSS & VDD หรือ gnd & + 5v), พิน3 rdสำหรับควบคุมคอนทราสต์ (VEE- ควบคุมความหนาของตัวอักษร แสดง), 3 พินควบคุม (RS & RW & E)
ในวงจรคุณสามารถสังเกตได้ว่าฉันใช้พินควบคุมเพียงสองอันทำให้เกิดความยืดหยุ่นในการทำความเข้าใจที่ดีขึ้นไม่ได้ใช้บิตคอนทราสต์และ READ / WRITE บ่อยครั้งดังนั้นจึงสามารถลัดลงกราวด์ ทำให้ LCD มีคอนทราสต์สูงสุดและโหมดอ่าน เราต้องควบคุมพิน ENABLE และ RS เพื่อส่งอักขระและข้อมูลตามนั้น
การเชื่อมต่อที่ทำกับ LCD มีดังต่อไปนี้:
PIN1 หรือ VSS ลงกราวด์
PIN2 หรือ VDD หรือ VCC ถึง + 5v
PIN3 หรือ VEE กับพื้น (ให้ความเปรียบต่างสูงสุดที่ดีที่สุดสำหรับผู้เริ่มต้น)
PIN4 หรือ RS (Register Selection) ถึง PD6 ของ uC
PIN5 หรือ RW (อ่าน / เขียน) ลงกราวด์ (ทำให้ LCD อยู่ในโหมดอ่านช่วยให้การสื่อสารสำหรับผู้ใช้ง่ายขึ้น)
PIN6 หรือ E (เปิดใช้งาน) ถึง PD5 ของ uC
PIN7 หรือ D0 ถึง PA0 ของ uC
PIN8 หรือ D1 ถึง PA1 ของ uC
PIN9 หรือ D2 ถึง PA2 ของ uC
PIN10 หรือ D3 ถึง PA3 ของ uC
PIN11 หรือ D4 ถึง PA4 ของ uC
PIN12 หรือ D5 ถึง PA5 ของ uC
PIN13 หรือ D6 ถึง PA6 ของ uC
PIN14 หรือ D7 ถึง PA7 ของ uC
ในวงจรคุณจะเห็นว่าเราใช้การสื่อสารแบบ 8 บิต (D0-D7) อย่างไรก็ตามนี่ไม่ใช่ภาคบังคับและเราสามารถใช้การสื่อสาร 4 บิต (D4-D7) ได้ แต่ด้วยโปรแกรมการสื่อสาร 4 บิตจะซับซ้อนเล็กน้อยดังนั้นฉันจึงชอบการสื่อสารแบบ 8 บิต
ดังนั้นจากการสังเกตเพียงตารางด้านบนเรากำลังเชื่อมต่อ 10 พินของ LCD เข้ากับคอนโทรลเลอร์ซึ่ง 8 พินเป็นพินข้อมูลและ 2 พินสำหรับควบคุม
ก่อนที่จะดำเนินการต่อเราต้องเข้าใจเกี่ยวกับการสื่อสารแบบอนุกรม โมดูล RFID ที่นี่จะส่งข้อมูลไปยังคอนโทรลเลอร์แบบอนุกรม มีโหมดการสื่อสารอื่น ๆ แต่เพื่อการสื่อสารที่ง่ายเราเลือก RS232 พิน RS232 ของโมดูลเชื่อมต่อกับพิน RXD ของ ATMEGA
ข้อมูลที่ส่งโดยโมดูล RFID จะเป็น:
ตอนนี้สำหรับอินเทอร์เฟซโมดูล RFID จำเป็นต้องใช้คุณสมบัติต่อไปนี้:
1. ต้องเปิดใช้งานพิน RXD (คุณสมบัติการรับข้อมูล) ของคอนโทรลเลอร์
2. เนื่องจากการสื่อสารเป็นแบบอนุกรมเราจึงจำเป็นต้องทราบเมื่อใดก็ตามที่ได้รับข้อมูลเพื่อที่เราจะสามารถหยุดโปรแกรมได้จนกว่าจะได้รับไบต์ที่สมบูรณ์ ซึ่งทำได้โดยการเปิดใช้งานการรับข้อมูลขัดจังหวะโดยสมบูรณ์
3. RFID ส่งข้อมูลไปยังคอนโทรลเลอร์ในโหมด 8 บิต ดังนั้นสองตัวอักษรจะถูกส่งไปยังคอนโทรลเลอร์พร้อมกัน สิ่งนี้แสดงในบล็อกของรูปที่ 3
4. จากรูปที่ 3 ไม่มีพาริตีบิตบิตหยุดหนึ่งบิตในข้อมูลที่ส่งโดยโมดูล
คุณสมบัติข้างต้นถูกตั้งค่าในรีจิสเตอร์คอนโทรลเลอร์ เราจะพูดถึงพวกเขาสั้น ๆ
สีแดง (RXEN): บิตนี้แสดงถึงคุณสมบัติการรับข้อมูลต้องตั้งค่าบิตนี้สำหรับข้อมูลจากโมดูลที่จะได้รับโดยคอนโทรลเลอร์และยังเปิดใช้งานพิน RXD ของคอนโทรลเลอร์
BROWN (RXCIE): ต้องตั้งค่าบิตนี้สำหรับการขัดจังหวะหลังจากการรับข้อมูลสำเร็จ เมื่อเปิดใช้งานบิตนี้เราจะได้รับรู้ทันทีหลังจากได้รับข้อมูล 8 บิต
PINK (URSEL): ต้องตั้งค่าบิตนี้ก่อนเปิดใช้งานบิตอื่นใน UCSRC หลังจากตั้งค่าบิตที่จำเป็นอื่น ๆ ใน UCSRC ต้องปิดใช้งาน URSEL หรือทำให้เป็นศูนย์
สีเหลือง (UCSZ0, UCSZ1, UCSZ2): บิตทั้งสามนี้ใช้สำหรับเลือกจำนวนบิตข้อมูลที่เรากำลังรับหรือส่งในครั้งเดียว
เนื่องจากข้อมูลที่ส่งโดยโมดูล RFID เป็นประเภทข้อมูล 8 บิต (FIGURE3) เราจึงต้องตั้งค่า UCSZ0, UCSZ1 เป็นหนึ่งและ UCSZ2 เป็นศูนย์
ORANGE (UMSEL): บิตนี้ถูกตั้งค่าโดยขึ้นอยู่กับว่าระบบกำลังสื่อสารแบบอะซิงโครนัส (ทั้งคู่ใช้นาฬิกาต่างกัน) หรือซิงโครนัส (ทั้งคู่ใช้นาฬิกาเดียวกัน)
เนื่องจากโมดูลและคอนโทรลเลอร์ใช้นาฬิกาที่แตกต่างกันบิตนี้จึงต้องตั้งค่าเป็นศูนย์หรือปล่อยให้อยู่คนเดียวเนื่องจากทั้งหมดถูกตั้งค่าเป็นศูนย์ตามค่าเริ่มต้น
สีเขียว (UPM1, UPM0): สองบิตนี้ได้รับการปรับตามความเท่าเทียมกันของบิตที่เราใช้ในการสื่อสาร
เนื่องจากโมดูล RFID ส่งข้อมูลโดยไม่มีความเท่าเทียมกัน (FIGURE3) เราจึงตั้งค่าทั้ง UPM1, UPM0 เป็นศูนย์หรือสามารถปล่อยให้อยู่คนเดียวได้เนื่องจากบิตทั้งหมดในการลงทะเบียนใด ๆ จะถูกตั้งค่าเป็นศูนย์
BLUE (USBS): บิตนี้ใช้สำหรับเลือกจำนวนบิตหยุดที่เราใช้ระหว่างการสื่อสาร
เนื่องจากโมดูล RFID ส่งข้อมูลด้วยบิตหยุดเดียว (รูปที่ 3) เราจึงต้องปล่อยบิต USBS ไว้เพียงอย่างเดียว
ในที่สุดเราต้องกำหนดอัตราการรับส่งข้อมูลจากรูปที่ 3 เป็นที่ชัดเจนว่าโมดูล RFID ส่งข้อมูลไปยังตัวควบคุมด้วยอัตราการส่งข้อมูลที่ 9600bps (บิตต่อวินาที)
อัตราการรับส่งข้อมูลถูกกำหนดไว้ในคอนโทรลเลอร์โดยเลือก UBRRH ที่เหมาะสม
ค่า UBRRH ถูกเลือกโดยอัตราการส่งข้อมูลอ้างอิงข้ามและความถี่คริสตัล CPU
ดังนั้นโดยค่า UBRR การอ้างอิงไขว้จะถูกมองว่าเป็น '6' ดังนั้นจึงกำหนดอัตราการส่งข้อมูล
มีปุ่มห้าปุ่มอยู่ที่นี่สี่ปุ่มสำหรับการเพิ่มคะแนนเสียงของผู้สมัครและปุ่มที่ห้าคือการรีเซ็ตคะแนนเสียงของผู้สมัครให้เป็นศูนย์ ตัวเก็บประจุที่มีอยู่ที่นี่มีไว้สำหรับลบล้างเอฟเฟกต์การตีกลับของปุ่ม หากถูกถอดออกคอนโทรลเลอร์อาจนับมากกว่าหนึ่งครั้งในแต่ละครั้งที่กดปุ่ม
ตัวต้านทานที่เชื่อมต่อกับพินมีไว้สำหรับ จำกัด กระแสเมื่อกดปุ่มเพื่อดึงพินลงมาที่พื้น เมื่อใดก็ตามที่กดปุ่มพินของคอนโทรลเลอร์ที่เกี่ยวข้องจะถูกดึงลงมาที่พื้นและด้วยเหตุนี้คอนโทรลเลอร์จะรับรู้ว่ามีการกดปุ่มบางปุ่มและต้องดำเนินการที่สอดคล้องกันอาจเป็นการเพิ่มการโหวตของผู้สมัครหรือการรีเซ็ตคะแนนโดยขึ้นอยู่กับปุ่มที่กด
เมื่อกดปุ่มที่เป็นตัวแทนของบุคคลที่เกี่ยวข้องคอนโทรลเลอร์จะเลือกและเพิ่มหมายเลขบุคคลที่เกี่ยวข้องภายในหน่วยความจำหลังจากเพิ่มขึ้นจะแสดงคะแนนของบุคคลที่เกี่ยวข้องบนจอ LCD 16x2
การทำงานของเครื่องลงคะแนนอธิบายได้ดีที่สุดตามขั้นตอนของรหัส C ด้านล่าง:
คำอธิบายรหัส
#include // header เพื่อเปิดใช้งานการควบคุมโฟลว์ข้อมูลผ่านพิน
#define F_CPU 1000000 // บอกความถี่คริสตัลคอนโทรลเลอร์ที่แนบมา
# รวม
#define E 5 // ให้ชื่อ“เปิดใช้งาน” 5 THขา PORTD เพราะมันจะเชื่อมต่อกับจอแอลซีดีเปิดใช้งานขา
# กำหนดหมายเลข 6 // ให้ชื่อ“registerselection” ถึง 6 THขา PORTD ตั้งแต่การเชื่อมต่อกับจอแอลซีดีอาร์เอสพิน
โมฆะ send_a_command (คำสั่ง char ที่ไม่ได้ลงชื่อ);
โมฆะ send_a_character (อักขระถ่านที่ไม่ได้ลงชื่อ);
โมฆะ send_a_string (ถ่าน * string_of_characters);
int หลัก (โมฆะ)
{
DDRA = 0xFF; // วาง porta เป็นพินเอาต์พุต
DDRD = 0b11111110;
_delay_ms (50); // ให้ดีเลย์ 50ms
DDRB = 0b11110000; // รับพิน portB เป็นอินพุต
UCSRB - = (1 <
// การเปิดใช้งานข้อมูลรับการขัดจังหวะโดยสมบูรณ์ทำให้พินรับข้อมูล
UCSRC - = (1 <
// เปลี่ยนบิตอื่น ๆ โดยการตั้งค่า URSEL ครั้งแรกตั้งค่าสำหรับการสื่อสาร 8 บิต
UCSRC & = ~ (1 <
UBRRH & = ~ (1 <
UBRRL = 6; // การตั้งค่าอัตราการส่งข้อมูล
int16_t VOTEA = 0; // person1 โหวตเก็บหน่วยความจำ
char A; // person1 คะแนนที่แสดงตัวอักษรบน LCD
int16_t VOTEB = 0;; // person2 โหวตเก็บความทรงจำ
ถ่าน B; // คน 2 โหวตแสดงตัวละครบนจอ LCD
int16_t VOTEC = 0;; // person3 โหวตเก็บความทรงจำ
ถ่าน C; // person3 โหวตที่แสดงตัวละครบน LCD
int16_t โหวต = 0;; // person4 โหวตเก็บความทรงจำ
char D; / / person4 โหวตที่แสดงตัวอักษรบน LCD
// ต่อไปนี้มี ID ของแท็กซึ่งต้องเปลี่ยนสำหรับแท็กอื่นต้องอัปเดตเพื่อให้โปรเจ็กต์ทำงานได้
// หลังจากทิ้งโปรแกรมในคอนโทรลเลอร์แล้วเราต้องนำการ์ดที่ต้องได้รับอนุญาตและรับ ID แท็กสิ่งเหล่านี้ได้มาจากการวางแท็กใกล้โมดูล RFID และ ID จะแสดงบนหน้าจอ หลังจากได้รับ ID แล้วโปรแกรมจะต้องได้รับการอัปเดตโดยแทนที่หมายเลข ID ด้านล่างด้วยหมายเลข ID ใหม่
ถ่าน ADMIT = {{(0x97), (0xa1), (0x90), (0x92)}, {(0x97), (0xa1), (0x90), (0x93)}, {(0x97), (0xa1), (0x90), (0x94)}, {(0x97), (0xa1), (0x90), (0x95)}, {(0x97), (0xa1), (0x90), (0x96)}}; |
ตอนนี้เราให้สิทธิ์การ์ดเพียงห้าใบเท่านั้นซึ่งสามารถเปลี่ยนเป็นหมายเลขใดก็ได้
ตัวอย่างเช่นพิจารณาว่าโปรแกรมดีฟอลต์ถูกทิ้งในคอนโทรลเลอร์รับการ์ดที่ควรได้รับอนุญาตทีละโมดูลที่อยู่ใกล้ ๆ คุณจะได้รับ ID สำหรับแต่ละอันเป็น xxxxxxxx (907a4F87)
หากเรามี 7 แท็กเราจะมี 7 แปดบิต ID
// ตอนนี้สำหรับไพ่เจ็ดใบจะเป็น // char ADMIT = {{(0x90), (0x7a), (0x4F), (0x87)},; // การจัดสรรหน่วยความจำสำหรับแสดง ID ที่ส่งโดยโมดูล int ผม = 0; int โหวต = 0; int k = 0; send_a_command (0x01); // ล้างหน้าจอ 0x01 = 00000001 _delay_ms (50); send_a_command (0x38); // บอก lcd ว่าเรากำลังใช้ 8bit command / data mode _delay_ms (50); send_a_command (0b00001111); // LCD SCREEN ON และ Courser กระพริบ char MEM; // การจัดสรรหน่วยความจำเพื่อจัดเก็บ ID ของแท็กที่สมบูรณ์ send_a_string ("หมายเลข RFID"); // ส่งสตริง send_a_command (0x80 + 0x40 + 0); // ย้าย Courser ไปยังบรรทัดที่สอง ในขณะที่ (1) { ในขณะที่ (! (UCSRA & (1 <
{ } COUNTA = UDR; // UDR เก็บข้อมูลแปดบิตที่ได้รับและนำมาเป็นจำนวนเต็ม MEM = COUNTA; // อักขระสองตัวแรกถูกอัปเดตเป็นหน่วยความจำ อิโตอา (COUNTA, SHOWA, 16); // คำสั่งสำหรับใส่หมายเลขตัวแปรใน LCD (หมายเลขตัวแปรอักขระที่จะแทนที่ฐานใดเป็นตัวแปร (สิบในที่นี้ขณะที่เรากำลังนับจำนวนในฐาน 10) send_a_string (SHOWA); // บอกให้จอแสดงผลแสดงอักขระ (แทนที่ด้วยหมายเลขตัวแปร) ของบุคคลที่สองหลังจากวางตำแหน่ง Courser บน LCD ในขณะที่ (! (UCSRA & (1 <
{ } COUNTA = UDR; อิโตอา (COUNTA, SHOWA, 16); send_a_string (SHOWA); MEM = COUNTA; // อักขระที่สามและสี่ถูกอัปเดตเป็นหน่วยความจำ ในขณะที่ (! (UCSRA & (1 <
{ } COUNTA = UDR; อิโตอา (COUNTA, SHOWA, 16); send_a_string (SHOWA); MEM = COUNTA; // อักขระที่ห้าและหกถูกอัปเดตเป็นหน่วยความจำ ในขณะที่ (! (UCSRA & (1 <
{ } COUNTA = UDR; อิโตอา (COUNTA, SHOWA, 16); send_a_string (SHOWA); MEM = COUNTA; // อักขระที่เจ็ดและแปดถูกอัปเดตเป็นหน่วยความจำ send_a_string (""); send_a_command (0x80 + 0x40 + 0); UCSRB & = ~ (1 <
สำหรับ (i = 0; i <5; i ++) { ถ้า ((MEM == ADMIT) & (MEM == ADMIT) & (MEM == ADMIT) & (MEM == ADMIT)) {// การตรวจสอบการอนุญาตซื้อโดยเปรียบเทียบอักขระสองตัวพร้อมกันกับอักขระในหน่วยความจำ PORTB - = (1 <
โหวต = 1; // หากได้รับอนุญาตตั้ง VOTE } } ถ้า (โหวต == 0) // การอนุญาตล้มเหลวหากไม่ได้ตั้งค่าการโหวต { UCSRB - = (1 <
} ในขณะที่ (โหวต == 1) // ทำวนซ้ำจนกว่าจะโหวตถ้าได้รับอนุญาต { send_a_command (0x80 + 0); // ไปที่ตำแหน่งศูนย์ในบรรทัดที่ 1 send_a_string ("VOTE NOW"); // กำลังแสดงสตริง ถ้า (bit_is_clear (PINB, 0)) // เมื่อกดปุ่มหนึ่ง { VOTEA ++; // เพิ่มหน่วยความจำการโหวตของคนแรกทีละคน โหวต = 0; // ปล่อยให้ while ลูปไปหลังจากโหวต } ถ้า (bit_is_clear (PINB, 1)) // เมื่อกดปุ่ม 2 { VOTEB ++; // เพิ่มหน่วยความจำการลงคะแนนจาก 2 ครั้ง คนโดยหนึ่ง โหวต = 0; } ถ้า (bit_is_clear (PINB, 2)) // เมื่อกดปุ่ม 3 { VOTEC ++; // เพิ่มหน่วยความจำการลงคะแนนจาก 3 ถนน คนโดยหนึ่ง โหวต = 0; } ถ้า (bit_is_clear (PINB, 3)) // เมื่อกดปุ่ม 4 { VOTED ++; // เพิ่มหน่วยความจำการลงคะแนนจาก 4 THคนโดยหนึ่ง โหวต = 0; } ถ้า (โหวต == 0) // เคลียร์หลังจากได้รับการโหวต { send_a_command (0x80 + 0); // ย้ายไปที่ตำแหน่งศูนย์ของบรรทัด 1 send_a_string ("ขอบคุณสำหรับการโหวต"); // display string สำหรับ (k = 0; k <10; k ++) { _delay_ms (220); } PORTB & = ~ (1 <
send_a_command (0x01); send_a_command (0x80 + 0); // แสดงผลโหวตของทั้งสี่ท่าน send_a_string ("A ="); send_a_command (0x80 + 2); อิโตอา (VOTEA, A, 10); send_a_string (A); send_a_command (0x80 + 8); send_a_string ("B ="); send_a_command (0x80 + 10); อิโตอา (VOTEB, B, 10); send_a_string (B); send_a_command (0x80 + 0x40 + 0); send_a_string ("C ="); send_a_command (0x80 + 0x40 + 2); อิโตอา (VOTEC, C, 10); send_a_string (C); send_a_command (0x80 + 0x40 + 8); send_a_string ("D ="); send_a_command (0x80 + 0x40 + 10); itoa (โหวต, D, 10); send_a_string (D); send_a_command (0x80 + 0x40 + 16); สำหรับ (k = 0; k <25; k ++) { _delay_ms (220); } UCSRB - = (1 <
send_a_command (0x01); send_a_command (0x80 + 0); // ย้ายไปที่ตำแหน่งศูนย์ send_a_string ("หมายเลข RFID"); // ส่งสตริง send_a_command (0x80 + 0x40 + 0); } } โมฆะ send_a_command (คำสั่ง char ที่ไม่ได้ลงชื่อ) { PORTA = คำสั่ง; PORTD & = ~ (1 <
พอร์ต - = 1 <
_delay_ms (50); พอร์ต & = ~ 1 <
ปอร์ตา = 0; } โมฆะ send_a_character (อักขระถ่านที่ไม่ได้ลงชื่อ) { PORTA = ตัวละคร; พอร์ต - = 1 <
พอร์ต - = 1 <
_delay_ms (50); พอร์ต & = ~ 1 <
ปอร์ตา = 0; } โมฆะ send_a_string (ถ่าน * string_of_characters) { ในขณะที่ (* string_of_characters> 0) { send_a_character (* string_of_characters ++); } } |