Thời gian của PWM được xác định bởi tốc độ tràn bộ đếm thời gian của bạn. Có rất nhiều cài đặt trên phần Chế độ hoạt động để suy nghĩ. Nếu tất cả những gì bạn muốn làm là tạo ra một sóng vuông có chu kỳ không đổi, với chu kỳ nhiệm vụ thay đổi, tôi nghĩ bạn sẽ muốn sử dụng chế độ CTC (Xóa bộ đếm thời gian trên So sánh so sánh). Ý tưởng cơ bản là đặt OCR0A thành số lần bấm giờ cho đến khi bạn muốn ghim chuyển đổi tiếp theo và sử dụng ngắt So sánh đối sánh để thay đổi giá trị đó cho lần tiếp theo. Vì vậy, trong avr-gcc, nó sẽ trông giống như:
#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdint.h>
// global variables defining number of ticks on and off
uint8_t on_time_ticks, off_time_ticks, csxx_bits=0;
void setup_timer(double p_ms, double duty){
TCCR0A = _BV(COM0A0) // toggle OC0A on Compare Match
TCCR0B = _BV(WGM02); // set CTC mode WGM0[2,1,0] = 0b100
// ... do some stuff based on your CPU frequency
// to define the csxx_bits of TCCR0B when the timer is running
// and consequently, to set on_time_ticks and off_time_ticks
OCR0A = on_time_ticks;
TCCR0B |= your_settings_here;
}
void start_timer(){
//start the timer running at the desired rate
TCCR0B |= csxx_bits;
}
int main(int argc, char **argv){
double period_ms, duty_cycle;
setup_timer(period_ms, duty cycle);
start_timer();
for(;;){
//spin or sleep or whatever
}
}
ISR(TIM0_COMPA_vect){
if(OCR0A == on_time_ticks){
OCR0A = off_time_ticks;
}
else{
OCR0A = on_time_ticks;
}
}
Cảnh báo, đây là mã chưa được kiểm tra nhưng tôi nghĩ ý tưởng này là đúng. Đây không phải là cách duy nhất để làm điều đó.
Nhân tiện, có một điều bạn nên biết về ATTiny13. Bộ tạo dao động RC nội bộ chỉ được đảm bảo chính xác trong vòng 10% so với sàn nhà máy. Có một quá trình sử dụng hiệu chuẩn bạn có thể đi qua (được mô tả bởi một Atmel appnote ) sẽ giúp bạn có được 2% độ chính xác cho ATtiny13. Nếu bạn muốn làm tốt hơn thế, có lẽ bạn sẽ cần sử dụng một con chip chứa một tinh thể bên ngoài ...