PDA

View Full Version : Serout2 on LCD Shows Junk Characters



RossWaddell
- 13th January 2013, 23:08
I'm trying to work out whether the code below is accurately producing 0-255 values for the ADCIN command which I'm then using in conjunction with Darrel's SPWM_Int.bas, but I can't tell because my Scott Edwards Electronics ILM-216 serial LCD just shows gobbledy-gook. I've jumpered pins 6 & 8 on the LCD to get 9600bps but it's no better than the default 2600 baud.

Can anyone help me out? I bought this serial LCD as my previous one was a parallel one which uses too many pins but it's not much good to me if it can't help me debug.

Scott Edwards Electronics data sheet for the ILM-216 can be seen here (http://www.seetron.com/docs/ilm216mnl.pdf).



' ************************************************** *************
' Pin Connections
' ************************************************** *************

' RA0 -> Middle arm of trim pot
' RC0 -> LED1
' RC1 -> LED2
' RC2 -> LED3
' RC4 -> Serial LCD output

DEFINE OSC 16 ; Set oscillator 16Mhz
;DEFINE OSC 4 ; Set oscillator 4Mhz
DEFINE ADC_BITS 8 ; Set number of bits in result
DEFINE ADC_SAMPLEUS 5 ; Set sampling time in uS
DEFINE ADC_CLOCK 3 ; Set clock source (3=rc)

' ************************************************** *************
' Device Fuses
' ************************************************** *************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF
__config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF
#ENDCONFIG

#DEFINE USE_LCD_FOR_DEBUG ; comment out for non-debug use

' ************************************************** *************
' Initialization
' ************************************************** *************

OSCCON = %01111000 ' 16MHz internal osc
;OSCCON = %01101000 ' 4MHz internal osc

pause 100

; Use PortA.0 (AN0) for ADCIN (trim pot reading)
ANSELA = %00000001 ; Analog on PORTA.0 (AN0) only
TRISA = %00000001 ; Input on PORTA.0 (AN0) only
;ADCON1 = %01110000 ; Left-justified results in 8-bits; Fosc/8 (2uS @ 4Mhz)
ADCON1.7 = 0 ; Left-justified results in 8-bits; Fosc/8 (2uS @ 4Mhz)
ANSELC = 0 ; Diginal only for all PortC pins
TRISC = %00000000 ; Make all PORTC pins output

#DEFINE USE_LCD_FOR_DEBUG ; comment out for non-debug use

#IFDEF USE_LCD_FOR_DEBUG
LCD_PIN VAR PORTC.4 ' Alias PORTC.4 as "LCD_PIN"
LCD_INST CON 254 ' instruction
LCD_CLR CON 1 ' Clear screen
LCD_L1 CON 128 ' LCD line 1
LCD_L2 CON 192 ' LCD line 2
; LCD_BAUD CON 16780 ' Baud rate/mode 2600bps for ILM-216 2x16 character display
LCD_BAUD CON 16468 ' Baud rate/mode 9600bps for ILM-216 2x16 character display
LCD_PACE CON 1 ' Optional pace value
#ENDIF

' ************************************************** *************
' Includes
' ************************************************** *************

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "SPWM_INT.bas" ; Software PWM module

DEFINE SPWM_FREQ 200 ; SPWM Frequency
DEFINE SPWM_RES 256 ; SPWM Resolution

DutyVars VAR BYTE[3] ; DutyCycle Variables
DutyVar1 VAR DutyVars[0] ; group them in an array for easy access
DutyVar2 VAR DutyVars[1] ; with FOR loops etc.
DutyVar3 VAR DutyVars[2]

ASM
SPWM_LIST macro ; Define Pin's to use for SPWM
SPWM_PIN PORTC, 0, _DutyVar1 ; and the associated DutyCycle variables
SPWM_PIN PORTC, 1, _DutyVar2 ; Notice the underscore before variables
SPWM_PIN PORTC, 2, _DutyVar3
endm
SPWM_INIT SPWM_LIST ; Initialize the Pins
ENDASM

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, SPWMhandler, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts

adval VAR WORD ; stores ADCIN results
oldDutyVar1 VAR WORD
;_________________________________________________ ____________________________

DutyVar1 = 0
DutyVar2 = 25
DutyVar3 = 255

#IFDEF USE_LCD_FOR_DEBUG
serout2 LCD_PIN, LCD_BAUD, LCD_PACE, [LCD_INST, LCD_CLR] ; clear screen
pause 5
serout2 LCD_PIN, LCD_BAUD, LCD_PACE, ["DutyVar1:", DEC DutyVar1, " "]
#ENDIF

Main:
ADCIN 0, adval
if adval <> oldDutyVar1 then
oldDutyVar1 = adval
DutyVar1 = adval

#IFDEF USE_LCD_FOR_DEBUG
serout2 LCD_PIN, LCD_BAUD, LCD_PACE, [LCD_INST, LCD_CLR] ; clear screen
pause 5
serout2 LCD_PIN, LCD_BAUD, LCD_PACE, ["DutyVar1:", DEC DutyVar1, " "]
#ENDIF
EndIf
Pause 100
Goto Main

Darrel Taylor
- 14th January 2013, 00:47
Ross,

You can't use software timed serial routines when using interrupts.

You will need to use the USART and HSEROUT.

gadelhas
- 14th January 2013, 00:48
Hi RossWaddell,

I used this LCD in the past and i had some problems with interrupts. If you are outputing something to the LCD and if an interrupt occurs, the data gets corrupted. If possible, you must disable the interrupt, then send the data with the serout command, and then enable interrupt, of course, if it is allowed to do in your program. When i don't use interrupts, no problem working with this LCD, with serout, serin, serout2, serin2, hserout and hserin!!

EDIT: grrr... Darrel.... get it first!!!!

RossWaddell
- 14th January 2013, 01:13
Thanks Darrel & Gadelhas. Am I right in thinking RA0 is the USART tx pin on the PIC16F1825?

gadelhas
- 14th January 2013, 01:41
Yes. You can have TX on RA0 or RC4, because in this chips is possible to change between those 2 pins, by controlling the APFCON0 and APFCON1 registers.

RossWaddell
- 14th January 2013, 01:52
If I'm using RA0, do I need to set those registers? Because without them the screen is completely blank:



'************************************************* ***************
'* Name : Test_SPWM.pbp *
'* Author : Darrel Taylor *
'* Date : 9/30/2006 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************


; LCD serout2 command won't work when using interrupts; need to use
; HSEROUT on chip's USART tx pin instead.



' ************************************************** *************
' Pin Connections
' ************************************************** *************

' RA0 -> Serial LCD output
' RA1 -> Middle arm of trim pot (AN1)
' RC0 -> LED1
' RC1 -> LED2
' RC2 -> LED3

DEFINE OSC 16 ; Set oscillator 16Mhz
;DEFINE OSC 4 ; Set oscillator 4Mhz
DEFINE ADC_BITS 8 ; Set number of bits in result
DEFINE ADC_SAMPLEUS 5 ; Set sampling time in uS
DEFINE ADC_CLOCK 3 ; Set clock source (3=rc)

DEFINE HSER_TXSTA 20h ; Set transmit status and control register
DEFINE HSER_BAUD 2400 ; Set baud rate

' ************************************************** *************
' Device Fuses
' ************************************************** *************
#CONFIG
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF
__config _CONFIG2, _PLLEN_OFF & _STVREN_ON & _BORV_LO & _LVP_OFF
#ENDCONFIG

#DEFINE USE_LCD_FOR_DEBUG ; comment out for non-debug use

' ************************************************** *************
' Initialization
' ************************************************** *************

OSCCON = %01111000 ' 16MHz internal osc
;OSCCON = %01101000 ' 4MHz internal osc

pause 100

; Use PortA.1 (AN1) for ADCIN (trim pot reading)
ANSELA = %00000010 ; Analog on PORTA.1 (AN1) only
TRISA = %00000010 ; Input on PORTA.1 (AN1) only
;ADCON1 = %01110000 ; Left-justified results in 8-bits; Fosc/8 (2uS @ 4Mhz)
ADCON1.7 = 0 ; Left-justified results in 8-bits; Fosc/8 (2uS @ 4Mhz)
ANSELC = 0 ; Diginal only for all PortC pins
TRISC = %00000000 ; Make all PORTC pins output

#DEFINE USE_LCD_FOR_DEBUG ; comment out for non-debug use

#IFDEF USE_LCD_FOR_DEBUG
LCD_PIN VAR PORTC.4 ' Alias PORTC.4 as "LCD_PIN"
LCD_INST CON 254 ' instruction
LCD_CLR CON 1 ' Clear screen
LCD_L1 CON 128 ' LCD line 1
LCD_L2 CON 192 ' LCD line 2
LCD_BAUD CON 16780 ' Baud rate/mode 2600bps for ILM-216 2x16 character display
; LCD_BAUD CON 16468 ' Baud rate/mode 9600bps for ILM-216 2x16 character display
LCD_PACE CON 1 ' Optional pace value
#ENDIF

' ************************************************** *************
' Includes
' ************************************************** *************

INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "SPWM_INT.bas" ; Software PWM module

DEFINE SPWM_FREQ 200 ; SPWM Frequency
DEFINE SPWM_RES 256 ; SPWM Resolution

DutyVars VAR BYTE[3] ; DutyCycle Variables
DutyVar1 VAR DutyVars[0] ; group them in an array for easy access
DutyVar2 VAR DutyVars[1] ; with FOR loops etc.
DutyVar3 VAR DutyVars[2]

ASM
SPWM_LIST macro ; Define Pin's to use for SPWM
SPWM_PIN PORTC, 0, _DutyVar1 ; and the associated DutyCycle variables
SPWM_PIN PORTC, 1, _DutyVar2 ; Notice the underscore before variables
SPWM_PIN PORTC, 2, _DutyVar3
endm
SPWM_INIT SPWM_LIST ; Initialize the Pins
ENDASM

ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, SPWMhandler, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM

@ INT_ENABLE TMR1_INT ; enable Timer 1 interrupts

adval VAR WORD ; stores ADCIN results
oldDutyVar1 VAR WORD
;_________________________________________________ ____________________________

DutyVar1 = 0
DutyVar2 = 25
DutyVar3 = 255

#IFDEF USE_LCD_FOR_DEBUG
HSEROUT [LCD_INST, LCD_CLR]
pause 5
HSEROUT ["DutyVar1=", DEC DutyVar1, 13, 10] ' Send text followed by carriage return and linefeed
#ENDIF

Main:
ADCIN 1, adval
if adval <> oldDutyVar1 then
oldDutyVar1 = adval
DutyVar1 = adval

#IFDEF USE_LCD_FOR_DEBUG
HSEROUT [DEC DutyVar1, 13, 10] ' Send text followed by carriage return and linefeed
#ENDIF
EndIf
Pause 100
Goto Main


Edit: Adding


APFCON0.2 = 1 ; Tx on RA0

makes the screen not blank, but it's still gobbledy-gook.

gadelhas
- 14th January 2013, 01:59
try with APFCON0.2 = 1, because the chip is initialized with TX on the RC4 pin, (APFCON0.2 = 0), so you must change it. datasheet page 123.

Darrel Taylor
- 14th January 2013, 04:07
The Scott Edwards display is expecting Inverted serial levels.
The USART puts out True levels by default.

Add this setting ...
BAUDCON.4 = 1 ; Transmit inverted data to the TX/CK pin

RossWaddell
- 14th January 2013, 13:03
The Scott Edwards display is expecting Inverted serial levels.
The USART puts out True levels by default.

Add this setting ...
BAUDCON.4 = 1 ; Transmit inverted data to the TX/CK pin

Thanks Darrel! It works now except the LCD shows a strange character in the 1st position (looks like "F1" with the "1" being a subscript).



#IFDEF USE_LCD_FOR_DEBUG
HSEROUT [LCD_INST, LCD_CLR]
pause 5
HSEROUT ["DutyVar1=", DEC DutyVar1, 13, 10] ' Send text followed by carriage return and linefeed
#ENDIF

Main:
ADCIN 1, adval
if adval <> oldDutyVar1 then
oldDutyVar1 = adval
DutyVar1 = adval

#IFDEF USE_LCD_FOR_DEBUG
HSEROUT [LCD_INST, LCD_CLR, LCD_L1]
HSEROUT ["DutyVar1=", DEC DutyVar1, " ", 13, 10] ' Send text followed by carriage return and linefeed
#ENDIF
EndIf
Pause 100
Goto Main

Darrel Taylor
- 14th January 2013, 14:48
HSEROUT [LCD_INST, LCD_CLR, LCD_L1]

You need at least a 2mS pause after the clear screen command.
Then you need another LCD_INST before the LCD_L1.
Or just leave out the LCD_L1 since the clear screen leaves the cursor on line 1.

RossWaddell
- 14th January 2013, 15:51
I have a 5ms pause before the Main loop, but I think it's irrelevant since the ADCIN gets a value which is immediately different than the set value for DutyVar1 (set to 0 earlier in the code) and hence it goes straight into the IF block.

I'll add a 5ms pause in the IF block, too. And remove the LCD_L1 if it's not needed.

Thanks again, Darrel!