News:

PROTON pic BASIC Compilers for PIC, PIC24, dsPIC33

Main Menu

Parallel to Serial Converter

Started by Teo, Mar 18, 2026, 09:30 PM

Previous topic - Next topic

Teo

Hello everyone,
Has anyone tried to make a parallel-serial converter for a printer?
I would use PIC18F26K22 with the output on 115200 bps.
The first UART1 serial port should be the input for some command signals and the second UART2 is the output of the Parallel to Serial conversion.
Thanks in advance,
Teo

RGV250


Teo

#2
Thank you Bob,
Something similar but I will do it with the PIC18F26K22 using, of course, the wonderful POSITRON.
Regards,
Teo

top204

#3
I've converted that simple C code in the link, into Positron8 for a PIC18F26K22 device, that uses a serial receive buffer via an interrupt, so no data is lost, and the code listing is below:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Paralelloslam adaption to Positron8, that is a serial to parallel interface for a printer.
' Original Programming & Hardware by Cosmos2000 & TK.
' Inspired by sentryGun53.
'
' This code uses an interrupt driven serial receive buffer, so no data is lost.
' Written for the Positron8 compiler by Les Johnson.
' https://sites.google.com/view/rosetta-tech/positron-compilers-experimenters-notebook
'
    Device = 18F26K22                                                   ' Tell the compiler what device to compile for
    Declare Xtal = 64                                                   ' Tell the compiler what frequency the device will be operating at (in MHz)
    Declare Auto_Heap_Arrays = On                                       ' Tell the compiler to create arrays above standard variables, so assembler code is more efficient
    Declare Auto_Variable_Bank_Cross = On                               ' Tell the compiler to create any multi-byte variables in the same RAM bank. For more efficiency
    On_Hardware_Interrupt GoTo ISR_Handler                              ' Point the interrupt vector to the interrupt handler routine
'
' Setup the RX1 and TX1 pins for the interrupt
'
$define TX1_Pin PORTC.6                                                 ' Define the USART1 TX pin to enable the USART1 interrupt and procedures
$define RX1_Pin PORTC.7                                                 ' Define the USART1 RX pin to enable the USART1 interrupt and procedures
'
' Setup USART1
'
    Declare HSerial1_Baud = 9600                                        ' Set the Baud rate of USART1
    Declare HSerout1_Pin  = TX1_Pin                                     ' Designate the USART1 TX pin
    Declare HSerin1_Pin   = RX1_Pin                                     ' Designate the USART1 RX pin

    Include "Buffered_USARTs.inc"                                       ' Load the USART1 and USART2 interrupt serial RX buffers into the program

$define Par_Data_Port PORTB                                             ' The port that the parallel data lines are on
$define Data0_Pin   PORTB.0                                             ' \
$define Data1_Pin   PORTB.1                                             ' |
$define Data2_Pin   PORTB.2                                             ' |
$define Data3_Pin   PORTB.3                                             ' | The pins of the parallel port
$define Data4_Pin   PORTB.4                                             ' |
$define Data5_Pin   PORTB.5                                             ' |
$define Data6_Pin   PORTB.6                                             ' |
$define Data7_Pin   PORTB.7                                             ' /

$define nStrobe_Pin PORTC.2
$define nAck_Pin    PORTC.3
$define Busy_Pin    PORTC.4
$define CTS_Pin     PORTC.5
$define Pwr_LED_Pin PORTA.2
'
' Create global variables, constants and aliases here
'
    Symbol cStrobeWaitUs = 2                                            ' Microseconds to strobe for
    Dim Bytein As Byte

