Forum: Mikrocontroller und Digitale Elektronik PIC LCD Ausgabe von Strings


von R. S. (frederenke)


Lesenswert?

Hallo,
ich habe ein Problem mit einem LCD. Es ist ein zweizeiliges mit jeweils 
8 Stellen pro Zeile mit Hitachi hd44780 Controller. Ich betreibe dies im 
4 Bit breitem Modus an PortB und PortC eines PIC 16F886. Zusätzlich habe 
ich an PortA zwei Kontroll-LED’s. Als Vorlagen dienten ein Skript von 
Sprut und ein anderes Skript zur Stringausgabe von phanderson.com. Ich 
hatte viele Probleme mit den Ports, weshalb ich die Werte zunächst in 
Shadow Registern speichere um sie dann erst gesammelt in den jeweiligen 
Port zu laden.  Dies geschieht mit den Funktionen write_porta, 
write_portb und write_portc.
Damit ich nicht jedes Mal beim Setzen von Bits in Port B die LCDE 
Leitung neu setze, ist diese einzeln an PortC.  Die Beschaltung sollte 
soweit stimmen, da ich mit einer bestimmten Variante meines Codes (der 
hier geposteten) das Display soweit ansteuern kann und es string0 in 
einer Zeile meiner Wahl ausgibt. Füge ich jedoch neue Programmzeilen 
hinzu (zum Beispiel das im Moment auskommentierte Programm; 
beliebiges_programm) oder möchte ich einen anderen als String 0 
ausgeben, so funktioniert mein Skript nicht mehr.
Woran liegt das?
Ich könnte vermuten, dass es mit der Programmspeicherorganisation 
zusammenhängt. Ein Teil des phanderson Skriptes war auf der zweiten 
Seite des Programmspeichers abgelegt. Ich habe diese drei Zeilen aber 
deaktiviert, da es mit diesen Zeilen überhaupt nicht lief.
Bei Bedarf kann ich noch die Schaltung nachreichen.
1
  list    p=16f886  ; list directive to define processor
2
  #include  <p16f886.inc>  ; processor specific variable definitions
3
4
   __CONFIG    _CONFIG1, _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _BOR_OFF & _CPD_OFF & _CP_OFF & _MCLRE_ON &  _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT
5
   __CONFIG    _CONFIG2, _WRT_OFF & _BOR21V
6
            
7
8
9
10
;***** VARIABLE DEFINITIONS ------
11
w_temp    EQU  0x7D    ; variable used for context saving
12
status_temp  EQU  0x7E    ; variable used for context saving
13
pclath_temp  EQU  0x7F    ; variable used for context saving    
14
15
16
w_copy    Equ  0x20
17
s_copy    Equ  0x21
18
LcdDaten    Equ  0x22
19
LcdStatus   Equ  0x23
20
loops    EQU  0x24
21
loops2    EQU  0x25
22
PROGRAM_SEL  EQU  0x26
23
TIMER_REG  EQU 0x27
24
SHUTTER_CNT  EQU 0x28
25
CHAR    EQU 0x29                                                      
26
LCDTmp    equ 0x2A
27
PORTB_SHDW   equ 0x2B
28
PORTC_SHDW   equ 0x2C
29
LETTER    equ  0x2D
30
OutTextNo  equ  0x2E
31
STR_NUM    EQU  0x2F
32
INDEX    equ  0x30
33
PORTA_SHDW  equ  0x31
34
  
35
  ORG     0000h             ; processor reset vector
36
  goto  Init
37
38
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
39
  ORG     0004h             ; interrupt vector location
40
41
  movwf   w_temp            ; save off current W register contents
42
  movf  STATUS,w          ; move status register into W register
43
  movwf  status_temp       ; save off contents of STATUS register
44
  movf  PCLATH,w      ; move pclath register into w register
45
  movwf  pclath_temp      ; save off contents of PCLATH register
46
47
  movf  pclath_temp,w    ; retrieve copy of PCLATH register
48
  movwf  PCLATH        ; restore pre-isr PCLATH register contents
49
  movf    status_temp,w     ; retrieve copy of STATUS register
50
  movwf  STATUS            ; restore pre-isr STATUS register contents
51
  swapf   w_temp,f
52
  swapf   w_temp,w          ; restore pre-isr W register contents
53
  retfie                    ; return from interrupt
54
55
; Constanten festlegen
56
Ini_con Equ  B'00000000'  ; TMR0 -> Intetupt disable
57
Ini_opt  Equ  B'00000010'  ; pull-up
58
59
  #define LCD_D4_SHDW  PORTB_SHDW, 4
60
  #define LCD_D5_SHDW  PORTB_SHDW, 5  ; 4 data lines
61
  #define LCD_D6_SHDW  PORTB_SHDW, 6
62
  #define LCD_D7_SHDW  PORTB_SHDW, 7
63
  #define  LCD_RS_SHDW  PORTB_SHDW, 1  ; 0 = Command, 1 = Data
64
  #define  LCD_RW_SHDW  PORTB_SHDW, 2  ; 0 = Command, 1 = Data
65
  #define LCD_E_SHDW  PORTC_SHDW, 7  ; 1 to send data
66
67
write_porta
68
    movwf  w_temp
69
    movf  PORTA_SHDW,0
70
    movwf  PORTA
71
    RETLW  w_temp
72
write_portb
73
    movwf  w_temp
74
    movf  PORTB_SHDW,0
75
    movwf  PORTB
76
    RETLW  w_temp
77
write_portc
78
    movwf  w_temp
79
    movf  PORTC_SHDW,0
80
    movwf  PORTC
81
    RETLW  w_temp
82
83
;********************************************************
84
; Das Programm beginnt mit der Initialisierung
85
86
Init  
87
  bsf     STATUS, RP0  ; Bank 1
88
  movlw  B'00000000'  ; Ports a,b,c outputs
89
  movwf  TRISB
90
  movwf  TRISC    
91
  movwf  TRISA
92
  bcf     STATUS, RP0  ; Bank 0  
93
  clrf  PORTB_SHDW    
94
  clrf  PORTC_SHDW  
95
  call write_portb
96
  call write_portc  
97
  clrf  PORTA_SHDW  
98
  call write_porta      
99
  movlw   Ini_con       ; Interupt disable
100
  movwf   INTCON   
101
102
  call  InitLCD    ; Display initialisieren
103
104
Main  
105
    movlw  .250
106
      CALL   WAIT
107
      BSF    PORTA_SHDW,1
108
      call  write_porta
109
      CALL   WAIT
110
      CALL   WAIT
111
      CALL   WAIT
112
      CALL   WAIT
113
      CALL   WAIT
114
      
115
      movlw  0x01      ;Display löschen
116
      call  OutLcdControl
117
118
      BSF    PORTA_SHDW,2
119
      call  write_porta
120
  call line1
121
  MOVLW 0    ; display specific string
122
  MOVWF STR_NUM
123
  CALL OUT_STRING
124
Here GOTO Here
125
126
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
127
WAIT
128
top      movlw   .110           ; timing adjustment variable (1ms)
129
         movwf   loops2
130
top2     nop                    ; sit and wait
131
         nop
132
         nop
133
         nop
134
         nop
135
         nop
136
         decfsz  loops2, F      ; inner loops complete?
137
         goto    top2           ; no, go again
138
                                ;
139
         decfsz  loops, F       ; outer loops complete?
140
         goto    top            ; no, go again
141
         retlw   0              ; yes, return from subWAIT
142
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
143
WAIT1000
144
  movlw  D'250'    ; 250 ms Pause nach dem Einschalten
145
  movwf  loops
146
  call  WAIT
147
  call  WAIT
148
  call  WAIT
149
  call  WAIT
150
  return
151
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
152
WAIT3000
153
  call  WAIT1000
154
  call  WAIT1000
155
  call  WAIT1000
156
  return
157
158
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
159
line1
160
  movwf  w_temp
161
  movlw  0x02      ;Zeile1
162
  call  OutLcdControl
163
  retlw  w_temp
164
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
165
line2
166
  movwf  w_temp
167
  movlw  0xC0      ;Zeile2
168
  call  OutLcdControl
169
  retlw  w_temp
170
;**********************************************************  
171
; Initialisierung des LCD-Displays
172
173
InitLCD
174
  movlw  D'255'    ; 250 ms Pause nach dem Einschalten
175
  movwf  loops  
176
  call  WAIT    
177
  movlw  B'00110000'  ; 1
178
  movwf  PORTB_SHDW
179
  call   write_portb
180
181
  bsf  LCD_E_SHDW
182
  call write_portc
183
  nop  
184
  bcf  LCD_E_SHDW
185
  call write_portc
186
187
188
  movlw  D'50'    ; 50 ms Pause
189
  movwf  loops
190
  call  WAIT
191
  
192
  movlw  B'00110000'  ; 2
193
  call  Control8Bit
194
195
196
  movlw  B'00110000'  ; 3
197
  call   Control8Bit
198
199
200
  movlw  B'00100000'  ; 4
201
  call   Control8Bit
202
203
204
  movlw  B'00000001'  ; löschen und cusor home
205
  call  OutLcdControl  
206
207
208
  movlw  B'00101000'  ; 5 function set, 4-bit  2-zeilig,  5x7
209
  call  OutLcdControl  
210
211
212
  movlw  B'00001000'  ; 6 display off
213
  call  OutLcdControl
214
215
216
  movlw  B'00000110'  ; 7 entry mode, increment, disable display-shift
217
  call  OutLcdControl
218
219
220
  movlw  B'00000011'  ; 8 cursor home, cursor home
221
  call  OutLcdControl
222
223
  movlw  B'00001111'  ; 9 display on
224
  call  OutLcdControl
225
226
  return
227
228
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
229
; ein Steuerbyte 8-bittig übertragen
230
Control8Bit
231
  movwf  PORTB_SHDW
232
  call write_portb
233
  bsf  LCD_E_SHDW
234
  call write_portc
235
  nop
236
  bcf  LCD_E_SHDW
237
  call write_portc
238
  movlw  D'10'
239
  movwf  loops
240
  call   WAIT
241
  return
242
243
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
244
; darauf warten, daß das Display bereit zur Datenannahme ist
245
LcdBusy
246
    bsf     STATUS, RP0  ; make Port B4..7 input
247
  movlw  B'11110000'
248
  iorwf   TRISB, f 
249
    bcf     STATUS, RP0
250
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
251
BusyLoop     
252
  bcf  LCD_RS_SHDW
253
  bsf  LCD_RW_SHDW  ; Lesen
254
  call write_portb
255
  bsf  LCD_E_SHDW
256
  call write_portc
257
  nop
258
  movf  PORTB, w
259
  movwf  LcdStatus
260
  bcf  LCD_E_SHDW
261
  call write_portc
262
  nop
263
  bsf  LCD_E_SHDW  ; Enable
264
  call write_portc
265
  nop
266
  bcf  LCD_E_SHDW
267
  call write_portc
268
  btfsc  LcdStatus, 7  ; teste bit 7
269
  goto  BusyLoop
270
  bcf  LCD_E_SHDW
271
  call write_portc
272
    bsf     STATUS, RP0  ; make Port B4..7 output
273
  movlw  B'00001111'
274
  andwf   TRISB, f    
275
    bcf     STATUS, RP0
276
  return  
277
278
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
279
; ein Byte mit Steuerdaten von LcdDaten zum Display übertragen
280
OutLcdControl
281
  movwf  LcdDaten
282
  call  LcdBusy
283
  movf  LcdDaten, w
284
  andlw  H'F0'
285
  movwf  PORTB_SHDW
286
  call write_portb    ; Hi-teil Daten schreiben
287
  bsf  LCD_E_SHDW
288
  call write_portc
289
  nop
290
  bcf  LCD_E_SHDW
291
  call write_portc  ; Disable LcdBus
292
  swapf  LcdDaten, w
293
  andlw  H'F0'
294
  movwf  PORTB_SHDW
295
  call write_portb    ; Lo-teil Daten schreiben
296
  bsf  LCD_E_SHDW
297
  call write_portc
298
  nop
299
  bcf  LCD_E_SHDW
300
  call write_portc  ; Disable LcdBus
301
  return
302
303
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
304
; ein Datenbyte von LCDDaten zum Display übertragen
305
OutLcdDaten
306
  movwf  LcdDaten
307
  call  LcdBusy
308
  movf  LcdDaten, w
309
  andlw  H'F0'
310
  movwf  PORTB_SHDW
311
  call write_portb    ; Hi-teil Daten schreiben
312
  bsf  LCD_RS_SHDW      
313
  call write_portb
314
  bsf  LCD_E_SHDW
315
  call write_portc    ; Enable LcdBus
316
  nop
317
  bcf  LCD_E_SHDW
318
  call write_portc    ; Disable LcdBus  
319
  swapf  LcdDaten, w
320
  andlw  H'F0'
321
  movwf  PORTB_SHDW
322
  call write_portb    ; Lo-teil Daten schreiben
323
  bsf  LCD_RS_SHDW    
324
  call write_portb    
325
  bsf  LCD_E_SHDW
326
  call write_portc
327
  nop
328
  bcf  LCD_E_SHDW
329
  call write_portc    ; Disable LcdBus  
330
  bcf  LCD_RS_SHDW      ; Daten
331
  call write_portb    ;
332
  return
333
  ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
334
;beliebiges_programm
335
;  movwf  LcdDaten
336
;  call  LcdBusy
337
;  movf  LcdDaten, w
338
;  andlw  H'F0'
339
;  movwf  PORTB_SHDW
340
;  call write_portb    ; Hi-teil Daten schreiben
341
;  bsf  LCD_RS_SHDW      
342
;  call write_portb
343
;  bsf  LCD_E_SHDW
344
;  call write_portc    ; Enable LcdBus
345
;  nop
346
;  bcf  LCD_E_SHDW
347
;  call write_portc    ; Disable LcdBus  
348
;  swapf  LcdDaten, w
349
;  andlw  H'F0'
350
;  movwf  PORTB_SHDW
351
;  call write_portb    ; Lo-teil Daten schreiben
352
;  bsf  LCD_RS_SHDW    
353
;  call write_portb    
354
;  bsf  LCD_E_SHDW
355
;  call write_portc
356
;  nop
357
;  bcf  LCD_E_SHDW
358
;  call write_portc    ; Disable LcdBus  
359
;  bcf  LCD_RS_SHDW      ; Daten
360
;  call write_portb    ;
361
;  return
362
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
363
;ORG     0800h              ;stammt aus dem Beispielskript - habe ich deaktiviert
364
OUT_STRING
365
;  MOVLW 02H    ; set to page 2      ;stammt aus dem Beispielskript - habe ich deaktiviert
366
;  MOVWF PCLATH              ;stammt aus dem Beispielskript - habe ich deaktiviert
367
  MOVF STR_NUM, W
368
  CALL GET_STRING_ADDRESS
369
  MOVWF INDEX  ; this is the base index for the defined string
370
371
OUT_STRING_1
372
  MOVF INDEX, W    ; now output each character
373
  CALL GET_CHAR
374
  ADDLW 0  
375
  BTFSC STATUS, Z
376
  GOTO OUT_STRING_2
377
  call OutLcdDaten
378
  INCF INDEX, F
379
  GOTO OUT_STRING_1
380
OUT_STRING_2
381
  RETURN
382
383
GET_STRING_ADDRESS
384
  ADDWF PCL, F
385
  RETLW STRING0-STRING0  
386
  RETLW STRING1-STRING0
387
  RETLW STRING2-STRING0  
388
  RETLW STRING3-STRING0
389
390
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
391
GET_CHAR
392
  ADDWF PCL, F
393
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
394
STRING0
395
  DT "String 0", 0DH, 0AH, 00H
396
STRING1
397
  DT "String 1", 0DH, 0AH, 00H
398
STRING2
399
  DT "String 2", 0DH, 0AH, 00H
400
STRING3
401
  DT "String 3", 0DH, 0AH, 00H  
402
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
403
404
405
  end  
406
407
; example of preloading EEPROM locations
408
409
  ORG  0x2100
410
  DE  5, 4, 3, 2, 1
411
412
  END                       ; directive 'end of program'

von Kein Name (Gast)


Lesenswert?

Wenn keiner dein Programm debuggen will...
Kauf dir einen Pickit3 oder China-Clone. Mit dem In-Circuit Debugger 
wird MC-Programmierung so einfach wie PC-Programmierung.
(Im 16f886 Datenblatt steht nur was von ICD, der günstige Pickit 
funktioniert auch).

von pompete (Gast)


Lesenswert?

R. S. schrieb:


> Als Vorlagen dienten ein Skript von
> Sprut

...damit hatte ich meine ersten "Gehversuche", funktioniert für den 
Anfang
prima!


> und ein anderes Skript zur Stringausgabe von phanderson.com.
...warum nicht selber geschrieben,so lernt man am besten


> Zusätzlich habe
> ich an PortA zwei Kontroll-LED’s

...prima,für was nutzt Du diese?


> Ich hatte viele Probleme mit den Ports, weshalb ich die Werte zunächst
> in Shadow Registern speichere

...hmm,kann man machen,aber ein Sinn sehe ich nicht wirklich? wo lagen 
die Probleme?


> Dies geschieht mit den Funktionen write_porta,
> write_portb und write_portc.
> Damit ich nicht jedes Mal beim Setzen von Bits in Port B die LCDE
> Leitung neu setze, ist diese einzeln an PortC.

....3 ports zur ansteuerung eines Display ;-)..ja das kenne ich auch 
noch,
ist für den Anfang super einfach, aber versuch mal Spruts Beispiel auf 
ein Port umzuschreiben.


> Die Beschaltung sollte
> soweit stimmen, da ich mit einer bestimmten Variante meines Codes (der
> hier geposteten) das Display soweit ansteuern kann und es string0 in
> einer Zeile meiner Wahl ausgibt. Füge ich jedoch neue Programmzeilen
> hinzu (zum Beispiel das im Moment auskommentierte Programm;
> beliebiges_programm) oder möchte ich einen anderen als String 0
> ausgeben, so funktioniert mein Skript nicht mehr.
> Woran liegt das?

...wie macht es sich bemerkbar?
Hängt Dein Programm irgendwo fest,oder läuft Dein Controller Amok?
Hier bieten sich deine LEDs als Indikator an, wenn man sie entsprechend
in den betreffenden Programmteilen einbaut.
Vielleicht schreibt Deine Routine den zweiten String nur ausserhalb des 
sichtbaren Bereiches in den Ram des Displays?...hab jetzt nicht 
nachgeschaut ob du den Kursor vor dem neuchschreiben auf Anfang gesetzt 
hast....


> Ich könnte vermuten, dass es mit der Programmspeicherorganisation
> zusammenhängt. Ein Teil des phanderson Skriptes war auf der zweiten
> Seite des Programmspeichers abgelegt. Ich habe diese drei Zeilen aber
> deaktiviert, da es mit diesen Zeilen überhaupt nicht lief.

...wie gesagt, investiere die Zeit, mach Dir Gedanken und versuche sowas 
selber zu schreiben, der Lerneffekt ist unglaublich und wird Dir in 
Zukunft
bei neuen Problemstellungen doppelt und dreifach Zeit zurück geben ;-)

von Peter D. (peda)


Lesenswert?

R. S. schrieb:
> Füge ich jedoch neue Programmzeilen
> hinzu (zum Beispiel das im Moment auskommentierte Programm;
> beliebiges_programm) oder möchte ich einen anderen als String 0
> ausgeben, so funktioniert mein Skript nicht mehr.

Vermutlich überschreitet dann Dein Programm die 256 Word Größe.
Im Unterschied zu vielen anderen MCs ist beim PIC der Flash und der SRAM 
in 256 Byte Stücke segmentiert. Ein Zugriff ist daher nur in der 
ausgewählten Page bzw. Bank möglich.

Will man einen Jump oder Call in eine andere Page machen, muß man 
deshalb vor jedem Call das PCLATH berechnen.
Die DT-Anweisung ist eigentlich ein RETLW und benötigt auch einen CALL, 
d.h. vor jedem Byte lesen muß PCLATH berechnet werden.


R. S. schrieb:
> Ich
> hatte viele Probleme mit den Ports, weshalb ich die Werte zunächst in
> Shadow Registern speichere um sie dann erst gesammelt in den jeweiligen
> Port zu laden.

Ja, die älteren PICs ohne Latch spielen einem lustige Streiche ohne 
Schattenregister.
Man sollte modernere nehmen, die ein Ausgangslatch haben. Da kann man 
dann gefahrlos einzelne Bits setzen oder löschen ohne die anderen zu 
beeinflussen.


Peter

von pompete (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Ja, die älteren PICs ohne Latch spielen einem lustige Streiche ohne
> Schattenregister.
> Man sollte modernere nehmen, die ein Ausgangslatch haben. Da kann man
> dann gefahrlos einzelne Bits setzen oder löschen ohne die anderen zu
> beeinflussen.

..cool,der Peter hat die passende Antwort immer zur Hand, jetzt dämmerts 
bei mir auch wieder.
Ist schon eine Ewigkeit her, als ich mit den kleineren Pics meine ersten 
Programmierversuche machte.
Die Speicheraufteilung in Pages und die damit verbundenen 
Bankumschaltungen bis hin zu der Latch-geschichte...auweia!
Man ist mittlerweile sehr verwöhnt ;-)

von R. S. (frederenke)


Lesenswert?

Hallo,
zunächst erstmal vielen Dank für eure Zeit!

pompete schrieb:
> ...warum nicht selber geschrieben,so lernt man am besten
Hatte selber schon ein paar Sachen geschrieben. Einzelne Buchstaben 
konnte ich problemlos ausgeben. Nur bei ganzen Wörtern wurde der 
Quelltext elendig lang, weshalb ich diese Vorlage nahm.


pompete schrieb:
> ...prima,für was nutzt Du diese?
Die habe ich immer genutzt um zu sehen wo sich mein Programm aufhängt.

pompete schrieb:
> ...hmm,kann man machen,aber ein Sinn sehe ich nicht wirklich? wo lagen
> die Probleme?
Das Problem bestand darin, dass sobald ich Bits an den Ports geändert 
habe sich alle anderen mit änderten. Scheint auch ein gängiges Prolem zu 
sein, die Lösung hatte ich irgendwo im Netz gefunden

pompete schrieb:
> ....3 ports zur ansteuerung eines Display ;-)..ja das kenne ich auch
> noch,
> ist für den Anfang super einfach, aber versuch mal Spruts Beispiel auf
> ein Port umzuschreiben.
Eigentlich 2 Ports - den dritten werde ich für was anderes gebrauchen, 
wenn ich die LED nicht mehr benötige. Weniger als 2 Ports gingen wegen 
des oben genannten Problems leider nicht.

pompete schrieb:
> ...wie macht es sich bemerkbar?
> Hängt Dein Programm irgendwo fest,oder läuft Dein Controller Amok?
> Hier bieten sich deine LEDs als Indikator an, wenn man sie entsprechend
> in den betreffenden Programmteilen einbaut.
Probleme sind die folgenden:
-Aktiviere ich das nutzlose Zwischenprogramm, so wird nix mehr am 
Display ausgegebn
-Will ich einen anderen als String 0 ausgeben, so wird "Strin" 
ausgegeben und das Display gelöscht, wieder "Strin" ausgegeben usw.
-
pompete schrieb:
> Vielleicht schreibt Deine Routine den zweiten String nur ausserhalb des
> sichtbaren Bereiches in den Ram des Displays?...hab jetzt nicht
> nachgeschaut ob du den Kursor vor dem neuchschreiben auf Anfang gesetzt
> hast....
Guter Tipp aber die LCD Adressen stimmen soweit, da ich String 0 ja an 
einer beliebigen Stelle ausgeben lassen kann.


> ...wie gesagt, investiere die Zeit, mach Dir Gedanken und versuche sowas
> selber zu schreiben, der Lerneffekt ist unglaublich und wird Dir in
> Zukunft
> bei neuen Problemstellungen doppelt und dreifach Zeit zurück geben ;-)

Da hast du Zweifelsfrei recht, ich bin nach ca. 40 Arbeitsstunden aber 
mit meinem Latein am Ende....



Peter Dannegger schrieb:
> Vermutlich überschreitet dann Dein Programm die 256 Word Größe.
> Im Unterschied zu vielen anderen MCs ist beim PIC der Flash und der SRAM
> in 256 Byte Stücke segmentiert. Ein Zugriff ist daher nur in der
> ausgewählten Page bzw. Bank möglich.
>
> Will man einen Jump oder Call in eine andere Page machen, muß man
> deshalb vor jedem Call das PCLATH berechnen.
> Die DT-Anweisung ist eigentlich ein RETLW und benötigt auch einen CALL,
> d.h. vor jedem Byte lesen muß PCLATH berechnet werden.

Das mit dem PCLATH habe ich ganz grob verstanden, aber soweit ich das 
überblicke ist mein Programm nicht so groß. Wenn ich mir die HEX Datei 
mit USBurn anzeigen lasse befinden sich nur im ersten Block blau 
markierte Stellen.

Peter Dannegger schrieb:
> Ja, die älteren PICs ohne Latch spielen einem lustige Streiche ohne
> Schattenregister.
> Man sollte modernere nehmen, die ein Ausgangslatch haben. Da kann man
> dann gefahrlos einzelne Bits setzen oder löschen ohne die anderen zu
> beeinflussen.

Welche PICs besitzen diese Funktion? Ab 18F ?



Übrigens habe ich nun auch Probleme einen 16f628a zu beschreiben. Ich 
vermute, dass es mit meinem Brenner8 zusammenhängt. Ich werde mir nun 
das PICKIT3 zulegen. Ich habe das PICKIT3 bei verschiedenen Anbietern 
mit Bildern gesehen. Ab und zu waren "Adapterplatinen" dabei, welche an 
den roten PICKIT angeschlossen werden und wo sich der zu beschreibende 
PIC in einen Nullkraftsockel einstecken lässt. Ist das der 
Standardlieferumfang?
Ich hätte gerne diese Platinen, damit ich direkt starten kann wenn das 
PICKIT da ist. Wenn ich das richtig überblicke ist bei manchen Paketen 
eine Testplatine mit einem Pic18f dabei. welchen Zweck hat diese?

Bei Conrad ist es grade für 63€ im Angebot. Nur weiß ich nicht ob die 
passenden Adapter dabei sind

