Sida 2 av 2
Postat: 5 juni 2006, 13:24:14
av cykze
(0<<WGM00) är det samma som 0. En miss?
Vilken AVR använder du?
Man brukar aktivera interrupts globalt, sei(), efter att alla interruptinställningar gjorts. Vanligtvis placeras den precis innan huvudloopen startar.
>
"Kopplingen mellan looparna och interruptrutinen verkar väldigt osäker." <-- Vad menar du?
Jag tänkte främst på din jämförelse med variabeln 'dutyCycle'. Visserligen har du så långa delays i looparna i main(), så det inte borde ställa till med några problem. Men lösningen känns ändå inte 100% säker.
Om du kör med samma frekvens på alla 8 kanaler så borde du kunna få in det i en vanlig timer-interrupt.
Kan man inte göra något sånt här?
Kod: Markera allt
volatile uint8_t pwm[8];
timerinterrupten()
{
static uint8_t counter = 0;
uint8_t i;
if (counter == 0)
PORTB = 0x00;
for (i=0; i<sizeof(pwm); i++)
if (counter > pwm[i])
PORTB |= _BV(i);
counter++;
}
Varje element i pwm laddas med varsin dutycycle (0-255), och hela PORTB används för PWM.
edit: Lite kodfix och stavfel
edit2: kodfix igen
Postat: 5 juni 2006, 13:56:37
av JimmyAndersson
"MikroC är ju till PIC.... och Korken inkluderar en massa AVR-filer.... "
Icecap: Oj, jag såg inte AVR-prylarna.

Postat: 5 juni 2006, 22:31:50
av Korken
JimmyAndersson skrev:Korken: Vad programmerar du i? Är det t.ex MikroC ?
I Programmers Notepad.
//Emil
Postat: 6 juni 2006, 12:40:52
av Korken
cykze:
Jo, de var en smart lösning. Men, vad är _BV(i) i din kod?
Gärna lite info för den ser väldigt användbar ut.
//Emil
Postat: 6 juni 2006, 14:28:35
av cykze
_BV(i) är samma sak som (1<<i), och är definierat i någon av headerfilerna. Det är en smaksak vilket skrivsätt man använder.
Koppla koden så att den körs från en timer. Hur ofta timern körs avgör frekvensen på signalen.
Det första den gör är att nollställa alla pinnar på PortB. Sen är det en räknare som räknar upp med ett för varje interrupt. Efter 256 interrupt slår räknare om till 0 och PortB nollställs igen. Genom att sätta olika värden i arrayen pwm får man motsvarande pinne på PortB att gå hög någonstans mellan 0 - 255. pwm[0] = 127 gör t ex att man borde få en dutycycle på 50% på pinnen PB0.
Jag har inte testat koden själv, men jag tycker det borde fungera acceptabelt.
Postat: 6 juni 2006, 17:01:45
av Korken
Ok, ja måste säga att de va en smart lösning!
//Emil
Postat: 5 juli 2006, 23:14:09
av Diger_s
Hej.
Detta är mitt första inlägg och passande nog har det med software PWM att göra.
Jag håller på med en vidareutveckling av Fagge RGB-fönsterbelysning. Det blir inte lika snyggt då jag inte vill lära mig löda ytmonterat men jag hade tänkt att utveckla konceptet så man kan styra lampan från datorn och (i framtiden) köra synkroniserade mönster mellan olika lampor.
Men jag får inte min software PWM att fungera och jag har suttit många timmar och felsökt. Koden väldigt förenklad är som följer:
Kod: Markera allt
#define __AVR_ATtiny45__
#include <avr/io.h>
#include <avr/interrupt.h>
//#include "main.h"
volatile uint8_t next;
//main pwm
ISR(TIM1_OVF_vect){
static uint8_t softcount = 255;
static uint8_t current;
if(++softcount == 0){
current = next;
PORTB = 0x00;
}
if(softcount == current) PORTB=0x08;
}
ISR(TIM0_OVF_vect){
static uint8_t count = 0;
//PORTB ^= 0x08;
if(++count == 1){
++next;
//PORTB ^= 0x08;
}
}
int main(){
sei();
TCCR1 = 0x00; //prescaler timer1
TCCR0B = 0x05; //prescaler timer0
TIMSK |= 0x06; //interrupt
next = 0;
PORTB = 0x00;
for(;;){}
return 0;
}
Jag vet inte vad som är fel, jag har fyllt for-loopen med nop;ar och bytt plats på sei(); men utan resultat. Det jag har kommit fram till hittils är att det har något att göra med interrupten. Det verkar som om avren resettar sig på något vis. LEDen på PORTB blinkar frenetiskt (flashar) när jag avkommenterar PORTB ^= 0x08;, oavsätt vart jag avkommenterar den. Sätter jag TCCR1 = 0x01 slutar det att fungera.
Är det någon som vet varför den beter sig som den gör?
Postat: 6 juli 2006, 00:33:12
av sodjan
> Det verkar som om avren resettar sig på något vis.
I PIC-världen brukar det tyda på att man har watchdog enablat...
Postat: 6 juli 2006, 09:24:35
av Diger_s
Det har redan slagit mig och jag har provat att lägga in wdt_reset() lite här och var utan resuiltat.
Postat: 6 juli 2006, 10:46:34
av Diger_s
Det är löst. Det var så enkelt att den avr-gcc version inte förstod vad attiny45 var för någon krets och sådeles förmodligen komplierade fel. En nergradering och många timmar senare fungerar faktiskt den kod jag skrivit.
Postat: 6 juli 2006, 12:28:56
av sodjan
> Det har redan slagit mig och jag har provat att lägga in wdt_reset() lite här och var utan resuiltat.
Är det inte mycket enklare att bara *stänga av* WDT ?
> Det var så enkelt att den avr-gcc version inte förstod vad attiny45 var för någon krets
Dåligt att den då inte kunde säga det !
Postat: 6 juli 2006, 13:17:08
av Diger_s
Jag hade förståss fulhackat Makefile lite

Läste att ATTiny45 är av varianten avr2 för avr-gcc och satte sådeles MCU_TARGET till avr2 och satte __AVR_ATtiny45__ det första jag gjorde i main.c. Det intressanta var att cggvesionen var 4.1.1 och den version jag nedgraderade till var 3.4.5. Där förstod den vad ATTiny45 var.
Men nu fungerar det som det ska. När jag börjar bli färdig ska jag försöka posta lite bilder på projektet.