ATmega88 - Timer1 *Löst*

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
syltkaka
Inlägg: 188
Blev medlem: 9 december 2006, 18:55:09
Ort: Göteborg

ATmega88 - Timer1 *Löst*

Inlägg av syltkaka »

Hej

Ska programmera min AVR för att styra ett par vanliga rc-servon. Mha Timer1 vill jag generera 1-2ms långa pulser som återkommer var 20:e ms. Jag har aldrig arbetat med någon mikrokontroller förut och heller ej programmerat i C. Har dock programmerat förut.

Jag har lyckats styra servona först med delay och sedan med Timer0 med gott resultat. När jag använde Timer0 körde jag med faskorrekt PWM vilket tyvärr visade sig ge för dålig upplösning.

Nu tänker jag använda Timer1 (16bit) med snabb PWM för att få rejäl upplösning. Till problemet.

När jag skriver till 16-bitarsregistret OCR1A så funkar det fint. Den höga byten blir som den ska och den låga som den ska. Men efter ca 3 klockcyklar i whilesatsen så sätts den höga biten till 0000 0001, oavsett vad för värde där låg innan. I databladet står det hur man ska göra när man ska skriva till 16-bitars registers och nedan i kodexemplet ser ni min tolkning.

Vidare, hur många gånger jag än kollar WGM bitarna i TCCR1A/B så är dem rätt jämfört med databladet för att skapa snabb PWM med ICR1 definierad som TOP (jämför databladet sid 156). Likväl envisas simulatorn i AVR Studio4 att berätta för mig att räknarregistret TCNT1 räknar neråt (dekrementeras) vilket det inte ska göra med snabb PWM.

Kod: Markera allt

#define F_CPU	8000000
#include <avr/io.h>
#include <util/delay.h>

int main()
{
	//Variabeldeklaration
	unsigned char sreg;

	//Clock prescale register --> 8MHz
	CLKPR = 0x80;
	CLKPR = 0x00;
	
	//In- och utgångar
	DDRC = 0x20;

	//Initiera 16-bitreg
	sreg = SREG;
	SREG &= 0x7F;
	OCR1A = 1500;
	ICR1= 20000;
	SREG = sreg;

	//Timer1
	TCCR1B |= (1<<WGM12) | (1<<WGM13) | (1<<CS11);
	TCCR1A |= (1<<WGM11) | (1<<COM1A1);

	while(1)
	{
	}

	return 0;
}
Slutligen. Mitt misstag/fel kanske är uppenbart men JAG ser inte vad det kan vara. Jag använder WinAVR och programmar med avrdude. Har en parallellportsprogrammerare. Får inga kompileringsfel.

EDIT: Länk till Datablad
Senast redigerad av syltkaka 10 december 2006, 14:00:23, redigerad totalt 2 gånger.
Användarvisningsbild
Icecap
Inlägg: 26660
Blev medlem: 10 januari 2005, 14:52:15
Ort: Starup (Haderslev), Danmark

Inlägg av Icecap »

Lång URL till vettig: (mellanslag inlagt för synbarhet)
[ url=skitlångURLsomfårfönstretattfåfnatt]En kort beskrivning[/ url]
(Ta alltså bort alla mellanslag mellan '[' och ']')
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Har du testat och se om det fungerar i verkligheten?

För AVRStudio har lite (eller rättare sagt mycke) problem med 16bitars timmer

Från hjälp filen i AVRStudio:
"Known Issues: 16-bit Timer/Counters on all devices have several problems with PWM, prescaler and output compare."

SREG behöver du inte peta i (i det här exemplet), varför det står i data bladet är för att skrivningen till 16bitars registret inte ska bli avbrutet av ett interupt.
Så ledes behöver du inte peta i SREG om programet befinner sej i en interuptrutin eller intrupten avslagen.

litet tips SREG &= 0x7F; är lika med cli(); ^^
syltkaka
Inlägg: 188
Blev medlem: 9 december 2006, 18:55:09
Ort: Göteborg

Problemet löst

Inlägg av syltkaka »

Icecap: Tack!

Exile: Tack för upplysningen. Mkt riktigt visade det sig att simulatorn verkligen inte klarar av att hantera 16-bitarstimern. Tidigare använde jag interrupt för att sätta en breakpoint där så att jag skulle kunna mäta tiden i simulatorn. I framtiden kommer jag använda interrupt och då kommer jag använda cli(); (i databladet i kodeexempel står det _cli(); vilket inte fungerar, varför står det så?).


Problemet är alltså löst nu. Allt var mitt fel. När jag körde med Timer0 så var ju servot inkopplat på OC0A-pinnen men när jag skulle prova Timer1 glömde jag flytta servot till OC1A-pinnen.

Nu har jag ungefär 1000 steg framåt och lika många bakåt vilket visserligen är helt overkill men och andra sidan så är tre steg fram och bak för lite vilket jag hade med 8-bitarstimern.

Notera att i min kod i första inlägget sätter jag fel pinne till utgång. Det ska vara DDRB = 0x02;
Användarvisningsbild
exile
EF Sponsor
Inlägg: 496
Blev medlem: 21 oktober 2005, 23:32:07

Inlägg av exile »

Alla c exemplel i databladena är för IAR c kompilator, så _cli(); är för IAR och inte för gcc-avr ^^

Men det mesta skrivs på samma sätt...
Skriv svar