เมื่อทำงานที่ Prescaler นาฬิกา 64 ใน ATmega328 หนึ่งในตัวจับเวลาของฉันเร็วขึ้นด้วยสาเหตุที่ไม่ทราบเวลาในการดำเนินการ
ฉันใช้ตัวจับเวลาสองตัวบน ATmega328 เพื่อสร้างการตอกบัตรที่ต้องการโดยTLC5940 (ดูด้านล่างว่าทำไมเพราะนี่คือสิ่งสำคัญสำหรับคำถาม) TIMER0
สร้างสัญญาณนาฬิกาโดยใช้ Fast PWM OC0B
และตั้งค่าดังนี้:
TCCR0A = 0
|(0<<COM0A1) // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
|(0<<COM0A0) //
|(1<<COM0B1) // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
|(0<<COM0B0)
|(1<<WGM01) // Bits 1:0 – WGM01:0: Waveform Generation Mode
|(1<<WGM00)
;
TCCR0B = 0
|(0<<FOC0A) // Force Output Compare A
|(0<<FOC0B) // Force Output Compare B
|(1<<WGM02) // Bit 3 – WGM02: Waveform Generation Mode
|(0<<CS02) // Bits 2:0 – CS02:0: Clock Select
|(1<<CS01)
|(0<<CS00) // 010 = clock/8
;
OCR0A = 8;
OCR0B = 4;
TIMSK0 = 0;
TIMER2
ทวีคูณบรรทัดข้อมูลเพื่อสร้างพัลส์ blanking ทุก ๆ 256 TIMER0
รอบและตั้งค่าดังนี้:
ASSR = 0;
TCCR2A = 0
|(0<<COM2A1) // Bits 7:6 – COM0A1:0: Compare Match Output A Mode
|(0<<COM2A0) //
|(0<<COM2B1) // Bits 5:4 – COM0B1:0: Compare Match Output B Mode
|(0<<COM2B0)
|(0<<WGM21) // Bits 1:0 – WGM01:0: Waveform Generation Mode
|(0<<WGM20)
;
TCCR2B = 0
|(0<<FOC2A) // Force Output Compare A
|(0<<FOC2B) // Force Output Compare B
|(0<<WGM22) // Bit 3 – WGM02: Waveform Generation Mode
|(1<<CS22) // Bits 2:0 – CS02:0: Clock Select
|(0<<CS21)
|(0<<CS20) // 100 = 64
;
OCR2A = 255;
OCR2B = 255;
TIMSK2 = 0
|(1<<TOIE2); // Timer/Counter0 Overflow Interrupt Enable
TIMER2
เรียก ISR บนโอเวอร์โฟลว์ (ทุกๆ 256 รอบ) ISR สร้างพัลส์ blanking ด้วยตนเองและพัลส์ล็อคถ้าจำเป็น:
volatile uint8_t fLatch;
ISR(TIMER2_OVF_vect) {
if (fLatch) {
fLatch = 0;
TLC5940_XLAT_PORT |= (1<<TLC5940_XLAT_BIT); // XLAT -> high
for (int i=0;i<10;i++)
nop();
TLC5940_XLAT_PORT &= ~(1<<TLC5940_XLAT_BIT); // XLAT -> high
}
// Blank
TLC5940_BLANK_PORT |= (1<<TLC5940_BLANK_BIT);
for (int i=0;i<10;i++)
nop();
TLC5940_BLANK_PORT &= ~(1<<TLC5940_BLANK_BIT);
}
nop()
ล่าช้าในโค้ดข้างต้นเป็นเพียงที่จะทำให้การเต้นของชีพจรชัดเจนมากขึ้นในการติดตามวิเคราะห์ตรรกะ นี่คือลักษณะของการวนซ้ำในmain()
ฟังก์ชั่น: ส่งข้อมูลอนุกรมรอ ISR ดูแลการล็อคแล้วทำซ้ำอีกครั้ง:
for (;;) {
if (!fLatch) {
sendSerial();
fLatch = 1;
_delay_ms(1);
}
nop();
}
sendSerial()
SPI บางอันส่ง ( โค้ดบน pastebin เพื่อความกะทัดรัด ) ปัญหาของฉันคือหลังจากsendSerial()
เสร็จสิ้นในขณะที่รอfLatch
การตั้งค่าต่ำ (ประมวลผล) ตัวจับเวลาการตอกบัตรจะเร็วขึ้น นี่คือการติดตามตรรกะวิเคราะห์ (ฉันตัดออกพื้นที่ที่สัญญาณเดียวกันยังคงทำให้กราฟิกมีขนาดเล็กลง):
ทางด้านซ้ายช่อง 0 และ 1 แสดงส่วนท้ายของข้อมูล SPI ที่ส่ง ทางด้านซ้ายบนช่อง 4 คุณสามารถเห็นพัลส์ blanking ในช่องที่ 2 ชีพจรสับสัญญาณนาฬิกาตามที่คาดไว้ รอบ ๆ บริเวณที่ช่องว่างของภาพfLatch
ตั้ง1
อยู่ภายในmain()
รูทีน และในไม่ช้าTIMER0
ความเร็วก็เพิ่มขึ้นประมาณ 4 เท่าในที่สุดชีพจร blanking และ latching pulse จะถูกดำเนินการ (ช่อง 3 และ 4, สามในสามของภาพ) และตอนนี้ชีพจรการตอกบัตรกลับสู่ความถี่ปกติและข้อมูลอนุกรมนั้น ส่งอีกครั้ง ฉันพยายามถอดdelay_ms(1);
สายmain()
แต่ได้ผลลัพธ์เดียวกัน เกิดอะไรขึ้น? ฉันควรทราบว่า ATmega นั้นโอเวอร์คล็อกคริสตัล 20Mhz แล้วชะลอความเร็วลง 64x โดยใช้รหัสต่อไปนี้:
CLKPR = 1<<CLKPCE;
CLKPR = (0<<CLKPS3)|(1<<CLKPS2)|(1<<CLKPS1)|(0<<CLKPS0);
สิ่งนี้มีไว้สำหรับ: ฉันกำลังทดลองกับการควบคุมไดรเวอร์ LED TLC5940 : ชิปเหล่านี้ต้องใช้นาฬิกาภายนอกพร้อมการรีเซ็ตเมื่อสิ้นสุดรอบการตอกบัตร
sendSerial()
เป็นรหัสของฉันที่ส่งข้อมูลผ่าน SPI: มันไม่ได้สัมผัสTCCR
การลงทะเบียน (การควบคุมการจับเวลา)