টাইমার ও কাউন্টার
এই পাঠে যা শিখবেন
- ফ্রি-রানিং কাউন্টার ও reload/compare রেজিস্টারের কাজ
- প্রিস্কেলার কেন লাগে এবং ক্লক ফ্রিকোয়েন্সি কমাতে কীভাবে কাজ করে
- ইন্টারাপ্ট পিরিয়ড গণনার সূত্র এবং কয়েকটি বাস্তব কনফিগারেশনে তার প্রয়োগ
- একটি সত্যিকারের tick-by-tick কাউন্টার সিমুলেশন দিয়ে সূত্রের গণনা সরাসরি যাচাই করা
১ · টাইমার/কাউন্টার আসলে কী
টাইমার/কাউন্টারTimer/Counterএকটি হার্ডওয়্যার রেজিস্টার যা প্রতি ক্লক পালসে নিজে থেকে বাড়ে বা কমে — CPU-কে কোনো ইনস্ট্রাকশন চালাতে হয় না। হলো মাইক্রোকন্ট্রোলারের ভেতরে বসানো একটি সাধারণ কিন্তু অত্যন্ত গুরুত্বপূর্ণ পেরিফেরাল — একটি রেজিস্টার যা প্রতি ক্লক সাইকেলে (বা প্রিস্কেল করা ক্লকে) নিজে থেকে ১ করে বাড়ে, সম্পূর্ণ স্বয়ংক্রিয়ভাবে, CPU-এর কোনো হস্তক্ষেপ ছাড়াই। রেজিস্টার আর্কিটেকচারের সাধারণ ধারণার জন্য Computer Architecture কোর্স দেখুন — এই পাঠ ধরে নিচ্ছে সেই ভিত্তি আছে এবং সরাসরি টাইমার পেরিফেরালের আচরণে যাচ্ছে।
কাউন্টার একটি নির্দিষ্ট সর্বোচ্চ মান (যেমন ৮-বিট হলে ২৫৫, ১৬-বিট হলে ৬৫৫৩৫) পর্যন্ত বেড়ে তারপর ওভারফ্লো করে ০-তে ফিরে যায় — অথবা একটি প্রোগ্রামযোগ্য reload/compare রেজিস্টার-এ পৌঁছালেই ম্যাচ ইভেন্ট ঘটিয়ে নিজে থেকে রিসেট হয়ে আবার গোনা শুরু করে। প্রতিটি ওভারফ্লো/ম্যাচ ইভেন্ট একটি হার্ডওয়্যার ইন্টারাপ্ট জেনারেট করতে পারে — অর্থাৎ একবার কনফিগার করে দিলে টাইমার নিজে থেকেই নিয়মিত বিরতিতে CPU-কে "জাগিয়ে দেয়", পোলিং লুপের প্রয়োজন ছাড়াই (L17-এর পোলিং বনাম ইন্টারাপ্ট তুলনার মতোই — এখানে ইভেন্টটা সময়-ভিত্তিক)।
২ · প্রিস্কেলার — ক্লককে ধীর করা
মাইক্রোকন্ট্রোলারের মূল ক্লক সাধারণত মেগাহার্টজ রেঞ্জে (যেমন ১৬ MHz) — সরাসরি এই গতিতে একটি ৮/১৬-বিট কাউন্টার চালালে তা প্রতি সেকেন্ডে লক্ষ লক্ষ বার ওভারফ্লো করবে, যা বেশিরভাগ বাস্তব-জীবনের টাইমিং কাজের (যেমন ১ সেকেন্ড পরপর একটি LED ব্লিংক করানো) জন্য অপ্রয়োজনীয়ভাবে দ্রুত এবং ইন্টারাপ্ট ওভারহেড বাড়িয়ে দেবে। এই সমস্যা সমাধানের জন্য থাকে প্রিস্কেলার — একটি বিভাজক (divider) যা মূল ক্লককে N দিয়ে ভাগ করে কাউন্টারে পাঠায়, ফলে কাউন্টার প্রতি N ক্লক সাইকেলে একবার বাড়ে।
৩ · ইন্টারাপ্ট পিরিয়ড গণনার সূত্র
প্রিস্কেলার ও reload ভ্যালু জানা থাকলে ইন্টারাপ্ট ঠিক কত সেকেন্ড পরপর ফায়ার হবে তা নির্ভুলভাবে গণনা করা যায়:
$$ T_{period} = \dfrac{N_{prescaler} \times N_{reload}}{f_{clock}} $$
এখানে $N_{prescaler}$ হলো প্রিস্কেলার ডিভিশন ফ্যাক্টর, $N_{reload}$ হলো reload/compare রেজিস্টারে সেট করা টার্গেট ভ্যালু, এবং $f_{clock}$ হলো মূল ক্লক ফ্রিকোয়েন্সি (Hz)। নিচের কোড সেলে কয়েকটি বাস্তব কনফিগারেশনের জন্য এই সূত্র সরাসরি প্রয়োগ করে পিরিয়ড গণনা করা হয়েছে।
class Timer:
def __init__(self, clock_hz, prescaler, reload_value):
self.clock_hz = clock_hz
self.prescaler = prescaler
self.reload_value = reload_value
def formula_period_s(self):
# সূত্র: T = (prescaler * reload) / clock_hz
return (self.prescaler * self.reload_value) / self.clock_hz
configs = [
("কনফিগ A", Timer(clock_hz=16_000_000, prescaler=1, reload_value=16_000)),
("কনফিগ B", Timer(clock_hz=16_000_000, prescaler=64, reload_value=25_000)),
("কনফিগ C", Timer(clock_hz=8_000_000, prescaler=1024, reload_value=7_813)),
]
print("ক্লক + প্রিস্কেলার + reload থেকে ইন্টারাপ্ট পিরিয়ড:")
for name, t in configs:
period_s = t.formula_period_s()
print(f" {name}: clock={t.clock_hz:>10,} Hz, prescaler={t.prescaler:>5}, "
f"reload={t.reload_value:>6} -> period={period_s*1000:.4f} ms "
f"(~{1/period_s:.2f} Hz ইন্টারাপ্ট রেট)")
৪ · সিমুলেশন দিয়ে সূত্র যাচাই
উপরের সূত্র নির্ভুল কিনা তা যাচাই করার সবচেয়ে ভালো উপায় হলো কাউন্টারকে সত্যিই tick-by-tick গণনা করিয়ে দেখা — প্রতিটি tick-এ কাউন্টার ১ করে বাড়বে, যতক্ষণ না reload ভ্যালুতে পৌঁছায়। নিচের কোড সেলে এই সিমুলেশন চালিয়ে গণনা করা tick সংখ্যা দিয়ে বের করা পিরিয়ডকে সূত্রের পিরিয়ডের সাথে সরাসরি তুলনা করা হয়েছে।
class SimulatedTimer:
def __init__(self, clock_hz, prescaler, reload_value):
self.clock_hz = clock_hz
self.prescaler = prescaler
self.reload_value = reload_value
def formula_period_s(self):
return (self.prescaler * self.reload_value) / self.clock_hz
def run_until_overflow(self):
# সত্যিকারের tick-by-tick গণনা: কাউন্টার ০ থেকে শুরু করে
# প্রতি tick-এ ১ করে বাড়ে, reload_value-এ পৌঁছালে থামে
count = 0
ticks_counted = 0
while count < self.reload_value:
count += 1
ticks_counted += 1
return ticks_counted
t = SimulatedTimer(clock_hz=16_000_000, prescaler=64, reload_value=25_000) # কনফিগ B
ticks_counted = t.run_until_overflow()
simulated_period_s = (ticks_counted * t.prescaler) / t.clock_hz
formula_period_s = t.formula_period_s()
print(f"reload_value = {t.reload_value}")
print(f"সিমুলেশনে গোনা ticks = {ticks_counted}")
print(f"সিমুলেশন থেকে পিরিয়ড = {simulated_period_s*1000:.4f} ms")
print(f"সূত্র থেকে পিরিয়ড = {formula_period_s*1000:.4f} ms")
print(f"দুটো মেলে? = {abs(simulated_period_s - formula_period_s) < 1e-9}")
ticks_counted সবসময় ঠিক reload_value-এর সমান হয়, কারণ লুপটি প্রতি tick-এ
ঠিক ১ করে বাড়ে এবং count == reload_value হওয়া মাত্র থেমে যায় — অর্থাৎ tick-by-tick
সিমুলেশন আর বন্ধ-আকৃতির সূত্র (closed-form formula) দুটোই একই ফলাফল দেয়, কারণ তারা আসলে একই
হার্ডওয়্যার আচরণের দুটো ভিন্ন বর্ণনা মাত্র। এই "সূত্র বনাম সিমুলেশন" যাচাই-পদ্ধতিটাই L19-এর PWM এবং
L20-এর ADC পাঠে আবার ব্যবহৃত হবে।
ভাবনার প্রশ্ন
প্রতিটি প্রশ্ন নিজে কিছুক্ষণ ভাবুন — তারপর "→ উত্তর" চাপুন।
প্র ০১ প্রিস্কেলার ছাড়া সরাসরি মূল ক্লক দিয়ে কাউন্টার চালালে কী সমস্যা হতে পারে?
দুটো সমস্যা হতে পারে। প্রথমত, কাউন্টার এত দ্রুত (মেগাহার্টজ রেঞ্জে) ওভারফ্লো করবে যে বাস্তব-জীবনের ধীর টাইমিং কাজে (যেমন প্রতি সেকেন্ডে একবার) প্রয়োজনের চেয়ে বহুগুণ বেশি ইন্টারাপ্ট ফায়ার হবে, যা CPU-কে অকারণে ব্যস্ত রাখবে। দ্বিতীয়ত, দীর্ঘ পিরিয়ড পেতে হলে reload রেজিস্টারে অত্যন্ত বড় মান লাগবে, যা রেজিস্টারের বিট-প্রস্থ (যেমন ১৬-বিট হলে সর্বোচ্চ ৬৫৫৩৫) ছাড়িয়ে যেতে পারে — প্রিস্কেলার এই দুটো সমস্যাই সমাধান করে, একই বিট-প্রস্থের রেজিস্টার দিয়ে অনেক বড় রেঞ্জের পিরিয়ড পাওয়া সম্ভব করে।
প্র ০২ reload ভ্যালু একই রেখে ক্লক ফ্রিকোয়েন্সি দ্বিগুণ করা হলে ইন্টারাপ্ট পিরিয়ড কীভাবে বদলাবে?
সূত্র $T_{period} = (N_{prescaler} \times N_{reload}) / f_{clock}$ অনুযায়ী $f_{clock}$ ভাজক (denominator)-এ আছে — তাই $f_{clock}$ দ্বিগুণ হলে $T_{period}$ অর্ধেক হয়ে যাবে (পিরিয়ড ক্লক ফ্রিকোয়েন্সির সাথে ব্যস্তানুপাতিক)। অর্থাৎ দ্রুত ক্লক মানেই একই reload ভ্যালুতে আগে ইন্টারাপ্ট আসবে — এই সম্পর্কটাই ব্যাখ্যা করে কেন M2-এর PLL/ক্লক-মাল্টিপ্লায়ার কনফিগারেশন পরিবর্তন করলে বিদ্যমান টাইমার কোড পুনরায় ক্যালিব্রেট করতে হতে পারে।
প্র ০৩
উপরের সিমুলেশন কোডে ticks_counted সবসময় ঠিক reload_value-এর সমান হয়
কেন — এটা কি কাকতালীয়?
না, কাকতালীয় নয় — এটা লুপের গঠন থেকেই নিশ্চিত। count ০ থেকে শুরু হয়ে প্রতি
ইটারেশনে ঠিক ১ করে বাড়ে, এবং লুপ শর্ত count < reload_value মিথ্যা হওয়া মাত্র
(অর্থাৎ count == reload_value হওয়া মাত্র) থেমে যায়। প্রতি ইটারেশনে
ticks_counted-ও ঠিক ততবারই বাড়ে যতবার লুপ চলে — তাই দুটো সবসময় সমান হবে। এটাই
একটা সত্যিকারের হার্ডওয়্যার কাউন্টারের আচরণের বিশ্বস্ত মডেল।
অনুশীলন
-
চিন্তা করুন:
clock_hz=16_000_000,prescaler=8,reload_value=20_000হলে ইন্টারাপ্ট পিরিয়ড কত হবে বলে আপনার ধারণা? কোড সেলে বসিয়ে যাচাই করুন।সূত্র অনুযায়ী $T = (8 \times 20{,}000) / 16{,}000{,}000 = 160{,}000 / 16{,}000{,}000 = 0.01$ সেকেন্ড, অর্থাৎ $10$ মিলিসেকেন্ড। কোড সেলের
Timerক্লাসে এই মান বসিয়েformula_period_s()কল করলে ঠিক এই ফলাফলই আসবে। -
পরীক্ষা করুন: দ্বিতীয় কোড সেলে
SimulatedTimer-এর কনফিগারেশন বদলে কনফিগ C (clock_hz=8_000_000,prescaler=1024,reload_value=7_813) দিয়ে Run চাপুন —ticks_countedও দুই পিরিয়ড কী মান দেখায়?ticks_countedহবে ঠিক $7{,}813$ (reload_value-এর সমান)। সিমুলেশন পিরিয়ড হবে $(7{,}813 \times 1024) / 8{,}000{,}000 \approx 1.0001$ সেকেন্ড, আর সূত্র থেকেও একই মান আসবে — দুটো মেলার ফলাফলTrueদেখাবে, নিশ্চিত করবে কনফিগ C প্রায় ১ সেকেন্ড পরপর একবার ইন্টারাপ্ট দেয়।
আরও পড়ুন · ABCL TECH-এ আপনার পরবর্তী পদক্ষেপ
- কোর্সের সম্পূর্ণ সিলেবাস দেখুন ৫৭টি পাঠ মাইক্রোপ্রসেসর আর্কিটেকচার, এমবেডেড C, GPIO, টাইমার/PWM/ADC, সিরিয়াল প্রোটোকল, RTOS, সেন্সর/অ্যাকচুয়েটর, IoT আর্কিটেকচার, ওয়্যারলেস প্রোটোকল, MQTT/CoAP ও IoT সিকিউরিটি — বাকি পাঠগুলো শীঘ্রই যুক্ত হবে।
- Computer Architecture & Digital Logic কোর্স সহোদর কোর্স রেজিস্টার ও ক্লক সিস্টেমের সাধারণ ভিত্তি সেই কোর্সেই তৈরি হয়েছে — এই কোর্স পেরিফেরাল-স্পেসিফিক টাইমিং হার্ডওয়্যারে গভীরে যায়।
- সব Courses দেখুন ABCL TECH C, C++, Python, Java, JavaScript, DSA, DBMS, Discrete Mathematics, System Design, Cybersecurity, Cloud Computing & DevOps, Computer Networks, Operating Systems, Computer Architecture, Design and Analysis of Algorithms ও আরও অনেক কোর্স — সব এক জায়গায়।