PDA

View Full Version : Learning how to use USART



keithv
- 9th May 2018, 20:22
I'm trying to get one PIC to talk to the other. I'm not using MIDI messages at this point, but I am using MIDI hardware to connect the two PICs. The schematics are found here https://www.tigoe.com/pcomp/code/picbasic-pro/161/

I'm using two 16F887. One is the transmitting PIC. MIDI out hardware is connected to pin 25/portc.6/TX. I'm trying to send the numbers 1 ~ 9 every 600ms. An LED blinks each time it's supposed to send just to let me know that it's doing something.

The other PIC is supposed to receive the number and display it on an LCD. The MIDI in hardware is connected to pin 26/portC.7/RC. I made the LCD display "ready to receive" at start up so I know that it's working.

The blinking LED on the transmitting PIC is working, and the LCD on the receiving PIC is working, but I'm not seeing any numbers being displayed.

Here's the code for the transmitting PIC:



define OSC 20
define HSER_RCSTA 90h
define HSER_TXSTA 20h
define HSER_BAUD 31250


ANSEL = %00000000
ANSELH = %00000000
TRISD = %00000000
TRISE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %01000000


send var byte


main:


send = send + 1
hserout [send]
PORTA.0 = 1
pause 300
PORTA.0 = 0
pause 300
if send >= 10 then
send = 0
endif


goto main



Here's the code for the receiving PIC:

CLEARdefine LOADER_USED 1
define OSC 20
define HSER_RCSTA 90h
define HSER_TXSTA 20h
define HSER_BAUD 31250
define LCD_DREG PORTD
define LCD_DBIT 0
define LCD_RSREG PORTE
define LCD_RSBIT 0
define LCD_EREG PORTE
define LCD_EBIT 1
define LCD_RWREG PORTE
define LCD_RWBIT 2
define LCD_BITS 4
define LCD_LINES 4
define LCD_COMMANDUS 2000
define LCD_DATAUS 50


ANSEL = %00000000
ANSELH =%00000000
TRISD = %00000000
TRISE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %01000000


data_in var byte


pause 250
lcdout $fe, 1
lcdout $fe, $d4, "ready to receive"
pause 500
lcdout $fe, 1
pause 250


main:


hserin [dec data_in]
pause 5
if data_in != 0 then
gosub display
endif
goto main


display:
lcdout $fe, 1
lcdout $fe, $94, dec data_in
data_in = 0
return

mpgmike
- 9th May 2018, 21:43
LCDs speak in ASCii. The PBP3 Reference Manual covers ASCii on pages 42 & 305-6. To work with decimal, add 48 to your decimal value & it should appear on the LCD screen as the value intended.

keithv
- 9th May 2018, 23:26
LCDs speak in ASCii. The PBP3 Reference Manual covers ASCii on pages 42 & 305-6. To work with decimal, add 48 to your decimal value & it should appear on the LCD screen as the value intended.

That didn't help. I also realized that PORTC register should have been TRISC=%10000000. I fixed that, but it didn't help either.

mpgmike
- 10th May 2018, 02:52
There is an initialization process to get LCDs to come on line. It usually isn't needed, but I ran into an instance like yours where everything suggested it SHOULD work, but it didn't. One of the HD44780 LCD Data Sheets outlined an initialization process. Here is what I use:

4-Wire


Init_LCD:
RS = 0
' LCD = $20
DB7 = 0
DB6 = 0
DB5 = 1
DB4 = 0
En = 1
pauseus 10
En = 0
pause 5
' LCD = $20
DB7 = 0
DB6 = 0
DB5 = 1
DB4 = 0
En = 1
pauseus 10
En = 0
pauseus 160
' LCD = $20
DB7 = 0
DB6 = 0
DB5 = 1
DB4 = 0
En = 1
pauseus 10
En = 0
pauseus 160
LCD = $28
gosub Send
LCD = $10
gosub Send
LCD = $0C
gosub Send
LCD = $06
gosub Send
LCD = 1
gosub Send
pause 1
LCD = $80
gosub Send
RS = 1
pause 1
RETURN



For 8-wire:


Init_LCD:
low RS
PORTB = $30
high En
pauseus 4
low En
pause 5
PORTB = $30
high En
pauseus 4
low En
pauseus 160
PORTB = $30
high En
pauseus 4
low En
pauseus 160
PORTB = $38
gosub Send
PORTB = $10
gosub Send
PORTB = $0C
gosub Send
PORTB = $06
gosub Send
PORTB = 1
gosub Send
pause 1
PORTB = $80
gosub Send
high RS
pause 1
RETURN

Send:
high En
pauseus 8
low En
pause 1
return


Maybe this will help.

richard
- 10th May 2018, 05:05
The blinking LED on the transmitting PIC is working, and the LCD on the receiving PIC is working, but I'm not seeing any numbers being displayed.

given all things working display wise ,imho mike is leading you astray

tx unit:-

send = send + 1
hserout [send]

will send binary 0 to 9 , probably not the best idea but it is workable


ps weird baud rate


rx unit:-


hserin [dec data_in]
pause 5

will never work

1. its waiting for ascii numbers , the first non number will terminate routine
2. pause 5 why it serves no purpose and can cause framing errors


add this define
DEFINE HSER_CLROERR 1 ' Clear overrun error upon execution of every HSERIN command


rx unit:-
lcdout $fe, $94, dec data_in

if ok but it needs
hserin [data_in] to match data types

ps weird baud rate

keithv
- 10th May 2018, 19:47
Yes, the LDC is working just fine. The baud rate is the standard MIDI baud rate. I'm trying to make a MIDI controller.

I've updated the code with the suggestions and made it a little more simple. I'm trying to get the LCD of the receiving PIC to display "1" for 300ms and then "0" for 300ms.

Here's the code for the transmitting PIC:


define OSC 20
define HSER_RCSTA 90h
define HSER_TXSTA 20h
define HSER_BAUD 31250


ANSEL = %00000000
ANSELH = %00000000
TRISD = %00000000
TRISE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000

main:

hserout [1]
PORTA.0 = 1
pause 300
hserout [0]
PORTA.0 = 0
pause 300

goto main


Here's the code for the receiving PIC:


CLEAR
define LOADER_USED 1
define OSC 20
define HSER_RCSTA 90h
define HSER_TXSTA 20h
define HSER_BAUD 31250
define HSER_CLROERR 1
define LCD_DREG PORTD
define LCD_DBIT 0
define LCD_RSREG PORTE
define LCD_RSBIT 0
define LCD_EREG PORTE
define LCD_EBIT 1
define LCD_RWREG PORTE
define LCD_RWBIT 2
define LCD_BITS 4
define LCD_LINES 4
define LCD_COMMANDUS 2000
define LCD_DATAUS 50

ANSEL = %00000000
ANSELH = %00000000
TRISD = %00000000
TRISE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000

character var byte

pause 250
lcdout $FE, 1
lcdout $fe, $d4, "ready to receive"
pause 500
lcdout $fe, 1
pause 250

main:

hserin [character]
lcdout $fe, 1
lcdout $fe, $94, character

goto main


It's still not working.

richard
- 10th May 2018, 23:46
It's still not working.

how can it work ?
char's 0 and 1 are non printing characters on a lcd

lcdout $fe, $94, dec character

keithv
- 11th May 2018, 00:35
how can it work ?
char's 0 and 1 are non printing characters on a lcd

lcdout $fe, $94, dec character

Adding the dec modifier didn't help. I tried adding it to hserout as well and it didn't work. Maybe it's my hardware. This is what I'm trying to use.

8641

Can you recommend something else that's better for connecting two PICs?

richard
- 11th May 2018, 02:22
Can you recommend something else that's better for connecting two PICs?

it can't get simpler than this depending on distance / speed .
using serial tty ie hserin/out

Scampy
- 11th May 2018, 08:42
I would get the two talking directly without any MIDI interface. Just connect the TX from the PIC running the transmission code, to the RX on the receiving PIC using a simple jumper wire. If you need to send data back the connect the receiving PICs TX pin to the RX pin on the other PIC. I would then use the HSEROUT and HSERIN commands to send data.

You could write a short test routine so that the receiving PIC sends a character to the transmitting PIC when its ready to receive data (say by pressing a button), the transmission is made and the data displayed on the LCD.

So your transmission PIC has something like


RCIF VAR PIR1.5 ' USART receive flag
GIE VAR INTCON.7 ' Comms
TempWD VAR WORD ' temporary WORD variable
nTest var byte


FOR TempWD = 0 TO 1000
IF RCIF=1 THEN GOTO coms ; Check to see if somethings in the buffer, if there is something goto Comms
PAUSE 2
NEXT TempWD

coms:
HSERIN [nTest]
SELECT CASE nTest
CASE "Q" ; if Q then send data
GOTO Term_TX:

Term_TX
Hserout [DEC3 insert variable here] ; sends three digits of variable eg 123



You would then have your receiving PIC set up so that when you want to receive data it sends a Q to the transmitting PIC. The transmitting PIC is always looking at the serial port buffer to see if there is something in it, and when it finds something jumps to the comms subroutine, which checks to see what character has been received an for a match. If its Q then it transmits the data. You could use other characters to jump to other routines and do other things if you wanted.

The only caveat here is that I've only ever sent numeric data this way. Sending ASCII or strings may need more work.

Whilst the code is clunky it could always be tidied up and made more efficient once you have the two talking.

Scampy
- 11th May 2018, 09:00
Strange baudrate !

Using a EUSART calculator for your baudrate it gives these values for the port settings



DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_TXSTA 20h ' Enable transmit, BRGH = 0
DEFINE HSER_CLROERR 1 ' Clear overflow automatically
DEFINE HSER_SPBRG 39 ' 31250 Baud @ SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator


RCSTA = $90 ' Enable serial port & continuous receive
TXSTA = $20 ' Enable transmit, BRGH = 0
SPBRG = 39 ' 31250 Baud @ 0.0%
SPBRGH = 0
BAUDCON.3 = 1 ' Enable 16 bit baudrate generator


I don't have PBP3 - so no idea if the formatting is the same or needs changing

Ioannis
- 12th May 2018, 20:45
Please make sure that PIC to PIC directly connected work as expected.

Then move to MIDI interface.

Also be sure to connect TX to RX. Looks trivial but...

Ioannis

keithv
- 14th May 2018, 19:27
I removed the midi connections and just connected the TX of the transmitting PIC to the RC of the receiving PIC. Here is the code I'm using for each:

transmitting:


define OSC 20
define HSER_RCSTA 90h
define HSER_TXSTA 20h
define HSER_BAUD 31250
DEFINE HSER_SPBRG 39 ' 31250 Baud @ SPBRGH = 0



ANSEL = %00000000
ANSELH = %00000000
TRISD = %00000000
TRISE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000

main:

hserout [dec 1]
PORTA.0 = 1
pause 300
hserout [dec 0]
PORTA.0 = 0
pause 300

goto main


receiving:


CLEAR
define LOADER_USED 1
define OSC 20
define HSER_RCSTA 90h
define HSER_TXSTA 20h
define HSER_BAUD 31250
define HSER_CLROERR 1
DEFINE HSER_SPBRG 39 ' 31250 Baud @ SPBRGH = 0

define LCD_DREG PORTD
define LCD_DBIT 0
define LCD_RSREG PORTE
define LCD_RSBIT 0
define LCD_EREG PORTE
define LCD_EBIT 1
define LCD_RWREG PORTE
define LCD_RWBIT 2
define LCD_BITS 4
define LCD_LINES 4
define LCD_COMMANDUS 2000
define LCD_DATAUS 50

ANSEL = %00000000
ANSELH = %00000000
TRISD = %00000000
TRISE = %00000000
TRISA = %00000000
TRISB = %00000000
TRISC = %10000000

character var byte

pause 250
lcdout $FE, 1
lcdout $fe, $d4, "ready to receive"
pause 500
lcdout $fe, 1
pause 250

main:

hserin [character]
lcdout $fe, 1
lcdout $fe, $94, dec character

goto main


So now it's sorta working. The LCD does display something. It displays "216" when it should be displaying "0" and it displays "217" when it should be displaying 1.

Scampy
- 14th May 2018, 20:34
Try setting a variable.


character var word


then use something like



hserout [dec character]


And similar for the receiving pic. I'm no expert, but I think that just having DEC 1 as you had simply means its setting the DEC command to use just 1 digit as decimal value of a variable, not a value