Hallo,
das Displayflimmern ist auf dem Video sehr stark und sicher größtenteils vom Stroboskopeffekt hervorgerufen worden. Es war aber sozusagen Angesicht zu Angesicht auch noch ein leichtes Flimmern zu erkennen, daß mir aber denn doch keine Ruhe gelassen hat.
Lag daran, daß eine von 5 Ausgaben mit SPIOUT scheinbar auf Beendigung des Pulses gewartet hat. Das führte dann zu ungleichmäßigen Zeitabständen bei der gemultiplexten Ziffernausgabe. Mir ist noch nicht klar wie das sein konnte.
Hab das Timing entzerrt und die Anzeige ist jetzt ganz sauber! Lasse nun auch keine anderen Aufgaben mehr vom Interrupt unterbrechen
und hab alles überarbeitet und kommentiert.
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 µs an. Bereich 0,720ms bis 2,304ms in 16µs steps
'Version ohne flimmerndes Display :-)
'#######################################################
$regfile = "attiny45.dat"
$eepleave
$framesize = 32 'default?
$swstack = 32 'default?
$hwstack = 48 '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 Byte
Dim Displaydigit(10) 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
'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
X = 0 'Initialisierung von Zählvariablen
Y = 0 'Initialisierung von Zählvariablen
Z = 1 'Initialisierung von Zählvariablen
Config Portb.4 = Output 'PB4 as output, Servosignal
Gtccr = Gtccr Or &B01100000 'set PWM1B & OC1B (PB4) to clear on compare
Ocr1a = 160 'timing for int OC1A behind pulse (> max ocr1b)
Ocr1b = 0 'if OCR1B = 0 -> Pin OC1B = low in PWM mode
Ocr1c = 249 'set pwm frq. (8Mhz / 128 / (249 + 1) = 250 Hz)
Tccr1 = Tccr1 Or &B00001000 'set prescaler (128) switches timer on
On Oc1a Isr_set_ocr1b 'execute ISR on Timer 1 Comparematch A
Enable Oc1a
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 Adc_channel As Byte
Adc_channel = 3 'ADC3 (at Pin PB3)
Enable Interrupts
Do
Loop
End
'ISR wird angsprungen on Timer1 Compare Match A
'Der Zeitpunkt (Ocr1a = 160) liegt "oberhalb" des Pulses von OCR1B <= 143
'damit beeinflussen sich Ziffernausgabe und Pulserzeugung nicht
Isr_set_ocr1b:
X = X And &B00000011 'X does not exeed the value of 3
Incr X 'set digit position
Y = Displaydigitaddress(x) + 1
Spiout Displaydigit(y) , 1 'send digit to display
If Z >= 5 Then 'make one pulse out of five isr calls
Ocr1b = Comparematchvalue_ocr1b 'put value for pulse lemgth into OCR1B
Bitwait Pinb.4 , Set 'wait until pulse starts (TCNT1 at $00)
Bitwait Pinb.4 , Reset 'wait until pulse ends (match on OCR1B)
Ocr1b = 0 'keep PINB.4 LOW
Z = 1
Else 'if no pulse do all other tasks
Incr Z
Adc_readout = Getadc(adc_channel) 'read ADC
If Adc_readout < 10 Then 'trim small and large ADC values
Adc_readout = 10
Elseif Adc_readout > 1000 Then
Adc_readout = 1000
End If
Adc_readout = Adc_readout / 10 'calculate units for the timer
Adc_readout = Adc_readout + 43 'calculate units for the timer
Comparematchvalue_ocr1b = Adc_readout '16µs units -1 pulsewidth
Adc_readout = Adc_readout * 16 'prepare display register
Adc_readout = Adc_readout + 10016 'prepare display register
Adc_str = Str(adc_readout) 'prepare display register
Char = Mid(adc_str , 2 , 1) 'prepare display register
Displaydigitaddress(1) = Val(char) 'prepare display register
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) 'prepare display register
End If
Return
Entschuldigung wg. Mischmasch Deutsch-Englisch bei den Comments - Das Datenblatt macht einen komplett konfus 
Gruß
Searcher
Lesezeichen