von Klaus (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Ja, die älteren PICs ohne Latch spielen einem lustige Streiche ohne
> Schattenregister.
> Man sollte modernere nehmen, die ein Ausgangslatch haben. Da kann man
> dann gefahrlos einzelne Bits setzen oder löschen ohne die anderen zu
> beeinflussen.

So ist das nicht ganz richtig. Es gibt Probleme, wenn der Portpin nicht 
dem Zustand des Ausgangstreibers entspricht. Bei einem Read-Modify-Write 
Befehl wird dabei der falsche Portwert eingelesen und dann 
zurückgeschrieben. Ein solcher Zustand kann eintreten, wenn ein Bit im 
vorigen Maschinentakt geändert wurde. Wenn man zwei Bitset oder Bitclear 
Befehle auf dem gleichen Port hintereinder ausführt, kann das auftreten. 
Ein Nop dazwischen hilft.

Änliches passiert, wenn man große Kapazitäten an einem Portpin hat. 
Solange der nicht aufgeladen ist, wird auch der falsche Wert beim 
Read-Modify-Write ausgelesen und zurückgeschrieben.

Wenn man weiß, was man tut, ist das alles kein Problem.

MfG Klaus

von Klaus (Gast)


Lesenswert?

R. S. schrieb:
> Ab und zu waren "Adapterplatinen" dabei, welche an
> den roten PICKIT angeschlossen werden und wo sich der zu beschreibende
> PIC in einen Nullkraftsockel einstecken lässt.

Das hilft dir nicht beim Debuggen und da dein Code nicht funktioniert, 
brauchst du dringend einen Debugger.

MfG Klaus

von ... (Gast)


Lesenswert?

R. S. schrieb:
> Bei Bedarf kann ich noch die Schaltung nachreichen.
>
> list    p=16f886  ; list directive to define processor
>   #include  <p16f886.inc>  ; processor specific variable definitions
> ...

Erstmal wäre es ganz praktisch, Quellcode dieser Länge als Dateianhang 
anzuhängen.

von R. S. (frederenke)


Lesenswert?

Klaus schrieb:
> Ein Nop dazwischen hilft.
>
> Änliches passiert, wenn man große Kapazitäten an einem Portpin hat.
> Solange der nicht aufgeladen ist, wird auch der falsche Wert beim
> Read-Modify-Write ausgelesen und zurückgeschrieben.
>

Hallo Klaus,
das mit dem nop habe ich auch probiert hatte nicht geholfen, obwohl ich 
keine große Kapazität am Ausagang hatte - nämlich nur ein Transistor 
(BC337)

Naja mit der Shadowregisterlösung bin ich soweit zufrieden.

Aber wie habe ich das mit dem Debugger zu verstehen?
Das PICKIT3 ist doch Debugger und Programmer zugleich oder?
Zumindest dachte ich das....
Ich dachte der rote PICKIT Kasten hat einen Ausgang mit x-Pins die dann 
noch an den PIC gebracht werden müssen - hierzu dienen die Adapter.
Ist das Falsch?

von Erich (Gast)


Lesenswert?

Was du suchst als PicKit3 + Platinen ist das
"DV164131" (= PICkit 3 Debug Express).

Zusätzlich kann man kaufen die "DM164120-3" (28-Pin) und/oder "DM 
164120-4" (18-Pin).
Man kriegt 3 Platinen: eine bestückte + 2 leere.
Das ist das PicKit3 jeweils direkt anschließbar.
Der moderne 18-Pin uC ist der PIC16F1827.


Weitere Beiträge hier
Beitrag "Re: PIC Programmiereinstieg"
Autor: Erich (Gast)
Datum: 13.09.2012 11:40

und hier
Beitrag "Re: PIC Programmiereinstieg"


GOOGE:  "DV164131" microchip

Gruss

von Peter D. (peda)


Lesenswert?

R. S. schrieb:
> Wenn ich mir die HEX Datei
> mit USBurn anzeigen lasse befinden sich nur im ersten Block blau
> markierte Stellen.

Sicher, daß ein Block im Programmer auch einer Page im Code entspricht?

Schau einfach ins Assemblerlisting, ob da eine Adresse > 00FF auftaucht.
Die Strings sind schonmal 44 Words.

Wenn Du den Code angehangen hättest, könnte man leicht sehen, wieviel 
Zeilen das sind.


Peter

von Der Rächer der Transistormorde (Gast)


Lesenswert?

R. S. schrieb:
> Das PICKIT3 ist doch Debugger und Programmer zugleich oder?
> Zumindest dachte ich das....

Das Pickit ist die Verbindung zwischen deinem Prozessor und Mplab. Mplab 
ist die Toolchain von microchip in der alles drin ist was man zum 
programmieren und debuggen so bracht. Assembler,Compiler,Debugger 
Simulator etc pp. Frei zum downloaden und kostenlos.

Damit kannst du dein Programm debuggen. Es dauert aber eine gewisse Zeit 
bis man durch dieses etwas wirre Programm durchgestiegen ist.

Das PicKit 2 ist übrigens teilweise besser geeignet weil es auch mit 
anderen Compilern zusammenarbeitet und auch als Terminal dient über den 
man z.B. Texte Statis und Variablen ausgeben kann.

von Klaus (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Will man einen Jump oder Call in eine andere Page machen, muß man
> deshalb vor jedem Call das PCLATH berechnen.
> Die DT-Anweisung ist eigentlich ein RETLW und benötigt auch einen CALL,
> d.h. vor jedem Byte lesen muß PCLATH berechnet werden.

Nun, beim 16F886 ist eine Codebank 2k groß (11 Bit Adresse im 14 Bit 
Instruction Word), ist das Programm kleiner als 2k muß garnichts 
berechnet werden.

Der Rächer der Transistormorde schrieb:
> Damit kannst du dein Programm debuggen. Es dauert aber eine gewisse Zeit
> bis man durch dieses etwas wirre Programm durchgestiegen ist.

Was daran wirr sein soll, ist mir nicht klar. Es ist die Netbeans IDE. 
Nun kann man Eclipse oder Visual Studio besser finden, ist eine 
Geschmacksfrage. Aber wirr ??

MfG Klaus

von Erich (Gast)


Lesenswert?

Ergänzend zum Beitrag von vorhin hier noch folgendes (auch wenn ich dies 
neulich erst schrieb bei 
Beitrag "Re: PIC Programmiereinstieg"):

Du sparst dir viel Mühsal, wenn du gleich noch in C programmierst.
Es gibt für besagte uC keine Notwendigkeit und keinen Grund noch 
Assembler einzusetzen.
Lerne gleich in C zu programmieren -- ist sinnvoller.
Auf der CD zum "DV164131" sind 10-12 Beispiele, diese systematisch 
durcharbeiten und und bist gut aufgestellt.
Parallel dazu kannst die Aufgaben auch vom dortigen PIC18F45K20 auf den 
Chip deiner Wahl umarbeiten. Wobei der 16F1933 oder 16F1936 die neueren 
28-Pin Typen sind.
Gerade mit den (kleinen) Pic16 ist Assembler ein Bankswitching und 
"retlw" Kauderwelch ohne Ende. Sinnlos.

Und nochwas, aber das schrieb auch schon einer: lange Listings hier 
einstellen, das schreckt eher ab. Dateianhang ist besser.

Gruss

von Peter D. (peda)


Lesenswert?

Klaus schrieb:
> Nun, beim 16F886 ist eine Codebank 2k groß (11 Bit Adresse im 14 Bit

Sorry, ich war irgendwie beim PIC12.
Die PIC unterscheiden sich ja erheblich im Core.
Die 8051 haben alle den gleichen Core. Es gab zwar Versuche, den 8051 
aufzubohren (Dallas 80C390, Intel 251, Philips MX) zu 16Bit und mehr 
Adreßraum, aber das hat gefloppt.


Peter

von Ottmar K. (wil1)


Lesenswert?

Hallo R. S. (frederenke)

Besteht Dein Problem noch?
In dem Fall kann ich Dir ein LCD-Basisprogramm in MPLAB-Assembler 
(beruht auf Sprut) zukommen lassen, welches ich mal für den 16F876 
geschrieben habe und welches auch funktioniert, bzw. worauf Due aufbauen 
kannst.
Zum 16F886 dürften wohl keine Unterschiede bestehen, welche die Funktion 
der LCD-Ausgabe gefährden könnten.

mfG Ottmar

von R. S. (frederenke)


Lesenswert?

Hallo Ottmar
gerne - kann man in dem Programm Strings angeben?
Gruß

von Ottmar K. (wil1)


Angehängte Dateien:

Lesenswert?

R. S. schrieb:
> Hallo Ottmar
> gerne - kann man in dem Programm Strings angeben?
> Gruß

zunächst "nein". Das Programm gibt lediglich diesen 2 Zeiler aus:
"LDC READY 4 YOU!. Damit weiß man aber, dass das LCD funktioniert und 
man den Fehler anderswo suchen muss.

Eine passende Routine zur Ausgabe von Strings Sub Lcd_Out (auch bei 
www.sprut.de gesehen) hänge ich dir zusätzlich an. Die Routine hatte ich 
zur Ausgabe von Menüs, Registerinhalten etc verwendet. Für lediglich 8 
Zeichen oder so ist diese Sub etwas zu ausladend geraten. Ihre Stärke 
hat sie aber bei der Ausgabe von zig Menüs oder beim Debuggen.
 Evtl. mußt Du da nochmals nachfragen, falls nicht ganz verständlich, 
ist jetzt doch etwas spät.

mfg Ottmar

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.