Автор Тема: Proteus - проблем с LCD  (Прочетена 13112 пъти)

Lampard87

  • Новодошъл
  • *****
  • Публикации: 7
    • Профил
Proteus - проблем с LCD
« -: Април 27, 2012, 09:12:58 pm »
Здравейте. Написах една програма и рекох да я симулирам на Proteus, но дисплея не показва нищо. Тъй като програмата не е никак малка, написах една елементарна, с която само да се изписва "LCD TEST" на дисплея и пак нищо. Ето я и нея:

list p=16f872
title "LCD Test"
#include <p16f872.inc>
__config _CPD_ON & _WDT_OFF & _PWRTE_ON & _XT_OSC
;*************** Дефиниране на константи и променливи ***********
w EQU 0
f EQU 1
Disp_On EQU H'0C'
Disp_Off EQU H'08'
Entry_Inc EQU H'06'
CBLOCK H'20'
Counter
LCD_Temp
BF_Temp
ENDC
;************** Дефиниране на входно-изходни изводи *************
#define RS PORTC,0
#define RW PORTC,1
#define E PORTC,2
;****************************************************************
;                     Потребителска програма
;****************************************************************
ORG H'0000' ; Вектор на НУ
goto Start
ORG H'0004' ; Вектор на прекъсване
goto Int_Service
;****************************************************************
;                      Начало на програмата
;****************************************************************
Start bcf STATUS,RP1
bsf STATUS,RP0
movlw B'00000101' ; pull-up, вътрешен такт за TMR0
movwf OPTION_REG ; такт 1:64
bcf STATUS,RP0
clrf PORTA
clrf PORTB
clrf PORTC
bsf STATUS,RP0
clrf TRISA ; RA0-RA5 - изходи
clrf TRISB ; RB0-RB7 - изходи
clrf TRISC ; RC0-RC7 - изходи
bcf STATUS,RP0
goto main
;****************************************************************
;                   Използвани подпрограми
;****************************************************************
;------------- Програма за обслужване на прекъсванията ----------
Int_Service
return
;------------- Начална инициализация на LCD модула --------------
Init_LCD
call Wait1 ; Изчакай 16ms
movlw B'00110000'
movwf PORTB
bsf E
bcf E
call Wait2 ; Изчакай 5ms
movlw B'00111000'
movwf PORTB
bsf E
bcf E
movlw Disp_Off
call Send_Command
movlw Disp_On
call Send_Command
movlw Entry_Inc
call Send_Command
return
;------------- Изпращане на команда към LCD дисплея -------------
Send_Command
movwf LCD_Temp
call Check_BF
movf LCD_Temp,w
movwf PORTB
bcf RW
bcf RS
bsf E
bcf E
return
;----------------- Изпращане на кода на символа -----------------
Send_Char
movwf LCD_Temp
call Check_BF
movf LCD_Temp,w
movwf PORTB
bcf RW
bsf RS
bsf E
bcf E
return
;------------------- Проверка на флаг "Зает" --------------------
Check_BF
bsf STATUS,RP0
movlw H'FF'
movwf TRISB
bcf STATUS,RP0
bcf RS
bsf RW
bsf E
bcf E
movf PORTB,w
movwf BF_Temp
btfsc BF_Temp,7
goto Check_BF
bcf RW
bsf STATUS,RP0
clrf TRISB
bcf STATUS,RP0
return
;----------------- Подпрограми за времезадръжка -----------------
Wait1 clrf TMR0 ; Времезадръжка 16ms
bcf INTCON,T0IF
Loop1 btfss INTCON,T0IF
goto Loop1
return
Wait2 movlw D'176' ; Времезадръжка 5ms
movwf TMR0
bcf INTCON,T0IF
Loop2 btfss INTCON,T0IF
goto Loop2
return
Wait3 movlw D'128' ; Времезадръжка 2s
movwf Counter
clrf TMR0
Again3 bcf INTCON,T0IF
Loop3 btfss INTCON,T0IF
goto Loop3
decfsz Counter,f
goto Again3
return
;****************************************************************
;                      Главна програма
;****************************************************************
main call Init_LCD
movlw H'84'
call Send_Command
movlw 'L'
call Send_Char
movlw 'C'
call Send_Char
movlw 'D'
call Send_Char
movlw H'C0'
call Send_Command
movlw 'T'
call Send_Char
movlw 'E'
call Send_Char
movlw 'S'
call Send_Char
movlw 'T'
call Send_Char
call Wait3 ; Изчакай 2s
goto main
END


Ето и снимки на симулацията:
http://dox.bg/files/dw?a=9ebe23144f
http://dox.bg/files/dw?a=13ce430d8f

Задал съм честотата на микроконтролера при симулацията. Някакви идеи къде бъркам ?

hunter

  • Направо Робот! :)
  • *****
  • Публикации: 638
    • Профил
Proteus - проблем с LCD
« Отговор #1 -: Април 28, 2012, 04:21:32 pm »
Здрасти програмката ти маи е мешина скара  :D Имаш много времезадръжки а само един Counter за Wait e Counter за Wait1 Counter1 и тн. Не може да ползваш един Counter за всички. Друго къде в началото на програмата си задал кои вход-изход е аналогов и кой дигитален. То не е само да напишеш Clrf PORTA,B,C и тн. Много постно обслужване на прекъсване даже нулево. За мен програмата е много зле на пръв поглед още. Нека и колегите да кажат но моето мнение е това. И банките не си избрал правилно, имаш 4 банки избират се не само с 5 и 6 бит на STATUS RPO и RP1. Datasheet-a май не си го гледал.
Цвятко Цветков/ Бургас

http://www.youtube.com/watch?v=I1y67hzRWQY&feature=related

Lampard87

  • Новодошъл
  • *****
  • Публикации: 7
    • Профил
Proteus - проблем с LCD
« Отговор #2 -: Април 28, 2012, 05:13:04 pm »
Не мисля, че е проблем да използвам един регистър - Counter, тъй като преди употребата му го зареждам със съответната стойност.
Програмката е възможно да е поомешена, защото набързо я орязах от първоначалната ми, въпреки че е подобна на примера от книгата на Кенаров. Не схванах нещо за входовете/изходите. Оставих изводите от всеки порт да са изходи.
Забелязах, че има много теми в чуждестранни форуми за моя проблем, но така и не открих защо не се появяват символите на дисплея.

hunter

  • Направо Робот! :)
  • *****
  • Публикации: 638
    • Профил
Proteus - проблем с LCD
« Отговор #3 -: Април 28, 2012, 06:42:01 pm »
Е не може да режеш и да искаш да ти се даде отговор къде е грешно. Книгата е за 84А тук ти работиш с PIC който иска доста повече.
Цвятко Цветков/ Бургас

http://www.youtube.com/watch?v=I1y67hzRWQY&feature=related

hunter

  • Направо Робот! :)
  • *****
  • Публикации: 638
    • Профил
Proteus - проблем с LCD
« Отговор #4 -: Април 28, 2012, 06:50:37 pm »
Ето ти нещо резнато и от мен това съм го правил за подобен PIC сравни с твоето инициализация избор на банки и тн.


list    p=16F877A
include   <P16F877A.INC>

;FOSC = 20MHz
__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF



;********************* Дефиниране на Макроси **************************
BANK0   MACRO               ;MACRO to select data RAM bank 0
         bcf   STATUS,RP0
         bcf   STATUS,RP1
      ENDM

BANK1   MACRO               ;MACRO to select data RAM bank 1
         bsf   STATUS,RP0
         bcf   STATUS,RP1
      ENDM

BANK2   MACRO               ;MACRO to select data RAM bank 2
         bcf   STATUS,RP0
         bsf   STATUS,RP1
      ENDM

BANK3   MACRO               ;MACRO to select data RAM bank 3
         bsf   STATUS,RP0
         bsf   STATUS,RP1
      ENDM
      
LOAD_DATA_EEPROM     MACRO      ;MACRO for loading constants in internal EEPROM
                  org     0x2100
                  DATA    0x00
               ENDM      
      
;
;***EndMacros



;********************* Дефиниране на константи и променливи **************************
   W    EQU    0
   f    EQU    1
   Z    EQU    2   

CBLOCK    0x20                      ;0 RAM starts at address 20h
   Counter
   Counter1
   IPortB
   IPortB0   
   IPortB1
   IPortB2
   BlokStage
   TempCoutPortF
ENDC

CBLOCK  0x070
   Wtemp
   STATUStemp
   PCLATHtemp
   FSRtemp
ENDC

;--------------------- Дефиниране на входно-изходните портове ------------------------
;#define    SCK       PORTC,   3       ;Изход Тактова честота
;#define    SDI       PORTC,   4       ;SDI за SPI
;#define    SDO       PORTC,   5       ;SDO за SPI
#define    SS          PORTA,   5       ;SS за SPI
#define    REC       IPortB,   0       ;Бутон за запис
#define    PLAY       IPortB,   1       ;Бутон за възпроизвеждане
#define    STOP       IPortB,   2       ;Бутон за стоп
#define    SV_REC       PORTB,   3       ;Светодиод за запис
#define    SV_PLAY    PORTB,   4       ;Светодиод за възпроизвеждане
#define    SV_STOP    PORTB,   5       ;Светодиод за стоп


;***StartBlock************************************************************************
; Начало на програма
;*************************************************************************************
ORG 0x0000 ;start address = 0000h
   goto    start
;***EndBlock**************************************************************************


;***StartBlock************************************************************************
; Обработка на прекъсванията
;*************************************************************************************
ORG 0x0004 ;interrupt address = 0004h
;-----------------Блок за влизане в прекъсване -------------------
   movwf   Wtemp          ; Store W-reg
      swapf   STATUS,W       ; Swap status to be saved into W
      clrf   STATUS          ; bank 0, Clears IRP,RP1,RP0
      movwf   STATUStemp       ; Save status to bank zero STATUS_TEMP
      movf    PCLATH,W         ; pages 1, 2 and/or 3
      movwf   PCLATHtemp      ; Save PCLATH into W
      clrf    PCLATH          ; Page zero, regardless of current page
      movf    FSR,W          ; Copy FSR to W
      movwf   FSRtemp          ; Copy FSR from W to FSR_TEMP
;-----------------------------------------------------------------

   nop
   nop   
   
;-----------------Блок за излизане от прекъсване -----------------   
   clrf      STATUS         ; bank0
      movf      FSRtemp,W      ; Restore FSR register
      movwf   FSR
      movf    PCLATHtemp,W    ; Restore PCLATH
      movwf   PCLATH          ; Move W into PCLATH
      swapf   STATUStemp,W      ; Swap STATUS_TEMP register into W  (sets bank to original state)
      movwf   STATUS          ; Move W into STATUS register
      swapf   Wtemp,F          ; Swap W_TEMP
      swapf   Wtemp,W          ; Swap W_TEMP into W
      retfie                  ; end of interrupt vector
;-----------------------------------------------------------------   
   
;***EndBlock**************************************************************************


;***StartBlock************************************************************************
; Използвани подпрограми
;*************************************************************************************
;--------------- Подпрограма "Wait_Tpud" формира времезадръжка от Xms ----------------
Wait_Tpud:
   movlw    D'10'             ;Задава времето
   movwf    Counter          ;
   clrf    TMR0             ;Нулира TMR0
again:                      ;Изпълни цикъла отново
   bcf    INTCON,   T0IF       ;Нулира бит T0IF
loop1:
   btfss    INTCON,   T0IF       ;Бит T0IF=1
   goto    loop1             ;Не,повтори отново
   decfsz    Counter,f          ;
   goto    again             ;Изпълни цикъла отново
   return                   ;Връща към главна програма докадето е прекратена
;---endSub
start:
   BANK1                   ;Избор на Банка 1
   
   movlw    b'10010110'       ;nternal instruction cycle clock (CLKO), Prescaler is assigned to the Timer0 module,TMR0 Rate 1 : 128
   movwf    OPTION_REG          ;
   
   movlw    b'00000111'       ;Настроиване на компараторния блок - всички компаратори изключени
   movwf    CMCON             ;   
   
   movlw    b'00000110'       ;Настроиване на изходите само като цифрови
   movwf    ADCON1             ;
   
   movlw    b'11011111'       ;RA0-RA4-Входове, RA5-Изход за SS(SLAVE Select)  
   movwf    TRISA             ;
   
   movlw    b'00000111'       ;RB0-RB2-Входове, RB3-RB7-Изход
   movwf    TRISB             ;
   
   bcf    TRISC,   3          ;SCK изводи на SPI.
   bsf    TRISC,   4          ;SDI
   bcf    TRISC,   5          ;SDO
   
   movlw    b'01000000'       ;инициализация на SPI (SSPSTAT) - (CKE)Transmit occurs on transition from active to Idle clock state
   movwf    SSPSTAT          ;
   
   BANK0                   ;Избор на Банка 0
   
   bsf    SS                ;Забрана на SS(PORTA,0)
   clrf    PORTB             ;Нулиране на PORTB
   clrf    PORTC             ;Нулиране на PORTC    
   
   movlw    b'00100010'       ;инициализация на SPI (SSPCON) -  (CKP)Idle state for clock is a low level, SPI Master mode, clock = FOSC/64 (312,5KHz)
   movwf    SSPCON             ;
   
   movlw    b'00000111'
   movwf    IPortB   
   movwf    IPortB0
   movwf    IPortB2
   movlw    .200            
   movwf   TempCoutPortF   
   clrf   BlokStage
   goto    main
   nop
;***EndBlock**************************************************************************
Цвятко Цветков/ Бургас

http://www.youtube.com/watch?v=I1y67hzRWQY&feature=related

CarBeta5

  • Вече знае какво е робот!
  • *****
  • Публикации: 81
    • Профил
Proteus - проблем с LCD
« Отговор #5 -: Април 28, 2012, 09:53:35 pm »
Проблема ти е в преписването. Като сменяш контролера се променя програмата според спецификацията на новия контролер, съответно и _CONFIG.

В старт програмата като минеш в банка 1 добави:
    MOVLW  H'06'
     MOVWF  ADCON1


 - от прекъсване се излиза с RETFIE не с RETURN !
 - при инициализацията на дисплея първо се чака 40 милисекунди, не 16
 - започваш с команда 30, но не знам как си свързал порта с дисплея та не мога да го коментирам това преди да видя схемата
 - после пак има пауза и избираш режим, ти гледам че пердашиш на 8 бита
 - никъде не виждам адрес за изписване на каквото пишеш там, с H'01' се нулира РАМ'а, иначе първоначален адрес е каквото му е кеф след стартирането

На пръв поглед това виждам като грешки.

Lampard87

  • Новодошъл
  • *****
  • Публикации: 7
    • Профил
Proteus - проблем с LCD
« Отговор #6 -: Април 29, 2012, 03:36:21 pm »
Подкарах дисплея, но странното е че първия символ от първия ред липсва - в случая L, независимо на коя позиция ще го разположа. Защо се получи така?

Това са снимки от симулацията:



А това е кода:

list p=16f870
title "LCD Test"
#include <p16f870.inc>
__config _CPD_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _LVP_OFF & _CPD_OFF
;*************** Дефиниране на константи и променливи ***********
w EQU 0
f EQU 1
Disp_On EQU H'0C'
Disp_Off EQU H'08'
Entry_Inc EQU H'06'
CBLOCK H'20'
Counter
LCD_Temp
BF_Temp
ENDC
;************** Дефиниране на входно-изходни изводи *************
#define RS PORTC,0
#define RW PORTC,1
#define E PORTC,2
;****************************************************************
;                     Потребителска програма
;****************************************************************
ORG H'0000' ; Вектор на НУ
goto Start
ORG H'0004' ; Вектор на прекъсване
goto Int_Service
;****************************************************************
;                      Начало на програмата
;****************************************************************
Start bcf STATUS,RP1
bsf STATUS,RP0
movlw B'10000101' ; вътрешен такт за TMR0
movwf OPTION_REG ; такт 1:64
bcf STATUS,RP1
bcf STATUS,RP0
clrf PORTA
clrf PORTB
clrf PORTC
bcf STATUS,RP1
bsf STATUS,RP0
movlw H'06'
movwf ADCON1
clrf TRISA ; RA0-RA5 - изходи
clrf TRISB ; RB0-RB7 - изходи
clrf TRISC ; RC0-RC7 - изходи
bcf STATUS,RP1
bcf STATUS,RP0
goto main
;****************************************************************
;                   Използвани подпрограми
;****************************************************************
;------------- Програма за обслужване на прекъсванията ----------
Int_Service
retfie
;------------- Начална инициализация на LCD модула --------------
Init_LCD
call Wait1 ; Изчакай 16ms
movlw B'00110000'
movwf PORTB
bsf E
bcf E
call Wait2 ; Изчакай 5ms
movlw B'00111000'
movwf PORTB
bsf E
bcf E
movlw Disp_Off
call Send_Command
movlw Disp_On
call Send_Command
movlw Entry_Inc
call Send_Command
return
;------------- Изпращане на команда към LCD дисплея -------------
Send_Command
movwf LCD_Temp
call Check_BF
movf LCD_Temp,w
movwf PORTB
bcf RW
bcf RS
bsf E
bcf E
return
;----------------- Изпращане на кода на символа -----------------
Send_Char
movwf LCD_Temp
call Check_BF
movf LCD_Temp,w
movwf PORTB
bcf RW
bsf RS
bsf E
bcf E
return
;------------------- Проверка на флаг "Зает" --------------------
Check_BF
bcf STATUS,RP1
bsf STATUS,RP0
movlw H'FF'
movwf TRISB
bcf STATUS,RP1
bcf STATUS,RP0
bcf RS
bsf RW
bsf E
bcf E
movf PORTB,w
movwf BF_Temp
btfsc BF_Temp,7
goto Check_BF
bcf RW
bcf STATUS,RP1
bsf STATUS,RP0
clrf TRISB
bcf STATUS,RP1
bcf STATUS,RP0
return
;----------------- Подпрограми за времезадръжка -----------------
Wait1 clrf TMR0 ; Времезадръжка 16ms
bcf INTCON,T0IF
Loop1 btfss INTCON,T0IF
goto Loop1
return
Wait2 movlw D'176' ; Времезадръжка 5ms
movwf TMR0
bcf INTCON,T0IF
Loop2 btfss INTCON,T0IF
goto Loop2
return
Wait3 movlw D'128' ; Времезадръжка 2s
movwf Counter
clrf TMR0
Again3 bcf INTCON,T0IF
Loop3 btfss INTCON,T0IF
goto Loop3
decfsz Counter,f
goto Again3
return
;****************************************************************
;                      Главна програма
;****************************************************************
main call Init_LCD
Send_Message
movlw H'80'
call Send_Command
movlw 'L'
call Send_Char
movlw 'C'
call Send_Char
movlw 'D'
call Send_Char
Second_Line
movlw H'C0'
call Send_Command
movlw 'T'
call Send_Char
movlw 'E'
call Send_Char
movlw 'S'
call Send_Char
movlw 'T'
call Send_Char
Stop_Send
nop
goto Stop_Send
END


Edit: Изтървана буква.

CarBeta5

  • Вече знае какво е робот!
  • *****
  • Публикации: 81
    • Профил
Proteus - проблем с LCD
« Отговор #7 -: Април 29, 2012, 09:48:24 pm »
По принцип в симулациите се спазват стриктно максималните времена. Всяка инструкция отнема определено време.
Ако му сложиш по 4 или 5 NOP'a преди return в подпрограмите Send_Command и Send_Char ще се оправи симулацията.
На живо ще тръгне и така както е сега.

Lampard87

  • Новодошъл
  • *****
  • Публикации: 7
    • Профил
Proteus - проблем с LCD
« Отговор #8 -: Април 30, 2012, 08:12:16 am »
Пробвах сега с 4-битов интерфейс, но не тръгва - пак е празен дисплея. Къде пак бъркам ?