'----------------------------------------------------------------------------
' The main program starts here
' Wait for serial data and transfer it to a parallel interface
'
Main:
    Setup()                                                             ' Setup the program and any peripherals

    Do                                                                  ' Create a loop
        If USART1_DataAvailable() = True Then                           ' Is there a byte in the USART1 serial buffer?
            USART1_ByteInBuffer = False                                 ' Yes. So reset the flag
            If Busy_Pin = 0 Then                                        ' Is the busy pin low?
                Bytein = HRsin                                          ' Yes. So read the serial data
                PrintByte(Bytein)                                       ' Send it to the parallel port
            EndIf
        EndIf
        If Busy_Pin = 1 Then                                            ' Is the busy pin high?
            PinSet CTS_Pin                                              ' Yes. So set the CTS pin high
        Else                                                            ' Otherwise...
            PinClear CTS_Pin                                            ' Pull the CTS pin low
        EndIf
    Loop                                                                ' Do it forever

'----------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    Osc_64MHz()                                                         ' Set the device to 64MHz operation using its internal oscillator
    USART1_Open()                                                       ' Setup and open USART1 for interrupt RX
    PinHigh nStrobe_Pin                                                 ' Is active Low
    Low Par_Data_Port                                                   ' Make the parallel data pins all low
    PinInput nAck_Pin                                                   ' Is active Low
    PinInput Busy_Pin
    PinLow CTS_Pin
    DelayMs 500
    PinHigh Pwr_LED_Pin
    IntPeriph_Enable()                                                  ' Enable peripheral interrupts
    IntGlobal_Enable()                                                  ' Enable global interrupts
EndProc

'----------------------------------------------------------------------------
' Send a byte to the parallel interface
' Input     : pValue holds teh 8-bit value to write to the parallel port
' Output    : None
' Notes     : None
'
Proc PrintByte(pValue As Byte)
    Par_Data_Port = pValue                                              ' Transfer the value to the data pins
    PinClear nStrobe_Pin                                                ' \
    DelayUs cStrobeWaitUs                                               ' | Strobe the nStrobe_Pin to input data bits
    PinSet nStrobe_Pin                                                  ' /
EndPRoc

'----------------------------------------------------------------------------
' Set a printer to emphasised mode
' Input     : None
' Output    : None
' Notes     : None
'
Proc ResetPrinter()
    PrintByte(27)                                                       ' Reset printer to emphasised mode
    PrintByte("E")                                                      ' 27 is Escape & "E" = Dec 69 for Emphasised mode
EndProc

'---------------------------------------------------------------------------------------------
' Set the PIC18F26K22 device to 64MHz operation using its internal oscillator
' Input     : None
' Output    : None
' Notes     : None
'
Proc Osc_64MHz()
    OSCCON  = $70
    OSCCON2 = $04
    OSCTUNE = $40
    DelayMS 100
EndProc

'---------------------------------------------------------------------------------------------
' Interrupt handler
' Input     : None
' Output    : USART1_ByteInBuffer is true if a byte is received in USART1 buffer (must be cleared in the main program when completed)
' Notes     :
'
ISR_Handler:
    Context Save, FSR1L, FSR1H
'
' USART1 serial RX buffer
'
    If USART1_RX_Flag() = True Then                                     ' Was it a USART1 byte receive that triggered the interrupt?
        WREG = RC1STA & %00000110                                       ' Yes. So mask out unwanted bits and check for errors
        If STATUSbits_Z = 0 Then                                        ' Are there any bits set in RC1STA?
            WREG = RC1REG                                               ' \ Yes. So empty the 2 byte USART1 buffer
            WREG = RC1REG                                               ' /
            RC1STAbits_CREN = 0                                         ' \ Clear receiver status
            RC1STAbits_CREN = 1                                         ' /
        Else                                                            ' Otherwise... No error so...
            USARTx_bRXByte = RC1REG                                     ' Place the byte received into a variable
            USART1_ByteInBuffer = True                                  ' Indicate that a byte is in the serial buffer
            Inc USART1_bIndexIn                                         ' Move up the buffer
            If USART1_bIndexIn >= _cUSART1_BufferSize Then              ' End of buffer reached?
                USART1_bIndexIn = 0                                     ' Yes. So reset USART1_bIndexIn
            EndIf
            USART_wFSR1 = AddressOf(USART1_bRingBuffer)                 ' Point FSR1L\H to USART1_bRingBuffer
            USART_wFSR1 = USART_wFSR1 + USART1_bIndexIn                 ' Add the buffer position to FSR1L\H
            INDF1 = USARTx_bRXByte                                      ' Place the received byte into the buffer
        EndIf
    EndIf

    Context Restore

'---------------------------------------------------------------------------------------------
' Setup the fuses to use the internal oscillator on a PIC18Fx6K22 devices.
' OSC pins RA6 and RA7 are general purpose I/O.
'
Config_Start
    FOSC     = INTIO67                                                  ' Internal oscillator
    PRICLKEN = Off                                                      ' Primary clock disabled
    MCLRE    = EXTMCLR                                                  ' MCLR pin enabled
    WDTEN    = Off                                                      ' Watchdog Timer disabled
    PLLCFG   = Off                                                      ' Oscillator used directly
    FCMEN    = Off                                                      ' Fail-Safe Clock Monitor disabled
    IESO     = Off                                                      ' Oscillator Switchover mode disabled
    PWRTEN   = On                                                       ' Power up timer enabled
    BOREN    = Off                                                      ' Brown-out Reset disabled
    BORV     = 190                                                      ' VBOR set to 1.9 V nominal
    WDTPS    = 128                                                      ' Watchdog Timer Postscale is 1:128
    HFOFST   = Off                                                      ' The Access clock is not held Off until the HF-INTOSC is stable
    PBADEN   = Off                                                      ' PORTB<4:0> pins are configured as digital on reset
    CCP2MX   = PORTC1                                                   ' CCP2 input/output is multiplexed with RC1
    CCP3MX   = PORTB5                                                   ' P3A/CCP3 input/output is multiplexed with RB5
    T3CMX    = PORTC0                                                   ' T3CKI is on RC0
    P2BMX    = PORTB5                                                   ' P2B is on RB5
    STVREN   = On                                                       ' Stack full/underflow will cause a reset
    LVP      = Off                                                      ' Single-Supply ICSP disabled
    Debug    = Off                                                      ' Background debugger disabled. RB6 and RB7 configured as general purpose I/O pins
    XINST    = Off                                                      ' Extra mnemonics disabled
    Cp0      = Off                                                      ' Block 0 (000800-001FFF) not code protected
    CP1      = Off                                                      ' Block 1 (002000-003FFF) not code protected
    CPB      = Off                                                      ' Boot block (000000-0007FF) not code protected
    CPD      = Off                                                      ' Data EEPROM not code protected
    WRT0     = Off                                                      ' Block 0 (000800-001FFF) not write protected
    WRT1     = Off                                                      ' Block 1 (002000-003FFF) not write protected
    WRTB     = Off                                                      ' Boot block (000000-0007FF) not write protected
    WRTC     = On                                                       ' Configuration registers (300000-3000FF) write protected
    WRTD     = Off                                                      ' Data EEPROM not write protected
    EBTR0    = Off                                                      ' Block 0 (000800-001FFF) not protected from table reads executed in other blocks
    EBTR1    = Off                                                      ' Block 1 (002000-003FFF) not protected from table reads executed in other blocks
    EBTRB    = Off                                                      ' Boot block (000000-0007FFh) not protected from table reads executed in other blocks
Config_End

The device needs no external crystal, but will require a high resistance (approx 150K) pull-up resistor on the RX pin (PORTC.7), so that is it not floating, but, also, not pulling too hard.

Below is a screenshot of the program operating in the proteus simulator:

Ser_To_Par_Screenshot.jpg

The source codes and the proteus project files are attached to this post. Hopefully, it will give you ideas for your serial to parallel interface.

Regards
Les

Teo

Hi Les,
Many thanks. You are brilliant.
Next, I am going to do the alternative reception of the data on UART2 with "BUSY" control.
I think using interrupts for serial reception would be a good idea.
This data needs to be modified and transmitted through UART 1.
I wish you a peaceful evening.
With friendship,
Teo