Hallo,
ein weiteres Machwerk auf dem Weg zum Servotester mit Pulsweitenanzeige. Noch nicht ganz ausgereift und die Auflösung ist noch verbesserungswürdig. Aber damit hab ich hoffentlich schon ein paar Hürden zum Verstehen des ATtiny45 überwunden.

Mit dem CONFIG SERVO Befehl des BASCOM-AVR kam ich überhaupt nicht klar. Nach meinen Erfahrungen zu ungenau, abhängig von $CRYSTAL und sobald ISR laufen, nicht mehr kalkulierbar.

Deshalb den Timer1 "per Hand" für PWM konfiguriert. Da der Servo ein Impuls alle 20ms braucht, der zwischen 1 bis 2 ms lang sein soll und dieser Impuls auch noch möglichst fein einstellbar sein soll und auch noch sehr konstant sein muß, hab ich folgende Lösung versucht:
Kleinste Auflösung für Servopulseinstellung=16µs. Da man bei dem 8bit Timer damit nicht auf die 20ms Pulsabstand kommt - den Timer dann alle 5 Mal mit der Pulsweite als "Monoflop" Interrupt gesteuert auf den Ausgang wirken lassen - funktioniert.
Pulsweite einstellbar mit 10k Poti am ADC.

Code:
'###################################################
'File: Servotester mit Display.bas
'IDE: BASCOM-AVR Version 1.11.9.8
'HW circuit: ATtiny45_4_X_7_Segment_SPI (ADC- & Servoanschluß nicht eingezeichnet)
'Multiplexing und Servosignal via Timer1
'Servo an PB4. 10k Poti für Servopulseinstellung an PB3
'4 x 7 Segment zeigt Servopuls in ms an. Bereich 0,720ms bis 2,304ms in 16µs steps
'#######################################################

$regfile = "attiny45.dat"
$eepleave
$framesize = 32
$swstack = 32
$hwstack = 96                           'hwstack reichlich wg Interruptroutine
$crystal = 8000000

Dim X As Byte
Dim Y As Byte
Dim Z As Byte

Dim Init7segment As Byte

Dim Displaydigitaddress(4) As Word

Dim Displaydigit(17) As Byte            'darzustellende Zeichen (hex 0..F)
                   '0gfedcba (segmente, msb immer 0)
Displaydigit(1) = &B01000000            'Ziffer "0", 0 = segment ein, 1 = aus
Displaydigit(2) = &B01111001            'Ziffer "1"
Displaydigit(3) = &B00100100            'Ziffer "2"
Displaydigit(4) = &B00110000
Displaydigit(5) = &B00011001
Displaydigit(6) = &B00010010
Displaydigit(7) = &B00000010
Displaydigit(8) = &B01111000
Displaydigit(9) = &B00000000
Displaydigit(10) = &B00010000
Displaydigit(11) = &B00001000
Displaydigit(12) = &B00000011
Displaydigit(13) = &B01000110
Displaydigit(14) = &B00100001
Displaydigit(15) = &B00000110
Displaydigit(16) = &B00001110
Displaydigit(17) = &B01111111           'Wert um eine Ziffer dunkel zu schalten

Displaydigitaddress(1) = 16             'Wenn noch keine Ziffer eingegeben -> dunkel
Displaydigitaddress(2) = 16
Displaydigitaddress(3) = 16
Displaydigitaddress(4) = 16

X = 0                                   'Initialisierung von Zählvariablen
Y = 0                                   'Initialisierung von Zählvariablen
Z = 0                                   'Initialisierung von Zählvariablen

'Nutzung von Software SPI - nur Output
Config Spi = Soft , Dout = Portb.0 , Ss = Portb.1 , Clock = Portb.2
Spiinit

'mit Senden von acht high bits sicherstellen, daß über Q7 des Schieberegisters
'der HEF4017 erste Ziffer der 4 X 7 Segmentanzeige adressiert -> reset des 4017
Init7segment = &B11111111
Spiout Init7segment , 1


Config Portb.4 = Output                 'PB4 as output
Gtccr = Gtccr Or &B01100000             'set PWM1B & OC1B (PB4) to clear on compare
Ocr1b = 94                              'set pulse to 1504µs (on 8Mhz, prescaler = 128)
Ocr1c = 254                             'set min pwm frequency (8Mhz / 128 / 255 =~ 245 Hz
Tccr1 = Tccr1 Or &B00001000             'set prescaler (128) switches timer on
On Ovf1 Isr_timer1
Enable Timer1


Config Adc = Single , Prescaler = Auto , Reference = Avcc

Dim Comparematchvalue_ocr1b As Byte
Dim Adc_readout As Integer
Dim Adc_str As String * 5
Dim Char As String * 1
Dim Channel As Byte
Channel = 3                             'ADC3 (auf Pin PB3)

Enable Interrupts

Do

   Adc_readout = Getadc(channel)
   If Adc_readout < 10 Then
      Adc_readout = 10
      Elseif Adc_readout > 1000 Then
         Adc_readout = 1000
   End If

   Adc_readout = Adc_readout / 10
   Adc_readout = Adc_readout + 43
   Comparematchvalue_ocr1b = Adc_readout
   Adc_readout = Adc_readout * 16

   Adc_readout = Adc_readout + 10016
   Adc_str = Str(adc_readout)
   Char = Mid(adc_str , 2 , 1)
   Displaydigitaddress(1) = Val(char)
   Char = Mid(adc_str , 3 , 1)
   Displaydigitaddress(2) = Val(char)
   Char = Mid(adc_str , 4 , 1)
   Displaydigitaddress(3) = Val(char)
   Char = Mid(adc_str , 5 , 1)
   Displaydigitaddress(4) = Val(char)

Loop

End


Isr_timer1:

X = X And &B00000011
X = X + 1
Y = Displaydigitaddress(x) + 1
Spiout Displaydigit(y) , 1

If Z >= 4 Then
   Ocr1b = CompareMatchValue_OCR1B
   Bitwait Pinb.4 , Set
   Bitwait Pinb.4 , Reset
   Ocr1b = 0
   Z = 0
   Else
   Z = Z + 1
End If

Return

Praxistest mit echtem Servo steht noch aus (nur mit Oszi und 10k Pulldown probiert)
Anzeige flimmert leicht - warum auch immer - mal sehen...

EDIT: wg. Flimmern siehe verbessertes Listing im Beitrag vom 12.02.2011 weiter hinten im thread

Fazit - ich glaub ich hab den "nicht phasen korrekten PWM Timer" verstanden

Bitte um Aufzeigen möglicher Probleme, Kommentare, Fragen, etc. willkommen.

(hab mir vorgenommen, den Code demnächst noch ein bißchen besser zu kommentieren)

Gruß
Searcher