Jeśli chodzi o sprzętowego PWMa to chyba pokuszę się o AVR136, tylko zamiast atmegi wykorzystam attiny2313. Zasymulowałem sobie to na razie tylko w proteusie i całkiem ładnie to śmiga
___________________________________________________
Ok. Potrzebuje Waszej pomocy. PWMy ładnie działąją (12 kanałów), ale nie wiem jak zwiększyć częstotliwość tego PWMa. Przy kwarcu 20MHz jest tylko 303 Hz. Nie wiem dlaczego dzieli zegar aż na 65536 (256*256). Rozumiem, że pierwsze 256 to od tego, że licznik jest 8 bitowy. Drugie 256 od rozdzielczości PWMa.
Nie rozumiem, dlaczego jeśli załaduje do TCNT0 wartość większą od zera, co powinno skutkować skróceniem czasu odstępu pomiędzy przerwaniami, ten czas mi wydłuża, a w konsekwencji częstotliwość maleje.
A może zmniejszyć rozdzielczość PWMa co by zwiększyło częstotliwość. Jak zmienić z 256 na np 64? (co powinno dać 4-krotną częstotliwość rzędu 1,2kHz).
Poniżej trochę przerobiony przykład z AVR136.
[*.c]
#include <ctype.h>
#include "t2313_softpwm.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/signal.h>
#include <avr/wdt.h>
#include <util/delay.h>
//! global buffers
volatile unsigned char compare[CHMAX];
volatile unsigned char compbuff[CHMAX];
/*! \brief Init function. This function initialises the hardware
*/
void Init(void)
{
unsigned char i;
//unsigned char pwm;
//pwm = 200;
CLKPR = (1 << CLKPCE); // enable clock prescaler update
CLKPR = 0; // set clock to maximum (= crystal)
wdt_reset(); // reset watchdog timer
MCUSR &= ~(1 << WDRF); // clear the watchdog reset flag
WDTCSR |= (1<<WDCE)|(1<<WDE); // start timed sequence
WDTCSR = 0x00; // disable watchdog timer
DDRD = PORTD_MASK; // set port pins to output
DDRB = PORTB_MASK; // set port pins to output
/*
for(i=0 ; i<CHMAX ; i++) // initialise all channels
{
compare[i] = 128; // set default PWM values
compbuff[i] = 128; // set default PWM values
}
*/
TIFR = (1 << TOV0); // clear interrupt flag
TIMSK = (1 << TOIE0); // enable overflow interrupt
TCCR0B = (1 << CS00); // start timer, no prescale
//TIFR = (1 << TOV1); // clear interrupt flag
//TIMSK = (1 << TOIE1); // enable overflow interrupt
//TCCR1B = (1 << CS00); // start timer, no prescale
sei(); // enable interrupts
}
/*! \brief Interrupt Service Routine
*/
SIGNAL (SIG_TIMER0_OVF)
{
static unsigned char pinlevelB = PORTB_MASK, pinlevelD=PORTD_MASK;
static unsigned char softcount = 256;
PORTB = pinlevelB; // update outputs
PORTD = pinlevelD; // update outputs
if(++softcount == 0) // increment modulo 256 counter and update
{
for(unsigned char a = 0 ; a < CHMAX ; a++) compare[a] = compbuff[a];
// the compare values only when counter = 0.
// last element should equal CHMAX - 1
pinlevelB = PORTB_MASK; // set all port pins high
pinlevelD = PORTD_MASK; // set all port pins high
}
// clear port pin on compare match (executed on next interrupt)
if(compare[0] == softcount) CH0_CLEAR;
if(compare[1] == softcount) CH1_CLEAR;
if(compare[2] == softcount) CH2_CLEAR;
if(compare[3] == softcount) CH3_CLEAR;
if(compare[4] == softcount) CH4_CLEAR;
if(compare[5] == softcount) CH5_CLEAR;
if(compare[6] == softcount) CH6_CLEAR;
if(compare[7] == softcount) CH7_CLEAR;
if(compare[8] == softcount) CH8_CLEAR;
if(compare[9] == softcount) CH9_CLEAR;
if(compare[10] == softcount) CH10_CLEAR;
if(compare[11] == softcount) CH11_CLEAR;
}
int main(void)
{
DDRA = 255;
Init();
compbuff[8] = 128;
while(1)
{
PORTA |= (1<<2);
_delay_us(100);
PORTA &= ~(1<<2);
_delay_us(100);
}
return 0;
}
[*.h]
//! Pin mappings
#define CHMAX 12 // maximum number of PWM channels
#define CH0_CLEAR (pinlevelB &= ~(1 << PB0))
#define CH1_CLEAR (pinlevelB &= ~(1 << PB1))
#define CH2_CLEAR (pinlevelB &= ~(1 << PB2))
#define CH3_CLEAR (pinlevelB &= ~(1 << PB3))
#define CH4_CLEAR (pinlevelB &= ~(1 << PB4))
#define CH5_CLEAR (pinlevelB &= ~(1 << PB5))
#define CH6_CLEAR (pinlevelB &= ~(1 << PB6))
#define CH7_CLEAR (pinlevelB &= ~(1 << PB7))
#define CH8_CLEAR (pinlevelD &= ~(1 << PD3))
#define CH9_CLEAR (pinlevelD &= ~(1 << PD4))
#define CH10_CLEAR (pinlevelD &= ~(1 << PD5))
#define CH11_CLEAR (pinlevelD &= ~(1 << PD6))
//! Set bits corresponding to pin usage above
#define PORTB_MASK (1 << PB0)|(1 << PB1)|(1 << PB2)|(1 << PB3)|(1 << PB4)|(1 << PB5)|(1 << PB6)|(1 << PB7)
#define PORTD_MASK (1 << PD3)|(1 << PD4)|(1 << PD5)|(1 << PD6)
//! prototypes
void Init(void);