สารบัญ:

เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!: 9 ขั้นตอน (พร้อมรูปภาพ)
เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!: 9 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!: 9 ขั้นตอน (พร้อมรูปภาพ)

วีดีโอ: เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!: 9 ขั้นตอน (พร้อมรูปภาพ)
วีดีโอ: สอนทำคีย์การ์ด Arduino RFID-RC522 (NTW Production) 2024, กรกฎาคม
Anonim
เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!
เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!
เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!
เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!
เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!
เปลี่ยน Arduino ของคุณให้เป็นเครื่องอ่านบัตรแม่เหล็ก!

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

คำแนะนำนี้จะแสดงวิธีเชื่อมต่อเครื่องอ่านการ์ดแม่เหล็ก Magtek กับ AVR หรือ Arduino/โคลน และอ่านข้อมูลจากแทร็กแรกของการ์ด รัดที่นั่งของคุณ เครื่องอ่านบัตรแม่เหล็กมีบิตเรทสูง!

ขั้นตอนที่ 1: รายการอุปกรณ์

รายการอุปกรณ์
รายการอุปกรณ์
รายการอุปกรณ์
รายการอุปกรณ์

ต่อไปนี้คือสิ่งที่คุณจะต้องเริ่มต้น

  • เครื่องอ่านบัตรแม่เหล็ก (ของฉันคือเครื่องอ่านสองหัว Magetk 90 มม. $5.00)
  • AVR, Arduino หรือโคลน (ATmega328p ~ $4.30 จาก Mouser.com
  • เขียงหั่นขนมไม่มีบัดกรี
  • สายบาง
  • อาจเป็นส่วนหัวถ้าคุณชอบสิ่งนั้น
  • บางอย่างเพื่ออ่านพอร์ตอนุกรมของคุณ ฉันใช้ AVR Terminal จาก BattleDroids.net

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

ขั้นตอนที่ 2: เครื่องอ่านบัตรแม่เหล็กแบบคล็อกตัวเอง

เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้
เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้
เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้
เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้
เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้
เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้
เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้
เครื่องอ่านบัตรแม่เหล็กแบบตั้งเวลาได้

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

ข้อมูลของเครื่องอ่านการ์ดนี้ถูกต้อง 1.0 เราก่อนที่จะวางแฟลชลงบนเส้น ดังนั้นจึงไม่ต้องกังวลกับการล่าช้าในการเข้าสู่ "บิตไทม์" สำหรับเครื่องอ่านสองหัวเช่นที่ฉันใช้อยู่ มีแทร็กข้อมูลให้อ่านสองแทร็ก ใน 'ible นี้ ฉันจะแสดงการอ่านจากแทร็กแรกหลักเพื่อช่วยให้คุณเริ่มต้นได้ มีห้าการเชื่อมต่อที่คุณต้องทำ (สี่รายการถ้าคุณไม่รังเกียจที่จะให้การควบคุมที่ปรับแต่งมาอย่างดียิ่งขึ้นสำหรับพอร์ต I/O ที่น้อยลงที่ใช้) ตรวจสอบภาพด้านล่าง สายสีแดงไปที่ +5V ในขณะที่สายสีดำลงไปที่กราวด์ สายสีเขียวคือ /CARD_PRESENT; สายสีเหลืองคือ /STROBE และสายสีขาวคือ /DATA1 เครื่องหมายทับ (/) หมายความว่าข้อมูลถูกกลับด้าน สัญญาณต่ำ (เช่น 0) จะถูกอ่านเป็นสัญญาณเดียวหรือสูง ตัวเชื่อมต่ออื่นๆ เป็นสีน้ำตาลสำหรับ /STROBE2 และสีส้มสำหรับ /DATA2 เราจะไม่ใช้สิ่งเหล่านี้ หากต้องการ คุณสามารถลืม /CARD_PRESENT ได้เลย สายข้อมูลนี้เหลือน้อยหลังจากการหมุนของเฮดฟลักซ์ประมาณ 17 ครั้งเพื่อระบุว่ามีการ์ดอยู่ (แทนที่จะพูดว่า มีเสียงรบกวนแบบสุ่มทำให้เครื่องอ่านของคุณส่งข้อมูลปลอม) และใช้เพื่อตรวจสอบว่าข้อมูลที่คุณได้รับคือข้อมูลการ์ดและ ไม่ใช่ขยะ คุณสามารถข้ามการเชื่อมต่อนี้ได้หากคุณตรวจสอบการเริ่มต้นของ Sentinel ในสตรีมข้อมูล เพิ่มเติมในภายหลัง ดังที่คุณเห็นด้านล่าง ฉันใช้ส่วนหัวชายมุมฉากที่เชื่อมต่อกับบอร์ดขนมปัง และเชื่อมต่อผู้อ่านของฉันกับสิ่งนั้น ฉันเชื่อมต่อ /STROBE กับ PIND2 (พินดิจิตอล 2 บน Arduino), /CARD_PRESENT ถึง PIND3 (เพื่อจุดประสงค์ในการอธิบาย) และ /DATA1 ถึง PIND4 ตรวจสอบให้แน่ใจว่าคุณเปิดใช้งานพูลอัพบนหมุดเหล่านี้ หมุดของคุณจะไม่ลอย ฉันยังแลก Arduino ของฉันกับ Bare Bones AVR เพราะฉันชอบวิธีที่มันพอดีกับเขียงหั่นขนม

ขั้นตอนที่ 3: ข้อมูลเบื้องต้นเกี่ยวกับบัตรแม่เหล็ก

ข้อมูลเบื้องต้นเกี่ยวกับบัตรแม่เหล็ก
ข้อมูลเบื้องต้นเกี่ยวกับบัตรแม่เหล็ก

ฟังก์ชันหลักที่คุณต้องทำเพื่ออ่านการ์ดแม่เหล็กคือ: 1. ตรวจจับเมื่อรูดการ์ด 2. อ่านสตรีมข้อมูล 3. ตรวจจับเมื่อการ์ดหายไป 4. ประมวลผลข้อมูล 5. แสดง ข้อมูล อันดับแรก ฉันจะแนะนำคุณเกี่ยวกับข้อมูลเบื้องต้นเกี่ยวกับการ์ดแม่เหล็กที่คุณจำเป็นต้องรู้เมื่อคุณเริ่มเขียนโค้ดของคุณเอง

มาตรฐานบัตรแม่เหล็ก

บัตรแม่เหล็กได้รับมาตรฐานโดย ISO ในเอกสารต่อไปนี้: 7810 ลักษณะทางกายภาพของเอกสารขนาดบัตรเครดิต 7811-1 ลายนูน 7811-2 แถบแม่เหล็ก - ความบีบบังคับต่ำ 7811-3 ตำแหน่งของตัวอักษรนูน 7811-4 ตำแหน่งของแทร็ก 1 & 2 7811- 5 ตำแหน่งของแทร็ก 3 7811-6 แถบแม่เหล็ก - แรงบีบบังคับสูง 7813 บัตรธุรกรรมทางการเงิน อย่างที่คุณเห็น บัตรการเงินระบุไว้ในเอกสารแยกต่างหาก และมักมีรูปแบบที่แตกต่างจากบัตรของชำหรือบัตรโทรศัพท์ระหว่างประเทศ คุณจะต้องตั้งโปรแกรมสำหรับความแตกต่างเหล่านี้ ฉันเพิ่งมีบัตรเครดิตและบัตรประกันติดตัว ดังนั้นฉันจึงตั้งโปรแกรมสำหรับประเภทเหล่านี้ (ซึ่งทั้งคู่เกิดขึ้นเป็นรูปแบบ B)

รูปแบบการ์ด

บัตรแม่เหล็กมีหลายรูปแบบ รูปแบบ A และ B เป็นแบบทั่วไป โดย B เป็นรูปแบบที่พบได้บ่อยที่สุดที่ฉันเคยเห็น และได้รับการสนับสนุนในโค้ดนี้ ฉันเชื่อว่ารูปแบบ C ถึง M นั้นสงวนไว้โดย ISO ในขณะที่ N ถึง ?? สงวนไว้สำหรับการใช้งานแบบกำหนดเองของสถาบัน แทร็กที่ 1 สำหรับการ์ดการเงิน แทร็กแรกจะถูกบันทึกที่ 210 บิตต่อนิ้ว และเป็น 0.110" แรกของการ์ดจากด้านบน ข้อมูลจะถูกเข้ารหัสเป็น "ข้อมูลการ์ด" เป็น 7 บิตต่ออักขระ นั่นคือ 6 บิตสำหรับ อักขระและบิตสำหรับความเท่าเทียมกัน มี ~ 79 อักขระที่เป็นตัวอักษรและตัวเลขในแทร็ก 1 การเรียงลำดับทางกายภาพเป็นแบบย้อนกลับ นั่นคือ data คือ แต่มันถูกเขียนย้อนกลับบนการ์ด (และด้วยเหตุนี้ เฟิร์มแวร์ของคุณจะถูกอ่าน) เป็น. parity เป็นเลขคี่ รูปแบบข้อมูลการ์ดมีลักษณะดังนี้:

[SS] [FC] [บัญชีหลัก #] [FS] [ชื่อ] [FS] [ข้อมูลเพิ่มเติม] [FS][ES][LRC]โดยที่:

SS Start Sentinel FC รหัสรูปแบบ FS ตัวคั่นฟิลด์ ES End Sentinel LRC Longitudinal Redundancy ตรวจสอบอักขระ ติดตามหนึ่ง SS = '%', FC = หนึ่งในรูปแบบ (จะเป็น B หลายครั้ง), FS มักจะ '', ES คือ '?' และอักขระ LRC โดยทั่วไปคือ '<' แม้ว่าจะไม่ได้ระบุไว้ในมาตรฐานก็ตาม นอกจากการเขียนบนการ์ดแบบย้อนกลับแล้ว ข้อมูลยังมีพาริตีบิตคี่และเป็น 0x20 จาก ASCII เราจะจัดการเรื่องนี้เมื่อเราประมวลผลข้อมูล แทร็กที่ 2 แทร็กที่สองกว้าง 0.110 นิ้วและเริ่มต้นที่ 0.110 จากด้านบนของการ์ด ความหนาแน่นในการบันทึกคือ 75 บิตต่อนิ้ว ข้อมูลคือ 5 บิตต่ออักขระและประกอบด้วยสัญลักษณ์ตัวเลขประมาณ 40 ตัวเท่านั้น คุณไม่ควรพบ ตัวอักษรบนแทร็กนี้ รูปแบบข้อมูลการ์ดควรเป็นไปตามโครงสร้างนี้

[SS] [บัญชีหลัก #] [FS] [ข้อมูลเพิ่มเติม | ข้อมูลการตัดสินใจ] [ES] [LRC]

SS สำหรับแทร็กที่สองคือเครื่องหมายอัฒภาค: ';' และ FS คือ '=' ด้วยความรู้อันศักดิ์สิทธิ์นี้ภายใต้เข็มขัดของคุณ ให้ทำตามขั้นตอนต่อไปเพื่อดูโค้ดที่นำขั้นตอนที่อธิบายข้างต้นไปใช้

ขั้นตอนที่ 4: ตรวจจับเมื่อรูดการ์ด

ตรวจจับเมื่อรูดการ์ด
ตรวจจับเมื่อรูดการ์ด

1. ตรวจจับว่าการ์ดถูกรูดเมื่อใด ทางการจะตรวจสอบพิน /CARD_PRESENT เพื่อดูว่าการ์ดตกลงต่ำหรือไม่ โชคดีที่ไม่จำเป็นจริงๆ เราจะตรวจสอบบัตรที่ถูกต้องในภายหลัง อีกวิธีหนึ่ง คุณสามารถอ่านพินแฟลชของคุณเพื่อดูว่ามีการวางสโตรบบนพินเมื่อใด อย่างไรก็ตาม การทำเช่นนี้จะทำให้คุณมีศูนย์ตอกบัตรจำนวนมาก ผู้อ่านจะส่งศูนย์นำหน้าประมาณ 60-70 เพื่อแจ้งให้คุณทราบว่าข้อมูลกำลังจะถูกนำเสนอ อย่างไรก็ตาม เราจะใช้ลักษณะของข้อมูลไบนารีเพื่อกำหนดว่าเมื่อใดที่จะเริ่มบันทึกบิต ยามเริ่มต้น (SS) สำหรับแทร็กที่หนึ่งคือเครื่องหมายเปอร์เซ็นต์ (%) ค่าไบนารีคือ 0010 0101 ซึ่งหมายความว่าจะถูกจัดเก็บ (และอ่าน) เป็น 1010 001 (เป็น 7 บิตจึงไม่ส่งบิตที่ 8) ตอนนี้ ผู้อ่านที่ฉลาดหลักแหลมจะสังเกตเห็นว่าแม้ว่าข้อมูลจะย้อนหลัง จะไม่ตรงกับค่า ASCII แบบไบนารี นั่นเป็นเพราะมัน 0x20 จากเลขฐานสิบหก สัญลักษณ์ % คือ 0x25 และ 0100 0101 คือ 0x05 ข้อมูลบัตรถูกลบ 0x20 จากค่า คนที่ห้อยอยู่ที่นั่นในการตอดสูงนั้นเป็นบิตที่เท่าเทียมกัน มันถูกวางไว้เพื่อให้มีค่าเป็นเลขคี่ของ "1" เนื่องจากเรารู้ว่าการ์ดที่ถูกต้องจะเริ่มต้นด้วยเซนติเนลเริ่มต้นนี้เสมอ และเนื่องจากบิตพาริตีเป็น 1 จากนั้นเมื่อเราตรวจพบการเปลี่ยนสถานะ HIGH เป็น LOW ครั้งแรกบนพินข้อมูล เรารู้ว่าเราเพิ่งเริ่มรับ เริ่มรักษาการณ์จากการ์ด ตอนนี้ สิ่งนี้ไม่เป็นความจริงเสมอไป และแผนที่จะเข้าใจผิดได้ก็คือการตรวจสอบการ์ด /CARD_PRESENT เพื่อดูว่าบัตรเหลือ LOW หรือไม่ วิธีที่ง่ายที่สุดในการตรวจจับการเริ่มต้นของ SS คือการสร้างการขัดจังหวะภายนอกที่ทริกเกอร์บนขอบล้มของ /STROBE ข้อมูลมีความถูกต้อง 1.0 เราก่อนถึงขอบตก ดังนั้นเมื่อคุณได้สุ่มตัวอย่างขอบตก คุณจะรู้ว่าคุณสามารถอ่านพิน /DATA1 และรับค่าที่ถูกต้องได้ นี่คือรหัสสำหรับสร้างอินเตอร์รัปต์ภายนอกของคุณที่ทริกเกอร์บนขอบที่ตกลงมา

voidInitInterrupt (เป็นโมฆะ) { // ตั้งค่าการขัดจังหวะ BSET (EIMSK, INT0); // หน้ากากขัดจังหวะภายนอก BSET(EICRA, ISC01); // ขอบตก BCLR(EICRA, ISC00); // ขอบตก BSET(SREG, 7); // I-bit ใน SREG}

ใน common.h ของฉันที่ฉันรวมไว้ในโปรแกรมทั้งหมดของฉัน คุณสามารถหาคำจำกัดความของ BSET และ BCLR ได้ อ้างถึงไฟล์นั้นหากคุณมีคำถามเกี่ยวกับวิธีการตั้งค่าบิต ตอนนี้ เมื่ออินเตอร์รัปต์ถูกทริกเกอร์ เราต้องการสุ่มตัวอย่าง /DATA1 (ในรหัสของฉันที่กำหนดเป็น CARD_DATA) และตั้งค่าบิตในการลงทะเบียน IO วัตถุประสงค์ทั่วไป ถ้าเราเป็นบิตที่ 7 ให้บันทึกการลงทะเบียนเป็นอักขระในบัฟเฟอร์สากลของเรา ฉันใช้การลงทะเบียน GPIOR0 เพราะเข้าถึงได้อย่างรวดเร็ว รหัสเทียมมีลักษณะดังนี้:

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

หากคุณถามตัวเองว่าทำไมการลดลงแทนที่จะเพิ่มขึ้น โปรดจำไว้ว่าข้อมูลนั้นถอยหลัง ดังนั้นแทนที่จะบันทึกบิตในขณะที่เราได้รับจาก LSB ไปยัง MSB เราจะบันทึกจาก MSB ไปยัง LSB ดังนั้นเราจึงไม่ต้องย้อนกลับบิต ภายหลังเมื่อประมวลผลข้อมูล หากคุณต้องการจริงๆ คุณสามารถเพิ่มเลขฐานสิบหก 0x20 ได้ที่นี่ แต่เนื่องจากมันอยู่ที่ประมาณ 5us บนสโตรปเหล่านี้ ฉันกำลังทำให้การประมวลผลในรูทีนบริการอินเตอร์รัปต์นี้เหลือน้อยที่สุด

ISR (INT0_vect) { StopTimer (); ClearTimer(); if (!BCHK(PIND, CARD_DATA1)) // ผกผันต่ำ = 1 { BSET(GPIOR0, บิต); --นิดหน่อย; bDataPresent = 1; } อื่น ๆ ถ้า (bDataPresent) { BCLR (GPIOR0, บิต); --นิดหน่อย; } ถ้า (บิต < 0) { หนัง [idx] = (ถ่าน) GPIOR0; ++idx; บิต = 6; } StartTimer();} หากคุณสงสัยว่าธุรกิจเกี่ยวกับจังหวะเวลานั้นเกี่ยวกับอะไร เราจะพูดถึงขั้นตอนในการพิจารณาว่าการ์ดจะออกจากเครื่องอ่านเมื่อใด

ขั้นตอนที่ 5: อ่านสตรีมข้อมูล

อ่านกระแสข้อมูล

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

ขั้นตอนที่ 6: ตรวจหาการ์ดที่ออกจาก Reader

ตรวจจับการ์ดออกจาก Reader
ตรวจจับการ์ดออกจาก Reader

ตรวจจับเมื่อการ์ดหายไป

อย่างเป็นทางการ เราจะสุ่มตัวอย่างพิน /CARD_PRESENT เพื่อดูว่าขาขึ้นสูงอีกครั้งหรือไม่ แต่เราไม่ต้องการ steenkin' /CARD_PRESENT เพื่อรับพอร์ต I/O อื่น นี่คือที่มาของตัวจับเวลา ทุกครั้งที่มีการเรียกอินเตอร์รัปต์เนื่องจากเราตรวจพบขอบตกบน /STROBE เราจะหยุดตัวจับเวลา ล้างค่าตัวจับเวลา และเริ่มอ่าน เมื่อเราอ่านจบ เราก็เริ่มจับเวลาอีกครั้ง ทำซ้ำ ad nauseum หรือจนกว่าตัวจับเวลาจะถึงค่าที่กำหนด นั่นหมายความว่ามีการเรียกอินเตอร์รัปต์ล่าสุดและไม่มีข้อมูลเข้ามาอีก ดังนั้นเราจึงถือว่าเป็นเช่นนั้นและเริ่มประมวลผลข้อมูลที่เราได้รวบรวมไว้ สำหรับตัวจับเวลา เราใช้ TIMER1 เช่น ตัวจับเวลาแบบ 16 บิต ฉันใช้เรโซเนเตอร์ 16 Mhz กับ AVR ภายนอก หากคุณใช้ Arduino คุณก็เช่นกัน ดังนั้นฉันจึงเลือกค่าพรีสเกลเลอร์ที่ 1024 ซึ่งหมายความว่าทุกๆ (16, 000, 000 / 1024) ครั้งที่ตัวจับเวลาจะเพิ่มขึ้น กล่าวคือจะ 'ขีด' 15, 625 ครั้งต่อวินาที /CARD_PRESENT จะขึ้นสูงแสดงว่าการ์ดออกจากเครื่องอ่านประมาณ 150 มิลลิวินาทีหลังจากบิตข้อมูลล่าสุด เมื่อรู้อย่างนี้ ฉันจึงตัดสินใจตรวจสอบทุกๆ 1/4 ของวินาที ที่จะมีลักษณะเช่นนี้:

(((F_CPU) / PRESCALER) / 4) ซึ่งกลายเป็นประมาณ 3900 ดังนั้นเมื่อตัวนับเวลา TCNT1 ถึง 3900 ฉันรู้ว่ามันประมาณ 300 มิลลิวินาทีและฉันสามารถสรุปได้อย่างปลอดภัยว่าการ์ดได้ออกจากเครื่องอ่านแล้ว ง่าย

#define PRESCALER 1024#define CHECK_TIME ((F_CPU / PRESCALER) / 4) // 250 ms#define StartTimer() BSET(TCCR1B, CS10), BSET(TCCR1B, CS12) // 1024 prescaler#define StopTimer() BCLR(TCCR1B), CS10), BCLR(TCCR1B, CS12)#define ClearTimer() (TCNT1 = 0) คุณเคยเห็นใน ISR ที่ตัวจับเวลาเริ่ม หยุด และล้างการขัดจังหวะแต่ละครั้ง ตอนนี้ ในลูปหลัก เราแค่ตรวจสอบว่าตัวนับเวลาถึงค่าเป้าหมายของเราหรือไม่ และถ้าใช่ ให้เริ่มการประมวลผลข้อมูล

สำหรับ (;;) { ถ้า (TCNT1 >= CHECK_TIME) {

StopTimer(); ClearTimer(); ประมวลผลข้อมูล(); อ่านข้อมูล (); idx = 0; บิต = 6; bDataPresent = 0; memset(&buff, 0, MAX_BUFF_SZ1); } } ตอนนี้ประมวลผลข้อมูลได้อย่างปลอดภัยแล้ว

รหัสที่จัดรูปแบบโดย

ขั้นตอนที่ 7: ประมวลผลข้อมูล

ประมวลผลข้อมูล
ประมวลผลข้อมูล

ประมวลผลข้อมูล

ขั้นตอนการประมวลผลประกอบด้วย:

  • กำลังตรวจสอบ SS. ที่ถูกต้อง
  • การตรวจสอบความเท่าเทียมกัน
  • แปลงเป็น ASCII
  • กำลังตรวจสอบ ES. ที่ถูกต้อง
  • ตรวจสอบ LRC

ที่นี่ ฉันไม่กังวลกับการตรวจสอบความเท่าเทียมกัน เนื่องจากฉันเพิ่งตั้งบิตนั้นเป็นศูนย์ ฉันไม่ได้คำนวณ LRC สำหรับบทช่วยสอนเล็กๆ นี้ด้วย นั่นจะเป็นสิ่งที่เฟิร์มแวร์ที่รับรู้ได้อย่างสมบูรณ์ยิ่งขึ้นอาจต้องการทำ นี่คือรหัสสำหรับประมวลผลข้อมูลตามขั้นตอนข้างต้น (ไม่กล่าวถึงก่อนหน้านี้) ค้นหาได้ในภาพด้านล่าง มันแสดงความคิดเห็นและค่อนข้างอธิบายตนเอง หมายเหตุพิเศษเกี่ยวกับพาริตีและ ASCII: ฉันเพียงแค่ล้างพาริตี้บิต (บิตที่ 7…คือ 1 โดยมีศูนย์ 6 ตัวอยู่ด้านหลัง) และการแปลงจาก "ข้อมูลการ์ด" คุณต้องเพิ่ม 0x20 เป็นค่า เกี่ยวกับมัน.

ขั้นตอนที่ 8: แสดงข้อมูล

แสดงข้อมูล
แสดงข้อมูล
แสดงข้อมูล
แสดงข้อมูล

แสดงข้อมูล

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

ขั้นตอนที่ 9: ดาวน์โหลดโค้ดและสรุปข้อมูล

ในคำแนะนำนี้ ฉันได้พูดถึงพื้นฐานของเครื่องอ่านการ์ดแม่เหล็กและแสดงรหัสเพื่อให้คุณเริ่มต้นในทิศทางที่ถูกต้องในการอ่านข้อมูลจากการ์ดแม่เหล็ก มีงานอีกมากมายที่สามารถทำได้ เช่น การอ่านและการถอดรหัสแทร็กที่ 2 การคำนวณ LRC และการคำนวณความเท่าเทียมกันที่คี่ในแต่ละไบต์ สามารถดาวน์โหลดซอร์สโค้ดแบบเต็มได้ที่ด้านล่าง มันถูกเขียนใน AVR Studio 4.17 ฉันหวังว่าคุณจะสนุกกับการสอนนี้ และเช่นเคย ฉันหวังว่าจะได้ความคิดเห็นหรือข้อเสนอแนะใดๆ ที่คุณอาจมี ขอให้สนุกกับการเขียนโค้ดและ AVR!

แนะนำ: