ดู DS1307 ตั้งแต่แนวคิดไปจนถึงการนำไปปฏิบัติ การเชื่อมต่อ DS1307 กับการเชื่อมต่อไมโครคอนโทรลเลอร์ AVR Ds1307

DS1307 เรียกอีกอย่างว่า RTC (นาฬิกาเรียลไทม์) ชิปนี้เป็นนาฬิกาและปฏิทินแบบเรียลไทม์ การสื่อสารกับไมโครวงจรดำเนินการผ่านอินเทอร์เฟซ I 2 C ข้อดีของมันคือใช้งานได้ (นับเวลา) เมื่อปิดไฟหลักจากแหล่งพลังงานสำรอง 3 โวลต์ (เช่นจากแบตเตอรี่ CR3022) แต่ DS1307 มีข้อเสียเปรียบประการหนึ่ง: มันไม่ได้ตรวจสอบว่าข้อมูลที่ป้อนนั้นถูกต้องหรือไม่ ในการทำงานกับไมโครวงจร คุณจะต้องมีชุดอุปกรณ์ขั้นต่ำ: ควอตซ์ที่ 32768Hz แบตเตอรี่ 3 โวลต์และตัวต้านทาน 4.7 kOhm สองตัว แผนภาพการเชื่อมต่อ DS1307:

การทำงานกับ DS1307 ใน BASCOM-AVR

ในการเริ่มทำงานกับไมโครเซอร์กิตคุณต้องกำหนดค่าพอร์ตที่ไมโครเซอร์กิตเชื่อมต่ออยู่ หากต้องการทำสิ่งนี้ให้ใช้คำสั่ง การกำหนดค่า:
กำหนดค่า Sda =(พอร์ตไมโครคอนโทรลเลอร์ที่เชื่อมต่อขา SDA ของชิป DS1307)
กำหนดค่า Scl =(พอร์ตไมโครคอนโทรลเลอร์ที่เชื่อมต่อขา SCL ของชิป DS1307)
ตัวอย่างเช่น:
กำหนดค่า Sda = Portb.1
กำหนดค่า Scl = Portb.0

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

I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte (ตัวแปรที่เราเขียนวินาที), Ack I2crbyte (ตัวแปรที่เราเขียนนาที), Ack I2crbyte (ตัวแปรที่เราเขียนชั่วโมง), Ack I2crbyte (ตัวแปรที่เราเขียน เขียนจำนวนวันในสัปดาห์), Ack I2crbyte (ตัวแปรที่เราเขียนวันที่), Ack I2crbyte (ตัวแปรที่เราเขียนหมายเลขเดือน), Ack I2crbyte (ตัวแปรที่เราเขียนปี), Nack I2cstop

หลังจากอ่านข้อมูลแล้ว คุณต้องแปลงเป็นรูปแบบทศนิยมดังนี้:
(ตัวแปรวินาที) = มาเดค((ตัวแปรวินาที) )
(ตัวแปรนาที) = มาเดค((ตัวแปรนาที) )
(ตัวแปรนาฬิกา) = มาเดค((ตัวแปรนาฬิกา) )
(ตัวแปรวันในสัปดาห์) = มาเดค((ตัวแปรวันในสัปดาห์) )
(ตัวแปรวันที่) = มาเดค((ตัวแปรวันที่) )
(ตัวแปรเดือน) = มาเดค((ตัวแปรเดือน) )
(ตัวแปรปี) = มาเดค((ตัวแปรปี) )

นี่คือตัวอย่างการอ่านเวลาและวันที่และแปลงเป็นรูปแบบทศนิยม:

I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte Seco , Ack I2crbyte Mine , Ack I2crbyte ชั่วโมง , Ack I2crbyte วัน , Ack I2crbyte Dat , Ack I2crbyte เดือน , Ack I2crbyte ปี , Nack I2cstop Seco = Makedec(seco M) ine = Makedec(ของฉัน) ชั่วโมง = Makedec(ชั่วโมง) วัน = Makedec(วัน) Dat = Makedec(dat) เดือน = Makedec(เดือน) ปี = Makedec(ปี)

เราได้เรียนรู้วิธีการอ่านข้อมูลแล้ว ทีนี้มาลองเขียนข้อมูลลงใน DS1307 กันดีกว่า แบบนี้:
(ตัวแปรที่เราจะเขียนลงไป) = เมคบีซีดี((ตัวแปรที่เราจะเขียนลงไป) )
I2cstart
I2cwbyte&HD0
I2ไบต์(เซลล์ที่เราจะเขียนข้อมูล)
I2ไบต์(ตัวแปรที่เราจะเขียนลงไป)
I2cstop

โปรดทราบว่าคำสั่ง Makebcdแปลงตัวแปรเป็นรูปแบบทศนิยมไบนารี หมายเลขเซลล์และการกำหนด:

นี่คือตัวอย่างการเขียนตัวแปรวินาที:
เซโก้ = Makebcd(เซโก้)
I2cstart
I2cwbyte&HD0
I2cwไบต์ 0
I2cwbyte Seco
I2ซีสต็อป
อย่างไรก็ตามควรสังเกตว่าเมื่อ DS1307 สตาร์ทเป็นครั้งแรก (เช่นเมื่อเชื่อมต่อแบตเตอรี่สำรอง) ไมโครวงจรจะส่งคืนค่า 80 เป็นวินาทีซึ่งหมายความว่านาฬิกาหยุดทำงาน หากต้องการเรียกใช้ ให้จดค่า 1 เป็นวินาที หาก DS1307 ส่งกลับค่า 255 หรือ 168 เมื่ออ่านข้อมูลใดๆ แสดงว่าชิปไม่ได้เชื่อมต่ออย่างถูกต้องหรือไม่มีแบตเตอรี่สำรอง

ใช้งานได้จริงด้วยชิป DS1307

ตอนนี้เรามาลองใช้งานชิป DS1307 ในทางปฏิบัติ: มาประกอบนาฬิกาง่ายๆ พร้อมตั้งเวลาโดยใช้ปุ่มต่างๆ ในการทำเช่นนี้ ลองใช้ชิป DS1307, ไมโครคอนโทรลเลอร์ Attiny2313, ไฟแสดงสถานะ LCD บนคอนโทรลเลอร์ HD44780 และส่วนประกอบแยกหลายชิ้น มาสร้างแผนภาพง่ายๆ กัน:

และมาเขียนโปรแกรมง่ายๆ โดยใช้ความรู้ที่ได้รับ:

$regfile = "attiny2313.dat" $crystal = 4000000 กำหนดค่า Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.3 , Rs = Portb .2 Config Lcd = 16 * 2 Config Pind.5 = Input Config Pind.4 = Input Config Sda = Portb.1 Config Scl = Portb.0 Dim Seco As Byte Dim Mine As Byte Dim Hour As Byte Initlcd Cls Cursor Off ทำ I2cstart I2cwbyte &HD0 I2cwbyte &H00 I2cstart I2cwbyte &HD1 I2crbyte Seco , Ack I2crbyte Mine , Ack I2crbyte ชั่วโมง , Nack I2cstop Seco = Makedec(seco) Mine = Makedec(ของฉัน) ชั่วโมง = Makedec(ชั่วโมง) ค้นหา 1 , 1 Lcd ชั่วโมง ; - ของฉัน; - เซโก้; " " ถ้า Pind.5 = 0 จากนั้น Incr Mine Mine = Makebcd(ของฉัน) I2cstart I2cwbyte &HD0 I2cwbyte 1 I2cwbyte Mine I2cstop Waitms 100 สิ้นสุด ถ้าถ้า Pind.4 = 0 จากนั้น Incr ชั่วโมง ชั่วโมง = Makebcd(ชั่วโมง) I2cstart I2cwbyte &HD0 I2cwbyte 2 I2cwbyte ชั่วโมง I2cstop Waitms 100 สิ้นสุด หากสิ้นสุดลูป

DS1307- ชิปนาฬิกาเรียลไทม์พร้อมอินเทอร์เฟซ I2C(TWI)- นาฬิกา/ปฏิทินจัดเก็บข้อมูลต่อไปนี้: วินาที นาที ชั่วโมง วัน วันที่ เดือน และปี วันสิ้นเดือนจะมีการปรับโดยอัตโนมัติสำหรับเดือนที่มีน้อยกว่า 31 วัน รวมถึงการปรับสำหรับด้วย ปีอธิกสุรทิน- นาฬิกาทำงานในรูปแบบ 24 ชั่วโมงหรือ 12 ชั่วโมงพร้อมตัวบ่งชี้ AM/PM DS1307 มีวงจรตรวจสอบพลังงานในตัวที่ตรวจจับการสูญเสียพลังงานและสลับวงจรไปใช้พลังงานแบตเตอรี่โดยอัตโนมัติ

วแบต- อินพุตแบตเตอรี่สำหรับเซลล์ลิเธียม 3 โวลต์มาตรฐานหรือแหล่งพลังงานอื่นๆ สำหรับการใช้งานปกติ ต้องรักษาแรงดันไฟฟ้าของแบตเตอรี่ให้อยู่ระหว่าง 2.5 ถึง 3.5 V ระดับที่ห้ามไม่ให้เข้าถึงนาฬิกาเรียลไทม์และ RAM ของผู้ใช้นั้นได้รับการตั้งค่าภายในไว้ที่ 1.25 x Vbat แบตเตอรี่ลิเธียมที่มีความจุ 35 mAh ขึ้นไปนั้นเพียงพอที่จะจ่ายไฟให้กับ DS1307 ได้นานกว่า 10 ปีหากไม่มีพลังงาน
เอสซีแอล(อินพุตนาฬิกาอนุกรม) - SCL ใช้เพื่อซิงโครไนซ์การถ่ายโอนข้อมูลผ่านอินเทอร์เฟซแบบอนุกรม
เอส.ดี.เอ.(อินพุต/เอาต์พุตข้อมูลอนุกรม) - SDA - อินพุต/เอาต์พุตข้อมูลสำหรับอินเทอร์เฟซแบบอนุกรม 2 สาย นี่คือเอาต์พุตเดรนแบบเปิดที่ต้องใช้ตัวต้านทานแบบดึงขึ้นภายนอก
ตร.ว./ออก(ไดร์เวอร์สแควร์สแควร์ / เอาท์พุต) - เมื่อบิต SQWE ถูกตั้งค่าเป็น 1 เอาต์พุต SQW/OUT จะสร้างพัลส์คลื่นสี่เหลี่ยมที่ความถี่หนึ่งในสี่ความถี่: 1 Hz, 4 kHz, 8 kHz, 32 kHz พิน SQW/OUT เป็นแบบเปิดและต้องใช้ตัวต้านทานแบบดึงขึ้นภายนอก
X1, X2- สายสำหรับเชื่อมต่อคริสตัลควอตซ์มาตรฐาน 32.768 kHz วงจรภายในของออสซิลเลเตอร์ได้รับการออกแบบให้ทำงานกับคริสตัลที่มีความจุปกติ (CL) อยู่ที่ 12.5 pF
จีเอ็นดี- โลก.
วีซีซี– แหล่งจ่ายไฟ 5 โวลต์

DS1307ทำงานเป็นอุปกรณ์ทาสบนบัสอนุกรม ในการเข้าถึงคุณจะต้องตั้งค่าสถานะ เริ่มและส่งรหัสประจำตัวอุปกรณ์ตามด้วยที่อยู่ลงทะเบียน การลงทะเบียนครั้งต่อไปสามารถเข้าถึงได้ตามลำดับจนกว่าจะมีการตั้งค่าสถานะ หยุด- เมื่อไร วีซีซีต่ำกว่า 1.25 x Vbat อุปกรณ์จะหยุดการสื่อสารและรีเซ็ตตัวนับที่อยู่ ในช่วงเวลานี้ มันจะไม่ตอบสนองต่อสัญญาณอินพุตเพื่อป้องกันการบันทึกข้อมูลที่ผิดพลาด เมื่อไร วีซีซีหากอยู่ต่ำกว่า Vbat อุปกรณ์จะสลับไปที่โหมดจัดเก็บข้อมูลพลังงานต่ำ เมื่อคุณเปิดเครื่อง อุปกรณ์จะเปลี่ยนพลังงานจากแบตเตอรี่เป็น วีซีซีเมื่อแรงดันไฟฟ้าเกิน Vbat + 0.2V และตอบสนองต่อสัญญาณอินพุตเมื่อใด วีซีซีจะกลายเป็นมากกว่า 1.25 x Vbat เมื่อพลังงานอยู่ในขีดจำกัดปกติ อุปกรณ์จะสามารถเข้าถึงได้อย่างเต็มที่และสามารถเขียนและอ่านข้อมูลได้ เมื่อเชื่อมต่อแบตเตอรี่สามโวลต์เข้ากับอุปกรณ์และ VCC ต่ำกว่า 1.25 x Vbat ห้ามอ่านและเขียน อย่างไรก็ตาม การนับถอยหลังเวลายังคงทำงานอยู่ เมื่อไร วีซีซีต่ำกว่า Vbat แหล่งจ่ายไฟ RAM และการจับเวลาจะเปลี่ยนไปใช้แบตเตอรี่ภายนอก 3 V

ข้อมูลเวลาและวันที่ได้มาจากการอ่านบันทึกที่เกี่ยวข้อง การลงทะเบียนนาฬิกาแสดงอยู่ในตารางด้านล่าง เวลาและปฏิทินถูกตั้งค่าหรือเริ่มต้นโดยการเขียนไบต์ไปยังรีจิสเตอร์ที่เหมาะสม เนื้อหาของการลงทะเบียนเวลาและปฏิทินจะถูกจัดเก็บไว้ใน BCD (บีซีดี)ดังนั้นก่อนที่จะแสดงข้อมูลบนจอ LCD หรือตัวบ่งชี้เจ็ดส่วน จำเป็นต้องแปลงรหัส BCD เป็นรหัสไบนารี่หรือ ANSII

บิต 7 ของรีจิสเตอร์ 0 คือบิต Clock Halt เมื่อบิตนี้ถูกตั้งค่าเป็น 1 ตัวสร้างจะหยุดทำงาน เมื่อรีเซ็ตเป็นศูนย์ เครื่องกำเนิดไฟฟ้าจะทำงานและนาฬิกาจะนับเวลา

DS1307 สามารถทำงานในโหมด 12 ชั่วโมงหรือ 24 ชั่วโมงได้ บิต 6 ของการลงทะเบียนนาฬิการะบุหนึ่งในโหมดเหล่านี้ เมื่อเท่ากับ 1 โหมด 12 ชั่วโมงจะถูกตั้งค่า ในโหมด 12 ชั่วโมง ระดับสูงบิต 5 ระบุเวลาบ่าย ในโหมด 24 ชั่วโมง บิต 5 คือบิตที่สอง 10 ชั่วโมง (20-23 ชั่วโมง)

รีจิสเตอร์ควบคุม DS1307 ได้รับการออกแบบมาเพื่อควบคุมการทำงานของเอาต์พุต ตร.ว./ออก- นิดหน่อย ออก- การควบคุมเอาต์พุต บิตนี้จะควบคุมระดับเอาต์พุตของพิน ตร.ว./ออกเมื่อปิดใช้งานการสร้างคดเคี้ยว ถ้า SQWE = 0 ระดับตรรกะที่พิน ตร.ว./ออกเท่ากับ 1 ถ้า ออก= 1 และ 0 - ถ้า ออก = 0. ตาราง- ความละเอียดของการคดเคี้ยว เมื่อบิตนี้ถูกตั้งค่าเป็น 1 จะมีการเปิดใช้งานการสร้างคลื่นสี่เหลี่ยม ความถี่คลื่นสี่เหลี่ยมขึ้นอยู่กับค่าของบิต RS0 และ RS1 บิตเหล่านี้จะควบคุมความถี่ของคลื่นสี่เหลี่ยมเมื่อเปิดใช้งานการสร้างคลื่น ตารางด้านล่างแสดงความถี่ที่สามารถระบุได้ด้วยบิต RS

DS1307 รองรับบัส 2 สายแบบสองทิศทางและโปรโตคอลการถ่ายโอนข้อมูล อุปกรณ์ที่ส่งข้อมูลไปยังบัสเรียกว่าเครื่องส่ง และอุปกรณ์ที่รับข้อมูลเรียกว่าเครื่องรับ อุปกรณ์ที่ควบคุมการส่งสัญญาณเรียกว่าอุปกรณ์หลัก อุปกรณ์ที่ควบคุมโดยต้นแบบนั้นเป็นอุปกรณ์รอง บัสจะต้องได้รับการควบคุมโดยมาสเตอร์ที่สร้างนาฬิกาอนุกรม (SCL) ควบคุมการเข้าถึงบัส และสร้างสถานะ START และ STOP DS1307 ทำงานเป็นทาสบนบัส 2 สาย

ในการทำงานกับ DS1307 จำเป็นต้องจัดระเบียบฟังก์ชันการอ่านจากชิปและฟังก์ชันการเขียน

1. โหมดบันทึกใน DS1307- ได้รับข้อมูลอนุกรมและนาฬิกาผ่าน SDA และ SCL หลังจากที่แต่ละไบต์ถูกส่ง บิตการตอบรับจะถูกส่งไป ถาม- รัฐ เริ่มและ หยุดได้รับการยอมรับว่าเป็นจุดเริ่มต้นและจุดสิ้นสุดของการส่งสัญญาณแบบอนุกรม การรู้จำที่อยู่จะดำเนินการในฮาร์ดแวร์หลังจากได้รับที่อยู่ทาสและบิตทิศทาง ไบต์ที่อยู่ประกอบด้วยที่อยู่เจ็ดบิตของ DS1307 ที่เป็น 1101000 ตามด้วยบิตทิศทาง (R/W) ซึ่งเป็น 0 เมื่อได้รับและถอดรหัสไบต์ที่อยู่ DS1307 จะออกการตอบรับ ถามบนสาย SDA หลังจากที่ DS1307 ยืนยันที่อยู่สเลฟและเขียนบิตแล้ว ต้นแบบจะส่งที่อยู่รีจิสเตอร์ไปยัง DS1307 นี่จะเป็นการตั้งค่าตัวชี้การลงทะเบียนใน DS1307 จากนั้นต้นแบบจะเริ่มส่งข้อมูลไบต์ไปยัง DS1307 ซึ่งจะรับทราบแต่ละไบต์ที่ได้รับ เมื่อสิ้นสุดการบันทึก ผู้นำเสนอจะสร้างสถานะ หยุด.

2. โหมดอ่านจาก DS1307- ไบต์แรกจะได้รับและประมวลผลในโหมดตัวรับทาส อย่างไรก็ตาม ในโหมดนี้ บิตทิศทางจะระบุว่าทิศทางการส่งสัญญาณเปลี่ยนไป ข้อมูลอนุกรมจะถูกส่งผ่าน SDA จาก DS1307 ในขณะที่นาฬิกาอนุกรมจะถูกส่งผ่าน SCL ไปยัง DS1307 รัฐ เริ่มและ หยุดได้รับการยอมรับว่าเป็นจุดเริ่มต้นและจุดสิ้นสุดของการส่งสัญญาณแบบอนุกรม ไบต์ที่อยู่คือไบต์แรกที่ได้รับหลังจากที่ต้นแบบสร้างสถานะแล้ว เริ่ม- ไบต์ที่อยู่ประกอบด้วยที่อยู่เจ็ดบิตของ DS1307 ที่ 1101000 ตามด้วยบิตทิศทาง (R/W) ซึ่งเป็น 1 เมื่ออ่าน เมื่อได้รับและถอดรหัสไบต์ที่อยู่แล้ว DS1307 จะออกการตอบรับ ถามบนสาย SDA จากนั้น DS1307 จะเริ่มส่งข้อมูลโดยเริ่มจากที่อยู่รีจิสเตอร์ที่ตัวชี้รีจิสเตอร์ชี้ไป หากตัวชี้การลงทะเบียนไม่ได้ถูกเขียนก่อนที่จะเริ่มโหมดการอ่าน ที่อยู่แรกที่อ่านจะเป็นที่อยู่สุดท้ายที่เหลืออยู่ในตัวชี้การลงทะเบียน DS1307 ควรได้รับการปฏิเสธ โนสค์เพื่ออ่านให้จบ

มาดูคุณสมบัติการทำงานกับ DS1307 โดยใช้ตัวอย่างนาฬิกาธรรมดาที่จะแสดงชั่วโมง นาที และวินาที ข้อมูลจะแสดงบนจอ LCD ขนาด 16x2 ปุ่มสองปุ่ม “ชั่วโมง+” และ “นาที+” จะช่วยให้คุณตั้งเวลาที่ต้องการได้ ไมโครคอนโทรลเลอร์ Atmega 8 ได้รับการโอเวอร์คล็อกจากออสซิลเลเตอร์ภายในด้วยความถี่ 1 MHz ดังนั้นอย่าลืมเปลี่ยนฟิวส์ ด้านล่างเป็นแผนภาพการเชื่อมต่อ

โปรแกรมควบคุมประกอบด้วยชุดฟังก์ชันสำหรับการทำงานกับบัส TWI, นาฬิกา DS1307 และจอ LCD

I2CInit - การเริ่มต้นบัส
I2CStart - ส่งเงื่อนไข START;
I2CStop - การส่งเงื่อนไข STOP;
I2CWriteByte - เขียนข้อมูล
I2CReadByte - อ่านข้อมูล
DS1307Read - ฟังก์ชั่นสำหรับอ่านข้อมูลจาก DS1307;
DS1307Write - ฟังก์ชั่นสำหรับเขียนข้อมูลไปยัง DS1307;
lcd_com - การส่งคำสั่งไปยัง LCD;
lcd_data - ถ่ายโอนข้อมูลไปยัง LCD;
lcd_string - ฟังก์ชั่นแสดงสตริงบนจอ LCD
lcd_num_to_str - ฟังก์ชั่นสำหรับส่งออกอักขระประเภท int;
lcd_init - การเริ่มต้น LCD

ด้านล่างเป็นรหัสโปรแกรม:

#รวม #รวม // ฟังก์ชั่นเริ่มต้นบัส TWI เป็นโมฆะ I2CInit(void) ( TWBR = 2; // การตั้งค่าความถี่บัส TWSR = (1<< TWPS1)|(1 << TWPS0); // Предделитель на 64 TWCR |= (1 << TWEN); // Включение модуля TWI } // Функция СТАРТ void I2CStart(void) { TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTA); // Передача условия СТАРТ while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT } // Функция СТОП void I2CStop(void) { TWCR = (1 << TWINT)|(1 << TWEN)|(1 << TWSTO); // Передача условия СТОП while(TWCR & (1 << TWSTO)); // Ожидание завершения передачи условия СТОП } // Функция записи данных по шине uint8_t I2CWriteByte(uint8_t data) { TWDR = data; // Загрузка данных в TWDR TWCR = (1 << TWEN)|(1 << TWINT); // Сброс флага TWINT для начала передачи данных while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT // Проверка статуса // Если адрес DS1307+R и принято "подтверждение"(0x18) // или адрес DS1307+W и принято "подтверждение"(0x40) // или передается байт данных и принято "подтверждение"(0x28) if((TWSR & 0xF8) == 0x18 || (TWSR & 0xF8) == 0x40 || (TWSR & 0xF8) == 0x28) return 1; // OK else return 0; // ОШИБКА } // Функция чтения данных по шине uint8_t I2CReadByte(uint8_t *data,uint8_t ack) { // Возвращаем "подтверждение" после приема if(ack) TWCR |= (1 << TWEA); // Возвращаем "неподтверждение" после приема // Ведомое устройство не получает больше данных // обычно используется для распознования последнего байта else TWCR &= ~(1 << TWEA); // Разрешение приема данных после сброса TWINT TWCR |= (1 << TWINT); while(!(TWCR & (1 << TWINT))); // Ожидание установки флага TWINT // Проверка статуса // Если принят байт данных и возвращается "подтверждение"(0x50) // или принят байт данных и возвращается "ненеподтверждение"(0x58) if((TWSR & 0xF8) == 0x50 || (TWSR & 0xF8) == 0x58) { *data = TWDR; // Читаем данные из TWDR return 1; // OK } else return 0; // ОШИБКА } // Функция чтения данных из DS1307 uint8_t DS1307Read(uint8_t address,uint8_t *data) { uint8_t res; I2CStart(); // СТАРТ res = I2CWriteByte(0b11010000); // адрес DS1307+W if(!res) return 0; // ОШИБКА // Передача адреса необходимого регистра res = I2CWriteByte(address); if(!res) return 0; // ОШИБКА I2CStart(); // Повторный СТАРТ res = I2CWriteByte(0b11010001); // адрес DS1307+R if(!res) return 0; // ОШИБКА // Чтение данных с "неподтверждением" res = I2CReadByte(data,0); if(!res) return 0; // ОШИБКА I2CStop(); // СТОП return 1; // OK } // Функция записи данных в DS1307 uint8_t DS1307Write(uint8_t address,uint8_t data) { uint8_t res; I2CStart(); // СТАРТ res = I2CWriteByte(0b11010000); // адрес DS1307+W if(!res) return 0; // ОШИБКА // Передача адреса необходимого регистра res = I2CWriteByte(address); if(!res) return 0; // ОШИБКА res = I2CWriteByte(data); // Запись данных if(!res) return 0; // ОШИБКА I2CStop(); // СТОП return 1; // OK } // Функции работы с LCD #define RS PD0 #define EN PD2 // Функция передачи команды void lcd_com(unsigned char p) { PORTD &= ~(1 << RS); // RS = 0 (запись команд) PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); } // Функция передачи данных void lcd_data(unsigned char p) { PORTD |= (1 << RS)|(1 << EN); // RS = 1 (запись данных), EN - 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p & 0xF0); // старший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); PORTD |= (1 << EN); // EN = 1 (начало записи команды в LCD) PORTD &= 0x0F; PORTD |= (p << 4); // младший нибл _delay_us(100); PORTD &= ~(1 << EN); // EN = 0 (конец записи команды в LCD) _delay_us(100); } // Функция вывода строки на LCD void lcd_string(unsigned char command, char *string) { lcd_com(0x0C); lcd_com(command); while(*string != "\0") { lcd_data(*string); string++; } } // Функция вывода переменной void lcd_num_to_str(unsigned int value, unsigned char nDigit) { switch(nDigit) { case 4: lcd_data((value/1000)+"0"); case 3: lcd_data(((value/100)%10)+"0"); case 2: lcd_data(((value/10)%10)+"0"); case 1: lcd_data((value%10)+"0"); } } // Функция инициализации LCD void lcd_init(void) { PORTD = 0x00; DDRD = 0xFF; _delay_ms(50); // Ожидание готовности ЖК-модуля // Конфигурирование четырехразрядного режима PORTD |= (1 << PD5); PORTD &= ~(1 << PD4); // Активизация четырехразрядного режима PORTD |= (1 << EN); PORTD &= ~(1 << EN); _delay_ms(5); lcd_com(0x28); // шина 4 бит, LCD - 2 строки lcd_com(0x08); // полное выключение дисплея lcd_com(0x01); // очистка дисплея _delay_us(100); lcd_com(0x06); // сдвиг курсора вправо lcd_com(0x0C); // включение дисплея, курсор не видим } int main(void) { _delay_ms(100); DDRC = 0x00; PORTC = 0xFF; lcd_init(); // Инициализация LCD I2CInit(); // Инициализация шины I2C lcd_string(0x81, "«acГ Ѕa DS1307"); // Часы на DS1307 lcd_string(0xC4, " : : "); // Запускаем ход часов uint8_t temp; DS1307Read(0x00,&temp); temp &= ~(1 << 7); // обнуляем 7 бит DS1307Write(0x00,temp); while(1) { unsigned char hour, minute, second, temp; // Читаем данные и преобразуем из BCD в двоичную систему DS1307Read(0x00,&temp); // Чтение регистра секунд second = (((temp & 0xF0) >> 4)*10)+(อุณหภูมิ & 0x0F); DS1307อ่าน(0x01,&อุณหภูมิ); // อ่านนาทีที่ลงทะเบียนนาที = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F); DS1307อ่าน(0x02,&อุณหภูมิ); // อ่านชั่วโมงการลงทะเบียนนาฬิกา = (((temp & 0xF0) >> 4)*10)+(temp & 0x0F); จอแอลซีดีคอม(0xC4); lcd_num_to_str(ชั่วโมง, 2); // แสดงนาฬิกา lcd_com(0xC7); lcd_num_to_str(นาที, 2); // แสดงนาที lcd_com(0xCA); lcd_num_to_str(วินาที, 2); // แสดงวินาทีถ้า ((PINC & (1<< PC0)) == 0) // Если нажата кнопка { while((PINC & (1 << PC0)) == 0){} // Ждем отпускания кнопки hour++; // Увеличиваем часы на 1 if(hour >23) ชั่วโมง = 0; // แปลงจากไบนารี่เป็น BCD และเขียนเป็น DS1307 uint8_t temp; อุณหภูมิ = ((ชั่วโมง/10)<< 4)|(hour%10); DS1307Write(0x02, temp); _delay_ms(100); } if((PINC & (1 << PC1)) == 0) // Если нажата кнопка { while((PINC & (1 << PC1)) == 0){} // Ждем отпускания кнопки minute++; // Увеличиваем минуты на 1 if(minute >59) นาที = 0; // แปลงจากไบนารี่เป็น BCD และเขียนเป็น DS1307 uint8_t temp; อุณหภูมิ = ((นาที/10)<< 4)|(minute%10); DS1307Write(0x01, temp); _delay_ms(100); } } }

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

อัปเดต 10/17/2558
ตอนแรกมันเป็นชุดบทความโดยมีวัตถุประสงค์เพื่อพูดคุยเกี่ยวกับการสร้างอุปกรณ์ตั้งแต่เริ่มต้นจนถึงสถานะสำเร็จรูป แต่ทันใดนั้นฉันก็แพ้สิ่งที่เรียกว่า "นาฬิกา" ดังนั้นฉันจึงรวมทุกอย่างไว้ในบทความเดียว เครื่องสมบูรณ์ 99.9% (เหลือแค่ขันน็อตให้แน่น) แต่ก็ทำไม่ยาก :) พอหายภูมิแพ้ก็จะมีภาพสุดท้ายมาครับ

เริ่มจากข้อเท็จจริงที่ว่าจนถึงตอนนี้เราไม่รู้อะไรเลยเกี่ยวกับ ds1307 ยกเว้นว่านาฬิกานั้นผลิตขึ้นโดยใช้ความช่วยเหลือ ดังนั้นให้ดาวน์โหลดเอกสารสำหรับไมโครวงจรนี้และอ่านรายการ "สารพัด" ที่มี ดังนั้นจากย่อหน้าแรกโดยทั่วไปจะชัดเจนว่าใช้พลังงานต่ำ ข้อมูลจะถูกส่งผ่าน I2C คุณสามารถค้นหาวันที่และเวลา รูปแบบ 12 และ 24 ชั่วโมง การปรับวันที่อัตโนมัติ แต่สิ่งที่น่าสนใจที่สุดคือวงจร (TYPICAL OPERATING CIRCUIT)

เราสูบบุหรี่ในเอกสารข้อมูลและพยายามค้นหาว่าอะไรคืออะไร เราไปจากซ้ายไปขวา CPU - ไมโครคอนโทรลเลอร์ (นั่นคือ atmega ของเรา) ตัวต้านทานสองตัวมันบอกว่าดึงขึ้น - นั่นหมายถึงดึงขึ้น (คุณสามารถใช้แต่ละตัวได้ 10k) ควอตซ์ที่ 32768 Hz ไมโครวงจรเองและแบตเตอรี่ เอาต์พุต SQW/OUT สามารถกระโดดด้วยความถี่ 1Hz, 4kHz, 8kHz, 32kHz ตราบใดที่เราไม่สนใจสิ่งนี้ บางทีข้อมูลนี้อาจเพียงพอแล้วในตอนนี้ ฉันต้องการเขียนโค้ดบางอย่าง :)

เราสร้างโปรเจ็กต์ใน CodeVision ค้นหา ds1307 ในส่วน I2C และรวมไว้ในโปรเจ็กต์ คงจะดีถ้าแสดงข้อมูลที่ไหนสักแห่ง เช่น บนจอ LCD และปุ่มสองสามปุ่มก็ไม่เสียหาย

สิ่งที่คุณต้องมีคือกำหนดค่า LCD สำหรับพอร์ต D และปุ่มดึงขึ้นสามปุ่มสำหรับอินพุต ต่อไป เราต้องแสดงเวลาบนจอ LCD เพื่อที่จะทำเช่นนี้ มาดูคู่มือ CodeVision และยกตัวอย่างจากตรงนั้น ปรากฎว่าทุกอย่างง่าย - มีฟังก์ชั่นที่ตั้งเวลา:
rtc_set_time(3,0,0); //ตั้ง 03:00:00

เหล่านั้น. หลังจากเรียกใช้ฟังก์ชันนี้ ตัวแปร h, m, s จะมีชั่วโมง (h) นาที (m) และวินาที (s) สิ่งที่เหลืออยู่ก็คือการแสดงมันบนหน้าจอ นี่คือสิ่งที่เรารู้วิธีการทำ)
รหัสสุดท้ายจะมีลักษณะดังนี้:

#รวม #รวม #รวม #รวม // ฟังก์ชั่นโมดูล LCD ตัวอักษรและตัวเลข#asm .equ __lcd_port= 0x12 ; PORTD #endasm #รวม ถ่าน lcd_buf[33] ; เป็นโมฆะหลัก (โมฆะ) (ถ่านชั่วโมง, นาที, sek; PORTC= 0x07 ; DDRC= 0x00 ; // การเริ่มต้นบัส I2C i2c_init() ; rtc_init(0 , 0 , 0 ) ; // การเริ่มต้นโมดูล LCD lcd_init(16 ) ; rtc_set_time (3 , 0 , 0 ) ; ในขณะที่ (1 ) ( rtc_get_time(& ชั่วโมง,& นาที,& sek) ; lcd_clear() ; lcd_gotoxy(0 , 0 ) ; sprintf (lcd_buf, "%2d:%02d:%02d \n", ชั่วโมง, นาที, เสก) ; lcd_puts(lcd_buf) ; ดีเลย์_ms(500 ) ; -

- #รวม #รวม #รวม // ฟังก์ชั่นโมดูล LCD ตัวอักษรและตัวเลข #asm .equ __lcd_port=0x12 ;PORTD #endasm #include

