Searching \ for '4 x Serial I\O' in subject line. ()
Make payments with PayPal - it's fast, free and secure! Help us get a faster server
FAQ page:
Search entire site for: '4 x Serial I\O'.

Truncated match.
PICList Thread
'4 x Serial I\O'
1999\10\11@202514 by Thomas Brandon

picon face
I am looking at a project involving 4 MIDI interfaces (both in & out). MIDI
is a 31250bps NRZ comms scheme. As well as the I\O there are quite a few
other things going on such as routing of the messages, ADCing of knobs and a
possible USB interface down the track. I can't foresee any problems with 4
outputs, you could simply have them synchronised. You'd need a couple of
extra instructions to get the 4 bits as a nibble, but if you had one nibble
of a port as in and the other as out you could simply write to the whole
port without effecting input. I can't foresee any problems with this. In the
case that other port pins were used as ouputs you would need to read, AND,
OR and write, still not too bad. 31250bps = 32us\bit, on a 20MHz (5MIPS) PIC
that's 160 instructions\bit. Unlesss the reciever latched the data on the
rising edge of the clock, I can't see any problems, I should really be able
to be as much as 20 instructions late in writing the data with no problems,
as long as I don't lose time.

The main problem is 4 channels of MIDI in. In theory I think it should just
about be possible. The main problem is keeping the timing.
I could either poll the 4 inputs or have interrupt on falling edges (Stop
bit -> start bit).

Interrupts are a bit slow and nondeterministic, at least with 4 external
interrupts (incoming start bit) and 4 internal interrupts (4 outbound
channels). By synching the outputs and having only 1 internal interrupt it
gets better. But I still don't have a lot of leniency in the external
interrupt response. I would have to have a very efficent method of quickly
noting the timing of that channel for subsequent polling. The other problem
with external interrupts is I have to keep disabling them for the data bits
or else I will get extra interrupts due to falling edges in the data.

However straight polling implies a fair bit of logic to determine if the
values changed and if it has changed what that means (start, data, stop,
noise, etc).

The other options are of course external UARTs or a Scenix. I have
investigated external UARTs but have yet to find a suitable one I can
actually get here in Australia. The MAX3100 is pretty good, nice and small,
the only problem is sourcing them here. I have yet to find an Australian
supplier stocking them and Digikey doesn't have them in their catalogue. I
can get them through the Maxim small orders but the price is pretty poor
(they're charging more than digikey for 1-25) and I'm up for US$50 shipping.
Apart from that the only UARTs I've seen are the National 1655x series. I
can get the 16550 from Dick Smith but at AU$20ea, I can get 4 16F84's for
less and have 'intelligent' UARTs (or DUARTs). I am yet to find an
australian stockist of the 16552 DUART, and it's PLCC only which I'd rather
avoid. And, even the MAX3100 is pretty innefficient in many ways. I don't
need flow control or anything just RX and TX. Yet I have to pay for, and use
board space for these features.

In terms of Scenix's, they are in many ways an attractive alternative. My
main problem with them is lack of experience and their sensitivity. I'm not
exactly a PIC expert (and there pretty similar) so the sensitivity is more
of an issue (particularly in relation to my poor electronics knowledge).

Has anyone implemented multiple UARTs in a single PIC? Anyone think it'd be
possible? Anyone suggest an alternative external UART?


1999\10\11@210501 by Erik Reikes

At 10:27 AM 10/12/99 +1000, you wrote:
{Quote hidden}

This is quite a problem.

This may or may not work, but as I see it your biggest problem is 4 start
bits coming in at 4 different times asynchronously.

I would set up your Timer0 to give you a beat of Tbit/4, so 40
instructions.  This will give you fairly decent resolution in your bit
timing.  Then I would use interrupt on change for your 4 serial lines to
catch the start bits.  What you want to do is catch each start bit, turn
off the int on change, and delay one to two Timer0 beats to catch the
approximate middle of the bit.  The two interrupts could communicate via
some global variable, that would say how many more beats to sample the
first bit.  So basically what's happening is that Timer0 interrupt is
marking off exactly 1/4 bits,  the int on change catches the start bit of
each bit and signals the Timer0 interrupt to sample at appropriate times.

Any other processing will be done in the down times when interrupts are not
being serviced.  Where this gets sticky is the 4 instruction cycle latency.
With a 40 instruction beat, that kills 10% of you CPU right off the bat,
pllus whatever you use in the Timer0.  There may not be enough to go around.

Another suggestion might be to byte buffer your serial ins with shift
registers.  You would need a clock at 31250 KHz and a shift register for
each line you want to buffer.  The start bit generates an interrupt and
your micro enables the proper shift register.  You setup your timer0
interrupt to wake up at least every byte time (which is now 160*8 ~= 1200
instructions) to pull in the data.  This is sort of a roll your own UART.

Good luck!

-Erik Reikess

1999\10\11@211105 by jay

I've designed and built an RS232-RS485 converter with certain protocol needs
and a circular buffer using a PIC16C74A.  I had essentially two software
UARTS.  Stupid me, I didn't even use the built in UART, instead I bit banged
out 8n1 at 9600 and received at 9600 by interrupting every 33 microseconds
and going through the transmitting and receiving at controlled time lengths.
The device works ok, but if I had to do it again --- NO WAY JOSE!!!!!  I am
now looking at implementing the Phillips SCN2681 DUART, you can get these in
a 24-pin DIP version that does not have all the modem control signals.
Perhaps for your application you could stack two of these up.  Just a

Jason Mielke
Chief Engineer
Bliss Communications, Inc.

{Original Message removed}

1999\10\11@214018 by Ben Stragnell


The trouble with a clocked shift register running at the base bitrate (I
presume you meant 31250Hz, not KHz), would be that the clock at the other
end isn't necessarily exactly in sync with yours. If you happen to sample a
start-bit right on the rising/falling edge, then even the slightest
discrepancy in clock rates will cause incorrect data to be read on
subsequent bits.

In order to receive serial data with any degree of reliability it's
necessary to sample the port at 3 times the base bitrate. When you detect
the first edge of a start bit, you start to sample the data every 3rd tick,
*starting immediately at the next tick*. This means that you can be
confident that you're sampling the data anywhere between 1/3 and 2/3 through
each bit. So, as long as the clocks don't shift by 1/3 of a bit over the
course of the 10 (or however many) bits per word, you're safe.

Trouble is, you have to consider the worst case scenario here... with 4
*independant* channels, you'd have to run the timer at 12 x 31250 =
375KHz... ie. 13.3 instructions per tick (on a 20Mhz/5MIPS PIC) in order to
receive data reliably. That isn't going to be enough, given interrupt
latency, etc...

You're either going to need hardware UARTS, or a faster chip. You could use
a Scenix SX (they actually have an application note on their website which
deals with running 8 independant software UARTS), but unfortunately I don't
think they have the ADC capabilities you'd be looking for.

Hope this helps,

{Original Message removed}

1999\10\11@221800 by Thomas Brandon

picon face
The main problem with timer handling is interleaving the 4inputs and
4outputs effectively. Perhaps a miny RTOS using TMR2 and PR2 as a delay
system. The main problem then would be efficiently recording what should be
done on the next interrupt. However the PICs with 3 timers generally have
ADC's and too much RAM, plus the only such flash chips are the 'F87x's so I
would have to either pay for ADC's, RAM, Pins etc. that I don't need or
prototype on a 'F87x or a windowed part and use OTP for production. Which is
a pity as I liked the idea of having incircuit Firmware updates via MIDI
(could still update other chips of course).  Also, a bit of logic would be
required to decide when to group operations together (and handle this in the
interrupt) because they can't run as serial delays. The one thing I would
have on my side is Program code space. By bloating the code incredibly to
handle individually as many situations as possible may help speed. Ideally I
would use the 16F84A as it's the only 20MHz chip without extraneous
peripherals. However it does not include the one peripheral I want: a
hardware serial interface to communicate with the rest of the PIC's (ideally
I would use multi slave SSP as one PIC will clearly be the controller).

The shift registers would be a nice alternative in terms of cost but MIDI
has no clock so I would have to deal with generating 4 clocks, if possible
in the middle of the MIDI clocks. I would then also have to multiplex the 4
shift registers to the PIC. Thus I would need to have a multiplexed latch
for the data ouput or use a device with >13pin (8 for input data + 2 for mux
+ 4 for clock detect = too many pins). A shift register could at least help
communicate with the other PICs via a nice 2 wire interface yet still allow
parallel transfers if the reciever has more pins than cycles.

My main problem with a Scenix is that of reliability due to my lack of
electronic expeience. I have heard of fairly experienced PICsters burning
out scenix's so myself with little MCU experience would have even more
trouble. I've also heard of some weird things with scenix's like
spontaneously deciding to burn out (I'm not saying a 50MHz PIC @ 50MIPS
would do any better).. The external ADC for a scenix is not a big problem as
I can get a SX28-50 (50MIPS) and a Burr brown 500kHz 12-bit ADC for AU$15
and US$7 respectively. A total of ~AU$30 (have to get ADC from digikey so
add shipping) which compares not too badly with AU$25 for a 'F877 (10-bit
500kHz+ (I think) ADC). The other thing is even one scenix is not
excessively overpowered for the application. 50MIPs should be plenty, but
unfortunately those 50MIPs are spread across a whole second, so getting
everything to work at once may still be a challenge. Also, the ADC will have
to deal with sampling 64-128 voltages and getting extremely linear 7bit
outputs, doing this with only 128bytes of RAM (and doing UARTs etc) will be
pushing it. Hence overall segregation into multiple smaller units has
advantages in terms of both easing many of the design constraints and making
the final system more scalable. That particular virtual peripheral does
8x19.2K UARTs at 12.5MIPS (@50MHz). I would gather then that 4x31.25K could
then be done in less than 15-20MIPS @50MHz (or much the same at any clock).

I think I'll have muck around in MP-Sim and see how that goes. Due to other
tasks it may be that having 2 'F84A's doing 2 UARTs a piece is a workable
solution. However, I'll definitely be investigating thouroughly hardware
UARTs such as the Phillips UART without modem control.

Thanks Ben, Erik, Jay and all,
{Original Message removed}

1999\10\12@120529 by Dwayne Reid

>I am looking at a project involving 4 MIDI interfaces (both in & out). MIDI
>is a 31250bps NRZ comms scheme.


> The main problem is 4 channels of MIDI in. In theory I think it should just
>about be possible. The main problem is keeping the timing.
>I could either poll the 4 inputs or have interrupt on falling edges (Stop
>bit -> start bit).

I think this can be done on a 20 MHz / 5 MIPs part.  31,250 baud is 32 uS
per bit which is 160 instructions at 5 MIPs.  You need to sample at 3X rate
- that puts your sample points at 53, 53, 54 instructions.

Here is how I did it at 9600 baud on a 4 MHz 12c508 and 12c671.  The
technique is based upon John Payson's suggetion of using a long shift
register to store the entire character as it is received - I used 40 bits (5

   btfsc   input1
     bsf   RxSr1A,0
   btfsc   input2
     bsf   RxSr2A,0
   btfsc   input3
     bsf   RxSr3A,0
   btfsc   input4
     bsf   RxSr4A,0

; do something to eat up the rest of 53 cycles
; I put my task scheduler here

   btfsc   input1
     bsf   RxSr1A,1
   btfsc   input2
     bsf   RxSr2A,1
   btfsc   input3
     bsf   RxSr3A,1
   btfsc   input4
     bsf   RxSr4A,1

;test for received start bits.  I'll get into that later.

;make sure that middle portion also uses 53 instructions (isochronous)

   btfsc   input1
     bsf   RxSr1A,2
   btfsc   input2
     bsf   RxSr2A,2
   btfsc   input3
     bsf   RxSr3A,2
   btfsc   input4
     bsf   RxSr4A,2

;shift all 3 shift registers 3 places to the left.
;Remember that each SR is 5 bytes long.

;make sure bottom section is 52 instructions long
;I put my SPI and serial TX routines here

   goto    Top     ;bottom is 52 instr. long, this goto makes 54 to Top

I used the rest of the time between Top and Middle to run a mickey mouse
task scheduler which actually ran the application code.  The entire main
loop contained all my timing dependendant routines that either ran or wasted
the same number of cycles, depending upon whether a flag was set ot not.

The only clever bit of code it took to make this work was the technique I
used to look for start bits.  The following snippits are pulled from working

; May or may not do some futsing to correct minor baud rate errors.
; 111100--d--d--d--d--d--d--d--d--1-
; Note: easier if SR chain contains inverted data - a cleared SR chain looks
; like all stop bits.
; Aquire 3 samples, then see if any of the 3 samples had a start bit fall into
; the right spot.
; 00 0011--i- -i--i--i --i--i-- i--i--0-  1st sample with start bit
;   ^      0 ^ 1  2  3^  4  5  ^6  7    ^
; 00 011--i-- i--i--i- -i--i--i --i--0--  2nd sample with start bit
;   ^     0  ^1  2  3 ^ 4  5  6^  7     ^
; 00 11--i--i --i--i-- i--i--i- -i--0---  3rd sample with start bit
;   ^    0  1^  2  3  ^4  5  6 ^ 7      ^

The ^ above indicate the boundaries of the 5 bytes used to make up the SR.
The dashes indicate samples I don't care about.  The numbers show the
position of the bits within the character.  Note that the position of the
bits changes, depending upon where the start bit is detected.

I used a jump table to determine valid start bits, as follows:

;test for start bits for each of the 3 shifts.  A valid start is defined as 2
;consecutive 1s.  Jump table uses the upper nybble of the MS byte to detect
;any of the 3 valid start positions (XXXx----).
;x011 is 1st shift, 011x is 2nd shift, 11xx is 3rd shift
;Jump table clears C (has to, otherwise HUGE problem!).  Important in Bottom2.
   swapf       RXSRE,W         ;
   andlw       b'00001111'     ;
   addwf       PCL,F           ;6 cycles any jump
   goto        NoSample        ;nothing there
   goto        NoSample        ;potential start bit
   goto        BadSample       ;noise
   goto        Get1st          ;valid start bit - 1st shift
   goto        BadSample       ;noise
   goto        BadSample       ;noise
   goto        Get2nd          ;valid start bit - 2nd shift
   goto        Get2nd          ;and again
   goto        BadSample       ;noise
   goto        BadSample       ;noise
   goto        BadSample       ;noise
   goto        Get1st          ;this might be a valid 1st sample
   goto        Get3rd          ;valid start bit - 3rd shift
   goto        Get3rd          ;and again
   goto        Get3rd          ;and here too
   goto        Get3rd          ;and here

You would do 4 jump tables, one for each serial input.

I also used jump tables to look for variations in the stop bits and modified
the locations of the data bits according to where the stop bit was found.
This doubled my tolerance of baud rate error.

To sum things up, I think it is achievable.  I had time chunks of 34, 34, 35
cycles on a 12c508 or 12c671 running at 4 MHz - you have WAY more time at
53, 53, 54 cycles when running at 20 MHz.

I am willing to send you a copy of my code if you want to use it as a
template - I plan to publish it soon anyways.  For the record, I do 9600
buad TX and RX, as well as PWM, SPI, and look for button presses on 4 pins
of a 12c508; I also read 1 or 2 channels of a/d on the same 4 pins of a 12c671.

I hope this helps.


Dwayne Reid   <>
Trinity Electronics Systems Ltd    Edmonton, AB, CANADA
(780) 489-3199 voice          (780) 487-6397 fax

Celebrating 15 years of Engineering Innovation (1984 - 1999)

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Do NOT send unsolicited commercial email to this email address.
My posting messages to Usenet neither grants consent to receive
unsolicited commercial email nor is intended to solicit commercial

1999\10\13@130405 by Jose Souto

part 0 9345 bytes
x-html> Thomas Brandon wrote:
I am looking at a project involving 4 MIDI interfaces (both in & out).
I cannot resist...
/*--------------------------cut here  ------------------------------*/
    Jose L P Souto -
    Compiler: CC5xFree v3.0D from
    MCU: PIC16C505 @ 4Mhz Internal RC

        .-------  ------.
        |    &nbs p;  \/      |
Vcc     . +5V       GND .   Gnd
        |    &nbs p;          |
OVRUN   < RB5       RB0 >   OUT0
        |    &nbs p;          |
ACK     > RB4       RB1 >   OUT1
        |    &nbs p;          |
MIDI_IN > RB3       RB2 >   READY
        |    &nbs p;          |
OUT7    < RC5       RC0 >   OUT2
        |    &nbs p;          |
OUT6    < RC4       RC1 >   OUT3
        |    &nbs p;          |
OUT5    < RC3       RC2 >   OUT4
        |    &nbs p;          |

MIDI_IN - input (needs a pull-up)
ACK     - input
READY   - output
OVRUN   - output
OUT0    - output
OUT1    - output
OUT2    - output
OUT3    - output
OUT4    - output
OUT5    - output
OUT6    - output
OUT7    - output

No Watch_dog
#include <16c505.h>
bit ready   @   PORTB.2;
bit midi_in @   PORTB.3;
bit ack     @   PORTB.4;
bit overun  @   PORTB.5;
unsigned char x,rxBuf;
/*---------------------------------------------------------------------- ----*/
void Delay (unsigned char timeout)
/*---------------------------------------------------------------------- ----*/
{    // delay = 3*timeout + 7uS (including call and return)
/*---------------------------------------------------------------------- ----*/
void main (void)
/*---------------------------------------------------------------------- ----*/
    OSCCAL = W;                      // OTP part
//  OSCCAL = 0x80;        & nbsp;         // change for windowed part
    PORTB  = 0;
    TRISB  = 0x18;
    PORTC  = 0;
    TRISC  = 0x00;
    OPTION = 0xC3;      &nb sp;           // <- check it for your appl
    while (1)
        Delay(2);   &n bsp;            &nbs p;  // 2*3+7=13us
        do {
            Delay(5);             ;   // 5*3+7=22us
            Carry=midi_in;          // sample bit
            rxBuf=rr(rxBuf);        // store and count
        } while(!Carry);
        /* no stop-bit check */

1999\10\14@034640 by JP.BROWN

Hi Jose, could you tell us what your midi to parallel convertor was
designed for and what type of C lang. you used.
Thank's  John.

         -----  John P. Brown ----
          \            --- Witty remark goes here ---         /

1999\10\14@141313 by Jose Souto

part 0 2249 bytes
x-html> "JP.BROWN" wrote:
Hi Jose, could you tell us what your midi to parallel convertor was
designed for and what type of C lang. you used.
Thank's  John.
This is a dumb PIC application for somebody who needs to read
4 x serial MIDI inputs and don't have 4 UARTS. With the aid of
4x PIC16C505's and probably 4x 74HC244's plus some I/O lines
can read those MIDI inputs as bytes through an 8 bit bus.
The READY/ACK logic may be inverted to let the Master MCU
use an 74HC138 as the ACK\. I prefer 74HC259's when possible
because they are more flexible.
Since each serial byte takes 10*32us=320us to be read, there is
enough time for the master MCU to check the 4 READY's pins
and read them. There is also an Overrun pin with ACK logic to
report errors.

This was envisioned by me since the 1st <4 x serial MIDI> post
has no clear information about the hardware. I just wrote this
because it's very simple and I had experience with MIDI.

The code is written in a C "dialect" for the CC5X compiler.
You can download a free version from ownload.shtml
It will generate up to 1K code for the midrange PICmicro
      12 bits PIC core : PIC12CXXX, PIC16C5X, PIC16C5XX
      14 bits PIC core : PIC12CXXX, PIC14CXXX, PIC16CXXX, PIC16F8XX

I've been using this compiler because the generated code is
very good and the RAM usage is the best I've seen.
You may generate all Microchip instructions with intrinsic C
functions available. It's the case in the source with:
x = rr(rxBuf);
It will generate:
    rrf     rxBuf,W
    movwf   x

While it's getting the next serial byte it checks the ACK input pin
and when the ACK has gone it drops the READY pin

More... (looser matching)
- Last day of these posts
- In 1999 , 2000 only
- Today
- New search...