Направих следните промени:
- При инциализацията на дисплея изпращам команда 0010000 за 4-битов интерфейс, както и 00101000 за двуредов режим 5х8 точки. Изглежда по този начин:

;------------- Начална инициализация на LCD модула --------------
Init_LCD
call Wait1 ; Изчакай 16ms
movlw B'00110000'
movwf PORTB
bsf E
bcf E
call Wait2 ; Изчакай 5ms
movlw B'00100000'
movwf PORTB
bsf E
bcf E
movlw B'00101000'
call Send_Command
movlw Disp_Off
call Send_Command
movlw Disp_On
call Send_Command
movlw Entry_Inc
call Send_Command
return


- В подпрограмата за изпращане на команди изпращам двете тетради поотделно. Заменям тази част:

;------------- Изпращане на команда към LCD дисплея -------------
Send_Command
movwf LCD_Temp
call Check_BF
movf LCD_Temp,w
movwf PORTB
bcf RW
bcf RS
bsf E
bcf E
nop
nop
nop
nop
return


с тази:

;------------- Изпращане на команда към LCD дисплея -------------
Send_Command
movwf LCD_Temp
call Check_BF
movf LCD_Temp,w
andlw H'F0'
movwf PORTB
bcf RW
bcf RS
bsf E
bcf E
swapf LCD_Temp,w
andlw H'F0'
movwf PORTB
bsf E
bcf E
nop
nop
nop
nop
return


- По същия начин и в подпрограмата за изпращане на символ.

CarBeta5

  • Вече знае какво е робот!
  • *****
  • Публикации: 81
    • Профил
Proteus - проблем с LCD
« Отговор #9 -: Април 30, 2012, 02:49:35 pm »
Никъде не написа дали заработи 8 битовия режим.
По принцип промените за 4 битов режим са коректни, но си пропуснал да промениш и подпрограмата Check_BF,
която в този си вид чете 8 бита. Имаш два варианта.
- На мястото на call   Check_BF да сложиш call   Wait2, въпреки че и само 160 микросекунди ще са са достатъчни.
- Да промениш Check_BF да чете в 4 битов режим, трябва да се добавят още няколко команди и проблема е решен

Lampard87

  • Новодошъл
  • *****
  • Публикации: 7
    • Профил
Proteus - проблем с LCD
« Отговор #10 -: Април 30, 2012, 05:40:16 pm »
8-битовият режим тръгна нормално, след като добавих празните операции както ме посъветва.
А ще можеш ли да ми напишеш как да променя подпрограмата Check_BF за 4-битов режим ? Използвам RB4-RB7 за връзка с дисплея, съответно към D4-D7, а D0-D3 са на маса.

Lampard87

  • Новодошъл
  • *****
  • Публикации: 7
    • Профил
Proteus - проблем с LCD
« Отговор #11 -: Април 30, 2012, 06:13:15 pm »
Направих две запитвания към дисплея и след това проверих флага (бит 7) и се получи номера.

CarBeta5

  • Вече знае какво е робот!
  • *****
  • Публикации: 81
    • Профил
Proteus - проблем с LCD
« Отговор #12 -: Април 30, 2012, 06:19:21 pm »
В 4 битов режим всеки байт се предава на два такта. На теория флага, който проверяваш, е в първата тетрада и може да се провери директно и така както е програмата, но има LCD контролери, които ще забият ако не прочетеш и втората тетрада. Симулацията е предвидена и за тоя вариант и затова не тръгва. На живо би трябвало да работи и така. За да не ти дава грешка, след като запишеш състоянието на порта(т.е. старшата тетрада) в BF_Temp, му пусни още един импулс за да си прати и младшата тетрада, която ти няма да четеш защото не ти трябва, но... мир да има.
Добави:
...
   movf   PORTB,w
   movwf   BF_Temp
   bsf   E
   bcf   E

   btfsc   BF_Temp,7
   goto   Check_BF
...

Lampard87

  • Новодошъл
  • *****
  • Публикации: 7
    • Профил
Proteus - проблем с LCD
« Отговор #13 -: Май 01, 2012, 05:46:54 pm »
CarBeta5 благодаря много за помощта.