ถ่าน lcd_buf; เป็นโมฆะหลัก (โมฆะ) (ถ่านชั่วโมง, นาที, sek; PORTC = 0x07; DDRC = 0x00; // การเริ่มต้นบัส I2C i2c_init (); // DS1307 การเริ่มต้นนาฬิกาเวลาจริง rtc_init (0,0,0); // โมดูล LCD การเริ่มต้น lcd_init(16); rtc_set_time(3,0,0); ในขณะที่ (1) ( rtc_get_time(&ชั่วโมง,&นาที,&sek); lcd_clear(); lcd_gotoxy(0,0); sprintf(lcd_buf,"%2d:%02d :%02d\n",ชั่วโมง,นาที,วินาที); lcd_puts(lcd_buf); Delay_ms(500); ); )

เราประกอบและทดสอบใน Proteus:

เราจะทำการอัพเกรดเฟิร์มแวร์ของเราต่อไป เริ่มจากแนวคิดต่อไปนี้: DS1307 มีเอาต์พุต SQW/OUT ที่สามารถสร้างความถี่ได้หลายความถี่ หากคุณตั้งค่าเอาต์พุตนี้เป็น 1Hz และใช้สัญญาณนี้กับอินพุตอินเทอร์รัปต์ภายนอก ปรากฎว่า 1307 จะดึง "ส่วนท้าย" ของ atmega8 ของเราทุกๆ วินาที สำหรับเมก้านี้จะเป็นสัญญาณว่าถึงเวลาที่ต้องอัพเดตเวลาแล้ว สิ่งนี้จะช่วยให้คุณไม่ต้องโหลดไมโครคอนโทรลเลอร์ด้วยการอัพเดตเวลาอย่างต่อเนื่อง ข้อมูลเกี่ยวกับเวลาปัจจุบันจะได้รับการอัปเดตอย่างแน่นอนหนึ่งครั้งต่อวินาที

มาเพิ่มการขัดจังหวะระดับต่ำภายนอกให้กับโปรเจ็กต์บนพิน Int1 แล้วเปิดการดึงขึ้น มาตั้งค่าเอาต์พุต DS1307 ให้เป็นความถี่ 1Hz อย่างไรก็ตามการอ่านคู่มือมีประโยชน์ฉันพบคุณสมบัติที่น่าสนใจ - ตัวต้านทานแบบดึงขึ้นที่ขา SCL และ SDA ควรเป็น 3.3k - 4.7k ลองพิจารณาเรื่องนี้ดู

รหัสผลลัพธ์จะมีลักษณะดังนี้:

ขัดจังหวะ [ EXT_INT1] เป็นโมฆะ ext_int1_isr (โมฆะ ) ( time_flag= 1 ; )

ขัดจังหวะเป็นโมฆะ ext_int1_isr (เป็นโมฆะ) ( time_flag=1; )

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

if (time_flag== 1 ) ( rtc_get_time(& ชั่วโมง,& นาที,& sek) ; lcd_gotoxy(0 , 0 ) ; sprintf (lcd_buf, "%02d:%02d:%02d \n", ชั่วโมง, นาที, เสก) ; lcd_puts(lcd_buf) ; -

if(time_flag==1) ( rtc_get_time(&ชั่วโมง&นาที&sek); lcd_gotoxy(0,0); sprintf(lcd_buf,"%02d:%02d:%02d\n",ชั่วโมง,นาที,sek); lcd_puts( จอแอลซีดี_buf)

ตอนนี้เรามาดูคำถามถัดไป: การใช้ sprintf มีประสิทธิภาพเพียงใด? เพื่อไม่ให้เริ่มการสนทนาที่ว่างเปล่า ฉันจะให้โค้ด 2 ชิ้นที่ทำสิ่งเดียวกัน - แสดงข้อมูลเวลาบนหน้าจอ

ตัวเลือกแรกที่เรารู้จักแล้ว:

วิ่ง (lcd_buf, "%02d:%02d:%02d \n", ชั่วโมง, นาที, เสก) ; lcd_puts(lcd_buf) ;

sprintf(lcd_buf,"%02d:%02d:%02d\n",ชั่วโมง,นาที,วินาที); lcd_puts(lcd_buf);

เห็นด้วย ใช้งานง่ายและชัดเจน ตอนนี้ตัวเลือกหมายเลข 2:

lcd_putchar(ชั่วโมง/ 10 + 0x30 ) ; lcd_putchar(ชั่วโมง% 10 + 0x30 ) ; lcd_putchar(/// ) ; lcd_putchar(นาที/ 10 + 0x30 ) ; lcd_putchar(ขั้นต่ำ% 10 + 0x30 ) ; lcd_putchar(/// ) ; lcd_putchar(sek/ 10 + 0x30 ) ; lcd_putchar(sek% 10 + 0x30 ) ;

lcd_putchar(ชั่วโมง/10+0x30); lcd_putchar(ชั่วโมง%10+0x30); lcd_putchar(///); lcd_putchar(นาที/10+0x30); lcd_putchar(ขั้นต่ำ%10+0x30); lcd_putchar(///); lcd_putchar(วินาที/10+0x30); lcd_putchar(วินาที%10+0x30);

มันไม่ชัดเจนมาก แต่คุณสามารถเข้าใจได้ เราจะเปรียบเทียบพวกเขาอย่างไร? สิ่งนี้ทำได้ง่ายมาก - เปิดตัวดีบักเกอร์ AVR STUDIO และดูจำนวนรอบสัญญาณนาฬิกาที่ใช้ในการดำเนินการ ดังนั้น ดรัมโรล ผลลัพธ์... โค้ดชิ้นแรกวิ่งไปที่ 16,466 รอบนาฬิกา ซึ่งเทียบเท่ากับ 2,058.25 μs ที่ความถี่ในการทำงาน 8 MHz สำหรับโค้ดชิ้นที่สอง ตัวเลขนี้คือ 12,278 รอบนาฬิกา หรือ 1,534.75 ไมโครวินาที เห็นด้วยการลดเวลาดำเนินการและลดไมโครคอนโทรลเลอร์ลงประมาณ 25% จึงเป็นเหตุผลที่ดีพอที่จะไม่ใช้ sprintf เราละทิ้ง sprintf ออกจากโปรเจ็กต์ของเรา ตามด้วย stdio.h และ lcd_buf

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

ในขณะที่ (1) ( ถ้า (time_flag== 1) ( show_time() ; //แสดงข้อมูลเกี่ยวกับเวลาปัจจุบัน } } ;

ในขณะที่ (1) ( if(time_flag==1) ( show_time(); //แสดงข้อมูลเกี่ยวกับเวลาปัจจุบัน) );

การประกาศฟังก์ชันจะมีลักษณะดังนี้:

ถือเป็นโมฆะ show_time() ( rtc_get_time(& ชั่วโมง,& นาที,& sek) ; lcd_gotoxy(0 , 0 ) ; lcd_putchar(ชั่วโมง/ 10 + 0x30 ) ; lcd_putchar(ชั่วโมง% 10 + 0x30 ) ; lcd_putchar(:) ) ; lcd_putchar (ต่ำสุด/ 10 + 0x30 ) ; lcd_putchar(///) ; lcd_putchar(sek/ 10 + 0x30 ) ;

เป็นโมฆะ show_time() ( rtc_get_time(&ชั่วโมง,&นาที,&sek); lcd_gotoxy(0,0); lcd_putchar(ชั่วโมง/10+0x30); lcd_putchar(ชั่วโมง%10+0x30); lcd_putchar(″); lcd_putchar(min/ 10+0x30); lcd_putchar(ขั้นต่ำ%10+0x30); lcd_putchar(วินาที/10+0x30);

ตอนนี้เราต้องเพิ่มเอาต์พุตวันที่ให้กับเฟิร์มแวร์ของเรา วันที่ถูกตั้งค่าโดยใช้ฟังก์ชันต่อไปนี้:

rtc_set_date(6,13,10,13); //6 - วันในสัปดาห์, 13 - วัน, 10 - เดือน, 13 - ปี

rtc_get_date(&week_day,&วัน,&เดือน,&ปี); //วันในสัปดาห์ วัน เดือน ปี

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

#รวม // ฟังก์ชั่นบัส I2C #asm .equ __i2c_port= 0x18 ; PORTB .equ __sda_bit= 0 .equ __scl_bit= 1 #endasm #include // DS1307 ฟังก์ชั่นนาฬิกาเวลาจริง#รวม // ฟังก์ชั่น LCD ตัวอักษรและตัวเลข #include ถ่าน ชั่วโมง= 0 , นาที= 0 , sek= 0 , วัน= 0 , เดือน= 0 , ปี= 0 , week_day= 0 ; บิต time_flag= 0 ; เมนูถ่าน= 0 ; // รูทีนบริการขัดจังหวะภายนอก 1ขัดจังหวะ [ EXT_INT1] เป็นโมฆะ ext_int1_isr(โมฆะ) ( time_flag= 1 ; ) โมฆะ show_time() ( rtc_get_time(& ชั่วโมง,& นาที,& sek) ; rtc_get_date(& week_day,& วัน,& เดือน,& ปี) ; lcd_gotoxy(0 , 0 ) ; lcd_putchar(ชั่วโมง/ 10 + 0x30 ) ; lcd_putchar(# ) ; lcd_putchar(ขั้นต่ำ% 10 + 0x30 ) ; lcd_gotoxy(0 , 1 ) ; lcd_putchar(เดือน/ 10 + 0x30 ) ; lcd_putchar(เดือน% 10 + 0x30 ) ; lcd_putchar("/" ) ; lcd_putchar(ปี/ 10 + 0x30 ) ; lcd_putchar(ปี% 10 + 0x30 ) ; time_flag= 0 ; = 0x00 ; // การเริ่มต้น I2C Bus i2c_init() ; // DS1307 การเริ่มต้นนาฬิกาเวลาจริง // เอาต์พุตคลื่นสี่เหลี่ยมบนพิน SQW/OUT: เปิด// ความถี่คลื่นสี่เหลี่ยม: 1Hz rtc_init(0, 1, 0) ; // การเริ่มต้นการขัดจังหวะภายนอก// INT0: ปิด // INT1: เปิด // INT1 โหมด: GICR ระดับต่ำ|= 0x80 ; MCUCR= 0x00 ; GIFR= 0x80 ; // การเริ่มต้นโมดูล LCD lcd_init (16) ; rtc_set_time(12, 0, 0); rtc_set_date(6, 13, 10, 13); #asm("sei") ในขณะที่ (1 ) ( ถ้า (time_flag== 1 ) ( show_time() ; ) ) ; -

- // ฟังก์ชันบัส I2C #asm .equ __i2c_port=0x18 ;PORTB .equ __sda_bit=0 .equ __scl_bit=1 #endasm #include // DS1307 ฟังก์ชั่นนาฬิกาเวลาจริง #include // ฟังก์ชั่น LCD ตัวอักษรและตัวเลข #include ถ่าน ชั่วโมง=0,นาที=0,เสก=0,วัน=0,เดือน=0,ปี=0,week_day=0; บิต time_flag=0; เมนูถ่าน=0; // การขัดจังหวะภายนอก 1 รูทีนบริการขัดจังหวะ void ext_int1_isr(void) ( time_flag=1; ) void show_time() ( rtc_get_time(&hour,&min,&sek); rtc_get_date(&week_day,&day,&month,&year); lcd_gotoxy(0,0) ; lcd_putchar(ชั่วโมง/10+0x30); lcd_putchar("/") ; lcd_putchar("/"); lcd_putchar (ปี% 10+0x30); main (โมฆะ) ( PORTC=0x0F; DDRC=0x00; PORTD=0x08; DDRD=0x00; // การเริ่มต้น I2C Bus i2c_init(); // DS1307 การเริ่มต้นนาฬิกาเรียลไทม์ // เอาต์พุตคลื่นสี่เหลี่ยมบนพิน SQW/OUT: เปิด / / ความถี่คลื่นสี่เหลี่ยม: 1Hz rtc_init(0,1,0); // การเริ่มต้นการขัดจังหวะภายนอก // INT0: ปิด // INT1: เปิด // โหมด INT1: GICR ระดับต่ำ|=0x80; =0x80; // การเริ่มต้นโมดูล LCD lcd_init (16); rtc_set_time(12,0,0); rtc_set_date(6,13,10,13); #asm("sei") ในขณะที่ (1) ( if(time_flag==1) ( show_time(); ) ); -

ผลลัพธ์:

วงจรและเฟิร์มแวร์:

มาดูการจัดเมนูกันดีกว่า คำถามที่สำคัญที่สุดคือทุกอย่างควรมีลักษณะอย่างไร เช่น จำเป็นต้องกำหนดข้อกำหนดทางเทคนิค (t.z.)
ฉันต้องการให้สิ่งเหล่านี้เป็นหน้าจอแยกกัน:
-หน้าจอหลัก;
-หน้าจอตั้งเวลา;
-หน้าจอการตั้งค่าวันที่;
- หน้าจอการตั้งค่านาฬิกาปลุก

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

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

ในขณะที่ (1) ( สวิตช์ (เมนู) ( case 0 : show_time(); break ; case 1 : set_time() ; break ; case 2 : set_date() ; break ; case 3 : set_alarm() ; break ; ) ) ;

ในขณะที่ (1) ( สวิตช์(เมนู) ( กรณีที่ 0: show_time(); แตก; กรณีที่ 1: set_time(); แตก; กรณีที่ 2: set_date(); แตก; กรณีที่ 3: set_alarm(); แตก; ) );

ขั้นตอนต่อไปคือการกำหนดฟังก์ชันเหล่านี้ ในตอนแรกฉันวาดชื่อคงที่ เช่น lcd_puts("Set time"); ฟังก์ชั่นกลายเป็นเช่นนี้

เป็นโมฆะ set_alarm () ( ///////// ดูการตั้งค่าการเตือน lcd_gotoxy (0,0); lcd_puts ("ตั้งค่าการเตือน"); ) เป็นโมฆะ set_time () ( //////// ดูการตั้งค่าเวลา lcd_gotoxy ( 0,0); lcd_puts("ตั้งเวลา");

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

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

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

เป็นโมฆะ set_alarm() // ฟังก์ชั่นการประมวลผลสัญญาณเตือน ( // โหมดการแสดงผลของเมนูการตั้งค่าการเตือน if(sub_alarm==0) ( if(PINC.0==0) // ปุ่มขึ้น - เปลี่ยนหน้าจอเมนู ( เมนู=0; ... .. ) ) //เมนูย่อยสำหรับการตั้งค่าการเตือน if(sub_alarm==1) ( if(PINC.0==0) // ปุ่มขึ้น - เพิ่มค่า ( a_hour++; .... ) )

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

if(PINC.0==0) // ปุ่มขึ้น ( if(subProgram==1) //subProgram=1 - เปลี่ยนนาฬิกา ( a_hour++; ... ) if(subProgram==2) //subProgram=2 - เปลี่ยนนาที ( a_min++; ... ) if(subProgram==3) //subProgram=3 เปลี่ยนการตั้งค่าสถานะการเตือน ( ... ) )

สิ่งเดียวที่ควรกล่าวถึงคือสัญลักษณ์พิเศษที่แสดงบนหน้าจอหลักเมื่อเปิดนาฬิกาปลุก

ตัวอย่างนี้นำมาจากตัวอย่างในโฟลเดอร์ถ่าน CodeVision\examples\lcd

typedef ถ่านไบต์ที่ไม่ได้ลงนาม; //กำหนดประเภทใหม่แฟลชไบต์ char_table[ 8 ] = ( //วาดสัญลักษณ์ของคุณ 0b10000000, 0b10000100, 0b10001110, 0b10001110, 0b10001110, 0b10011111, 0b10100100, 0b11000000); // ฟังก์ชันที่ใช้กำหนดอักขระของผู้ใช้เป็นโมฆะกำหนด_char (ไบต์แฟลช * pc, ไบต์ char_code) ( ไบต์ i, ที่อยู่; ที่อยู่ = (char_code<< 3 ) | 0x40 ; for (i= 0 ; i< 8 ; i++ ) lcd_write_byte(address++,* pc++ ) ; } void main(void ) { byte i, address; lcd_init(16 ) ; define_char(char_table, 0 ) ; //โหลดสัญลักษณ์ลงใน LSDในขณะที่ (1) ( lcd_putchar(0) ; //แสดงสัญลักษณ์ }

typedef ถ่านไบต์ที่ไม่ได้ลงนาม; // กำหนดประเภทแฟลชใหม่ char_table=( // วาดตัวละครของคุณ 0b10000000, 0b10000100, 0b10001110, 0b10001110, 0b10001110, 0b10011111, 0b10100100, 0b11000000); // ฟังก์ชั่นที่ใช้ในการกำหนดอักขระผู้ใช้ void Define_char(byte flash *pc,byte char_code) ( byte i,address; address=(char_code<<3)|0x40; for (i=0; i<8; i++) lcd_write_byte(address++,*pc++); } void main(void) { byte i,address; lcd_init(16); define_char(char_table,0); //Грузим символ в лсд while(1) { lcd_putchar(0); //выводим символ на дисплей }

คุณสามารถวาดสัญลักษณ์ขนาด 5x7 ได้ สัญลักษณ์หนึ่งหมายถึงพิกเซลเต็มแล้ว ศูนย์หมายถึงไม่ได้เติมเข้าไป ผลที่ได้คือสัญลักษณ์ระฆัง

เฟิร์มแวร์

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

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

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

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

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

ลักษณะเฉพาะ:

  • การใช้พลังงานต่ำมาก ผู้ผลิตรับประกันการใช้งานนาฬิกาเป็นเวลา 10 ปีโดยใช้แบตเตอรี่มาตรฐานหนึ่งก้อน CR2032
  • หน่วยความจำ 56 ไบต์สำหรับจัดเก็บข้อมูลผู้ใช้ ฉันคิดว่านี่ไม่ใช่ตัวเลือกที่จำเป็นอย่างยิ่ง แต่อาจเป็นประโยชน์กับใครบางคน
  • เอาต์พุตที่ตั้งโปรแกรมได้สำหรับการตอกบัตรอุปกรณ์ภายนอก สามารถส่งสัญญาณออกได้ 1 Hz, 4.096 kHz, 8.192 kHz และ 32.768 kHz
  • โหมด 24 ชั่วโมง และ 12 ชั่วโมง

พินเอาท์

หมุดนาฬิกามีดังต่อไปนี้:

X1, X2— หมุดสำหรับเชื่อมต่อเครื่องสะท้อนควอทซ์ที่ความถี่ 32.768 kHz
วทท— เอาต์พุตสำหรับเชื่อมต่อแบตเตอรี่สำรองขนาด 3 โวลต์
จีเอ็นดี- โลก
เอส.ดี.เอ.- สายข้อมูลบัส i2c
เอสซีแอล- สายนาฬิกาบัส i2c
ตร.ว./ออก– สัญญาณเอาท์พุตสำหรับการตอกบัตรอุปกรณ์ภายนอก
วีซีซี- แหล่งจ่ายไฟ 5 โวลต์

การเชื่อมต่อกับคอนโทรลเลอร์
ความผูกพันมีน้อย คุณจะต้องใช้ควอตซ์ 32.768 kHz ตัวต้านทาน 1 ตัวเพื่อใช้งานบัส i2c และแบตเตอรี่ 3 โวลต์

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

อย่างไรก็ตามมันสามารถทำงานได้โดยไม่ต้องใช้ควอตซ์ ในการดำเนินการนี้ สัญญาณนาฬิกาภายนอกที่มีความถี่ 32.768 kHz จะถูกส่งไปยังขา X1 และ X2 ยังคงลอยอยู่ในอากาศ

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

ตัวเลขทั้งหมดในหน่วยความจำจะถูกจัดเก็บในรูปแบบทศนิยมไบนารี ซึ่งหมายความว่าสามารถจัดเก็บตัวเลขสองหลักในหนึ่งไบต์ได้ ตัวอย่างเช่น หมายเลข 0x23 ประกอบด้วยหมายเลข 2 และหมายเลข 3 สำหรับแต่ละหมายเลข จะมีการจัดสรร 4 บิต เหตุใดจึงทำเช่นนี้? เพื่อความสะดวกและประหยัดหน่วยความจำ นอกเหนือจากเวลาและวันที่แล้ว การตั้งค่าหลายบิตยังถูกจัดเก็บไว้ในหน่วยความจำ:

  • นาฬิกาหยุด- ควบคุมนาฬิกา เมื่อบิตถูกตั้งค่า นาฬิกาจะหยุดเดิน ในการเริ่มนาฬิกาคุณต้องเขียน 0 ไปที่บิตนี้ หลังจากเชื่อมต่อแบตเตอรี่สำรองแล้ว บิตนี้จะถูกตั้งค่าและนาฬิกาจะไม่นับเวลา! คุณต้องจำสิ่งนี้
  • 24/12 - บิตนี้สำหรับเลือกโหมดนาฬิกา เมื่อบิตนี้เท่ากับหนึ่ง ระบบจะใช้โหมด 12 ชั่วโมง มิฉะนั้น 24 ชม. หากใช้โหมด 12 ชั่วโมง บิตที่ 5 จะระบุ AM หรือ PM ทันที ถ้าบิตเป็น 1 แสดงว่า PM ในโหมด 24 ชั่วโมง บิตนี้ใช้เพื่อจัดเก็บเวลาหลายสิบชั่วโมงร่วมกับบิต 4
  • เอาท์พุต— ควบคุมสถานะของขา SQW/OUT บิตถูกตั้งค่า - บันทึกอยู่ที่ขา 1 รีเซ็ต - ที่ขา 0 เพื่อควบคุมด้วยวิธีนี้บิต ตารางจะต้องรีเซ็ต
  • ตาราง- เมื่อตั้งค่าบิตแล้ว พัลส์สี่เหลี่ยมจะปรากฏบนขา SQW/OUT
  • RS1, RS0— บิตเหล่านี้จะตั้งค่าความถี่พัลส์ การขึ้นต่อกันของความถี่ของชุดบิตอยู่ในตารางด้านล่าง:

ซอฟต์แวร์

ในการทำงานกับนาฬิกา DS1307 ได้มีการเขียนไลบรารีอย่างง่ายที่มีฟังก์ชันพื้นฐานดังต่อไปนี้:

DS_start— เริ่มนาฬิกา คุณยังสามารถเริ่มนาฬิกาได้ด้วยการตั้งเวลา
ดีเอส_สต็อป- หยุดนาฬิกา
DS_set_time —การตั้งเวลา ก่อนที่จะเรียกโพรซีเดอร์ คุณต้องใส่วินาทีใน tmp1 นาทีใน tmp2 และชั่วโมงใน tmp3 นาฬิกาในรูปแบบ 24 ชั่วโมง
DS_get_time: —อ่านเวลาจากนาฬิกา วินาทีจะถูกบันทึกเป็น tmp1 นาทีเป็น tmp2 ชั่วโมงเป็น tmp3
DS_get_date:— อ่านวันที่จากนาฬิกา วันจะถูกบันทึกเป็น tmp1 เดือนเป็น tmp2 ปีเป็น tmp3
DS_set_date: —การตั้งวันที่ ก่อนที่จะเรียกขั้นตอนนี้ คุณต้องใส่วันใน tmp1, เดือนใน tmp2 และปีใน tmp3 (ตัวเลข 2 หลักสุดท้าย)

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

โปรแกรมทดสอบช่วยให้คุณควบคุมนาฬิกาผ่าน UART (ความเร็ว 9600 คอนโทรลเลอร์ทำงานที่ 8 MHz) เมื่อเริ่มต้น เวลา วันที่ และข้อความแจ้งให้ป้อนคำสั่งตั้งแต่ 1 ถึง 3 จะปรากฏขึ้นทันที เมื่อคุณเลือกตัวเลือก 1 เวลา/วันที่จะถูกอ่านอีกครั้ง ตัวเลือกที่ 2 ให้คุณตั้งเวลา และตัวเลือกที่ 3 วันที่ หากคุณต้องการลองเล่นกับนาฬิกา ไฟล์จำลองจะรวมอยู่ในไฟล์เก็บถาวรต้นทาง

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

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

DS1307 เป็นโมดูลขนาดเล็กที่ออกแบบมาเพื่อการนับเวลา ประกอบขึ้นโดยใช้ชิป DS1307ZN และใช้พลังงานจากแบตเตอรี่ลิเธียม (LIR2032) ซึ่งช่วยให้ทำงานอัตโนมัติได้เป็นเวลานาน นอกจากนี้ในโมดูลยังมีหน่วยความจำ EEPROM แบบไม่ลบเลือนขนาด 32 KB (AT24C32) ไมโครวงจร AT24C32 และ DS1307ZN เชื่อมต่อกันด้วยบัสทั่วไปโดยใช้อินเทอร์เฟซ I2C

ข้อกำหนดทางเทคนิค

แรงดันไฟฟ้า: 5V
อุณหภูมิในการทำงาน: – 40°C … + 85°C
หน่วยความจำ: 56 ไบต์ (ไม่ลบเลือน)
แบตเตอรี่ : LIR2032 (การตรวจจับแหล่งพลังงานอัตโนมัติ)
อินเทอร์เฟซ: I2C
ขนาด: 28มม.x 25มม.x 8มม

ข้อมูลทั่วไป

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

การแลกเปลี่ยนข้อมูลกับอุปกรณ์อื่นดำเนินการผ่านอินเทอร์เฟซ I2C จากพิน SCL และ SDA จำเป็นต้องใช้ตัวเก็บประจุ C1 และ C2 เพื่อลดเสียงรบกวนตามแนวสายไฟ เพื่อให้แน่ใจว่าสัญญาณ SCL และ SDA อยู่ในระดับที่เหมาะสม จึงมีการติดตั้งตัวต้านทาน R2 และ R3 (ดึงขึ้นไปที่แหล่งจ่ายไฟ) ในการตรวจสอบการทำงานของโมดูล สัญญาณ SQ รูปทรงสี่เหลี่ยมที่มีความถี่ 1 Hz จะถูกส่งไปยังพิน 7 ของชิป DS1307Z จำเป็นต้องใช้องค์ประกอบ R4, R5, R6, VD1 เพื่อชาร์จแบตเตอรี่ลิเธียม นอกจากนี้บอร์ดยังมีที่นั่ง (U1) สำหรับติดตั้งเซ็นเซอร์อุณหภูมิ DS18B20 (หากจำเป็นคุณสามารถบัดกรีเข้าไปได้) คุณสามารถอ่านค่าที่อ่านได้จากพิน DS ซึ่งเชื่อมต่อกับแหล่งจ่ายไฟผ่านตัวต้านทาน R1 ด้วย ความต้านทาน 3.3 kOhm แผนภาพวงจรและวัตถุประสงค์ของหน้าสัมผัสสามารถดูได้จากภาพด้านล่าง

บนบอร์ดมีหน้าสัมผัสสองกลุ่มโดยมีระยะห่าง 2.54 มม. ฉันจะใช้ขั้วต่อแบบพินเพื่อความสะดวกในการเชื่อมต่อกับเขียงหั่นขนมซึ่งจะต้องบัดกรี

ผู้ติดต่อกลุ่มแรก:
DS: เอาต์พุต DS18B20 (1 สาย)


VCC: แหล่งจ่ายไฟโมดูล "+"
GND: แหล่งจ่ายไฟโมดูล "-"

ผู้ติดต่อกลุ่มที่สอง:
ตาราง: อินพุต 1 MHz
DS: เอาต์พุต DS18B20 (1 สาย)
SCL: นาฬิกาอนุกรม
SDA: สายข้อมูล (Serial Dфta)
VCC: แหล่งจ่ายไฟโมดูล "+"
GND: "-" แหล่งจ่ายไฟโมดูล
ค้างคาว:

การชาร์จแบตเตอรี่
ตามที่อธิบายไว้ โมดูลของคุณสามารถชาร์จแบตเตอรี่ได้ ซึ่งใช้งานโดยใช้ส่วนประกอบ R4, R5, R6 และไดโอด D1 แต่วงจรนี้มีข้อเสียเปรียบ: แบตเตอรี่จะคายประจุผ่านตัวต้านทาน R4 และ R6 (ตามที่ผู้ใช้ ALEXEY ระบุไว้ไม่มากนัก) เนื่องจากโมดูลใช้กระแสไฟเพียงเล็กน้อย คุณจึงสามารถถอดวงจรไฟฟ้าออกได้ โดยถอด R4, R5, R6 และ VD1 ออก แทนที่ R6 ด้วยจัมเปอร์ (หลังจากถอดส่วนประกอบออกแล้ว คุณสามารถใช้แบตเตอรี่ CR2032 ทั่วไปได้)

การเชื่อมต่อ DS1307 กับ Arduino

ชิ้นส่วนที่จำเป็น:
Arduino UNO R3 x 1 ชิ้น
ลวดดูปองท์ 2.54 มม. 20 ซม. x 1 ชิ้น
สาย USB 2.0 A-B x 1 ชิ้น
นาฬิกาเรียลไทม์ RTC DS1307 x 1 ชิ้น

การเชื่อมต่อ:
หากต้องการเชื่อมต่อนาฬิกาเรียลไทม์ DS1307 คุณจะต้องบัดกรีขั้วต่อพินเข้ากับพินกลุ่มแรก ต่อไปเราเชื่อมต่อสายไฟ SCL (DS1307) กับพิน 4 (Arduino UNO) และ SDA (DS1307) กับพิน 5 (Arduino UNO) สิ่งที่เหลืออยู่คือเชื่อมต่อ VCC กับ +5V และ GND กับ GND อย่างไรก็ตาม เอาต์พุตอินเทอร์เฟซ I2C จะแตกต่างกันในบอร์ด Arduino ที่แตกต่างกัน สามารถดูวัตถุประสงค์ของแต่ละรายการได้ด้านล่าง

ตั้งเวลา DS1307
ก่อนอื่นคุณต้องดาวน์โหลดและติดตั้งไลบรารี่ "DS1307RTC" และ "TimeLib" ในสภาพแวดล้อมการพัฒนา Arduino IDE จากนั้นคุณจะต้องตั้งเวลาเปิดตัวอย่างจากไลบรารี DS1307RTC "ไฟล์" -> "ตัวอย่าง" - > “DS1307RTC” -> “SetTime” หรือคัดลอกโค้ดด้านล่าง

// เชื่อมต่อไลบรารี DS1307RTC const char *monthName = ( "ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พฤษภาคม", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค. " , "พ.ย.", "ธ.ค." ); tmElements_t tm; การตั้งค่าเป็นโมฆะ() ( bool parse=false; bool config=false; // รับวันที่และเวลาที่คอมไพเลอร์ถูกรันถ้า (getDate(__DATE__) && getTime(__TIME__)) ( parse = true; // และกำหนดค่า RTC ด้วย ข้อมูลนี้ if (RTC.write(tm)) ( config = true; ) ) Serial.begin(9600); while (!Serial) ; // รอการหน่วงเวลา Arduino Serial Monitor (200); Time="); Serial.print(__TIME__); Serial.print(", Date="); Serial.println(__DATE__); else if (แยกวิเคราะห์) ( Serial.println("DS1307 Communication Error:-("); Serial.println("โปรดตรวจสอบวงจรของคุณ"); ) else ( Serial.print("ไม่สามารถแยกวิเคราะห์ข้อมูลจากคอมไพเลอร์, Time=\""); Serial.print(__TIME__); Serial.print("\", วันที่=\""); Serial.print(__DATE__); Serial.println("\""); ) ) void loop() ( ) bool getTime(const char *str) ( int Hour, Min, Sec; if ( sscanf(str, "%d:%d:%d", &Hour, &Min, &Sec) != 3) return false; Second = Sec; return true; ) bool getDate(const char *str) ( ถ่าน เดือน; วัน, ปี; uint8_t ดัชนีเดือน; if (sscanf(str, "%s %d %d", Month, &Day, &Year) != 3) คืนค่าเท็จ; สำหรับ (monthIndex = 0; monthIndex< 12; monthIndex++) { if (strcmp(Month, monthName) == 0) break; } if (monthIndex >= 12) คืนค่าเท็จ; tm.Day = วัน; tm.เดือน = monthIndex + 1; tm.Year = CalendarYrToTm(ปี); กลับเป็นจริง; -

ดาวน์โหลดแบบร่าง

เราโหลดร่างนี้ลงในคอนโทรลเลอร์ Arduino (เวลาถูกนำมาจากระบบปฏิบัติการ) เปิด "การตรวจสอบพอร์ต"

โปรแกรม
มีอีกตัวอย่างหนึ่งในไลบรารี คุณสามารถเปิด DS1307RTC “File” -> “Examples” -> “DS1307RTC” -> “ReadTest”

/* ทำการทดสอบบน Arduino IDE 1.6.12 วันที่ทดสอบ 23/11/2559 */ #รวม // รวมไลบรารี Wire #include // รวมไลบรารี TimeLib #include // เชื่อมต่อการตั้งค่าโมฆะไลบรารี DS1307RTC() ( Serial.begin(9600); // ตั้งค่าอัตราการถ่ายโอนข้อมูลในขณะที่ (!Serial) ; // รอให้พอร์ตอนุกรมเชื่อมต่อ จำเป็นเท่านั้นสำหรับ Leonardo ล่าช้า (200); // รอ 200 µs Serial.println("DS1307RTC Read Test"); // ส่งข้อมูลออกไปยังพอร์ตอนุกรม Serial.println("-------------------" ); พอร์ตอนุกรม ) void loop() ( tmElements_t tm; if (RTC.read(tm)) ( Serial.print("Ok, Time = "); print2digits(tm.Hour); Serial.write(///) ; print2digits (tm.Minute); Serial.write(quote); print2digits(tm.Second); วันที่ (D/M/Y) = "); .write("/"); Serial.print(tm. เดือน); Serial.print(tmYearToCalendar(tm.Year)); else (if (RTC) .chipPresent()) ( Serial.println("The DS1307 is stop. Please run the SetTime"); Serial.println("example) เพื่อเริ่มต้นเวลาและเริ่มทำงาน"); Serial.println(); ) else ( Serial .println("DS1307 read error! โปรดตรวจสอบวงจร"); Serial.println(); ) ล่าช้า(9000); ) ล่าช้า(1000); ) ถือเป็นโมฆะ print2digits(int number) ( ถ้า (หมายเลข >= 0 && หมายเลข< 10) { Serial.write("0"); } Serial.print(number); }

ดาวน์โหลดแบบร่าง

เราโหลดโค้ดนี้ลงในคอนโทรลเลอร์ Arduino เปิด "Port Monitoring"