Zdravím, už je to nějakou dobu co jsem sem psal a sháněl nějaký návod na 4 kanálové PWM vytvořené softwarově. To co mi pan kolega
Showlee, kterému za to ještě jednou děkuju, už ovšem nestačí. PWM funguje na frekvenci 244Hz a po připojení na výkonové LED je vidět jemné “poblikávání”. Proto jsem se rozhodl program upravit, zatím bohužel neúspěšně.
Myšlenka však zůstává stejná, čitač, který načítá vzhůru a pomocí porovnávacího registru se porovnává aktuální hodnota s nastavenou a při shodě se vyvolá přerušení ve kterém se provede nastavení kanálu do log.1. Kanály musí být ovšem seřazeny postupně ,aby mohlo během načítání čitače dojít k nastavení všech 4 kanálů(proto pole [hodnota,pozice]). Při přetečení čítače se všechny kanály shodí zpět na 0 a začne se znovu.To vše na frekvenci cca 1kHz, a OC proto, aby PWM generovalo co nejmenší počet přerušení.
Bohužel realita je krutá a tak jak jsem si myslel ,že by to mohlo fungovat, tak to zatím nefunguje. Zde přikládám kód(boublesort jsem vyřadil a hodnoty si nastavil vzestupně už dopředu):
#define F_CPU 16000000UL
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include "uart.h"
//.................SW-PWM.........................
#define REG_TCNT0 0 // frekvence PWM
#define BITPOS_0 0
#define BITPOS_1 1
#define BITPOS_2 2
#define BITPOS_3 3
#define PORT_1 PORTB
#define SET_BIT(BYTE,BIT)(BYTE|=(1<<BIT))
#define CLEAR_BIT(BYTE,BIT)(BYTE&=~(1<<BIT))
#define CHECK_BIT(BYTE,BIT)(BYTE&=(1<<BIT))
// Deklarace globalnich promennych
//volatile unsigned char Kanal1 = 0,Kanal2 = 0,Kanal3 = 0,Kanal4 = 0;
volatile unsigned char Kanal[4][2]={ {0,1} , {10,2} , {230,3} , {254,4} };
volatile unsigned char pozice=0;
ISR(TIMER0_COMP_vect)//přerušení pri shode registru
{
// jestlize promenna [cislo][x] je 1 nastav kanal1
do{
SET_BIT(PORT_1,(Kanal[pozice][1])); //nastaví příslušný bit do 1
pozice++; //posun na další kanál
}while(Kanal[pozice-1][0]==Kanal[pozice][0]); //opakuje nastaveni pokud se hodnoty rovnají
OCR0=Kanal[pozice][0]; //nastaví další kanál
if(pozice==3){pozice=0;} //nulování
}
ISR(TIMER0_OVF_vect)//přerušení pri přetečení
{
CLEAR_BIT(PORT_1,BITPOS_0); // nuluje piny 0
CLEAR_BIT(PORT_1,BITPOS_1); // nuluje piny 1
CLEAR_BIT(PORT_1,BITPOS_2); // nuluje piny 2
CLEAR_BIT(PORT_1,BITPOS_3); // nuluje piny 3
OCR0=Kanal[0][0];
}
void bubbleSort(void)
{
int i, j;
unsigned char temp,temp2;
for (i = (4 - 1); i > 0; i--)
{
for (j = 1; j <= i; j++)
{
if (Kanal[j-1][0] > Kanal[j][0])
{
temp = Kanal[j-1][0];
temp2 = Kanal[j-1][1];
Kanal[j-1][0] = Kanal[j][0];
Kanal[j-1][1] = Kanal[j][1];
Kanal[j][0] = temp;
Kanal[j][1] = temp2;
}
}
}
}
//HLAVNI PROGRAM
int main (void){
sei(); //povolení globalniho přerušení
PORTA= 0xFF; //PORT A - 1 na vystupu (pro tlačitka)
DDRA= 0x00; //PORT A - Vstupy
PORTB = 0x00; // LED
DDRB = 0xFF; //Port B - jako vystup výkonových LED Kanálu
PORTC= 0xFF; //PORT C - 1 na vystupu (zhasnou led)
DDRC = 0xFF; //PORT C - Vystupy7
bubbleSort();
// Nastaveni TIMER0 a Preruseni (Timer0 zajistuje softwarove PWM)
TCNT0 = REG_TCNT0;
TIMSK |= (1<<TOIE0)|(1<<OCIE0) ; // Preruseni pri preteceni a shodě
TCCR0 |= (1<<CS01)|(1<<CS00); // Normalni rezim,delicka f/64
for(;;)
{
}
}
Pokud by v tom někdo viděl zásadní problém byl bych rád za jakoukoli pomoc. Jinak mě napadlo když mám volný 16 bit č/č udělat to pomocí něj ten má přece jenom 2 OC registry ale zatím se mi nepodařilo rozběhnout nějakým způsobem toto tak se nechci pouštět do jiného.