Question

I'm using a pc1602f PowerTip directly connected to the PC parallel port using this scheme: http://www.beyondlogic.org/parlcd/parlcd.htm

All well as energizes the LCD and shows me the front row with black blocks, until then fine but now I want to send information through the parallel port.

If you look at the page you will see that there is a source to send information to the lcd, but uses windows libraries: huh:

I leave my code attempted to become linux.

#include <stdio.h>   
#include <string.h>  
#include <unistd.h>  
#include <fcntl.h>   
#include <errno.h>   
#include <termios.h> 
#include <stdlib.h>
#include <unistd.h>
#include <sys/io.h>
#define PORTADDRESS 0x3f8
#define DATA PORTADDRESS+0
#define STATUS PORTADDRESS+1
#define CONTROL PORTADDRESS+2

main(int argc, char **argv)
{char string[] = {"Testing 1,2,3"};

    int count;
    int len;

    char init[10];
    init[0] = 0x0F; /* Init Display */
    init[1] = 0x01; /* Clear Display */
    init[2] = 0x38; /* Dual Line / 8 Bits */

    if (ioperm(PORTADDRESS,1,1))
        fprintf(stderr, "No se puede acceder al: %x\n", PORTADDRESS), exit(1);

    outb(CONTROL, inb(CONTROL) & 0xDF); 
    outb(CONTROL, inb(CONTROL) & 0x08);


    for (count = 0; count <= 2; count++)
    {

        outb(DATA, init[count]);
        outb(CONTROL,inb(CONTROL) | 0x01); 
        sleep(20);                                 
        outb(CONTROL,inb(CONTROL) & 0xFE); 
        sleep(20);                                  
    }
    outb(CONTROL, inb(CONTROL) & 0xF7);  

    len = strlen(string);

    for (count = 0; count < len; count++)
    {
        outb(DATA, string[count]);
        outb(CONTROL,inb(CONTROL) | 0x01); 
        sleep(2);
        outb(CONTROL,inb(CONTROL) & 0xFE); 
        sleep(2);
    }

}

Compiles perfectly but when I want to try it as root and run it throws me

root@ubuntu: /

media/E80C-30D5/LCD/build #./lcd

Segmentation fault (`core 'generated)

root@ubuntu: /media/E80C-30D5/LCD/build #

Looking at dmesg I find this.

[3176.691837] lcd [3867] general protection ip: 400cb4 sp: 7fff887ad290 error: 0 in lcd [+2000 400 000]root@ubuntu: / media/E80C-30D5/LCD/build #

I put the dmesg log of ttyS*

root @ ubuntu: / media/E80C-30D5/LCD/build # dmesg | grep ttyS
[2.335717] serial8250: ttyS0 at I / O 0x3f8 (irq = 4) is a 16550A
[2.335817] serial8250: ttyS1 at I / O 0x2f8 (irq = 3) is a 16550A
[2.336100] 00:0 b: ttyS1 at I / O 0x2f8 (irq = 3) is a 16550A
[2.336207] 00:0 c: ttyS0 at I / O 0x3f8 (irq = 4) is a 16550A
root @ ubuntu: / media/E80C-30D5/LCD/build #

Do not get it to run, you can help me please?

Was it helpful?

Solution

I agree with others that you should write to the appropriate device file rather than perform I/O directly, if possible.

However, for the sake of completeness:

ioperm(PORTADDRESS,1,1)

should be

ioperm(PORTADDRESS,4,1)

Also, use parentheses to avoid bugs that results from incorrect macro expansion, like this:

#define PORTADDRESS (0x3f8)
#define DATA        (PORTADDRESS+0)
#define STATUS      (PORTADDRESS+1)
#define CONTROL     (PORTADDRESS+2)

OTHER TIPS

The code you're trying to run will not run in a "modern" operating system. Linux and versions of Windows after 16-bit will not let you perform operations that directly access ports or memory. Access to memory goes through a memory manager so the addresses you're specifying are not really the ones you end up accessing; and ports are accessed only by device drivers that are part of the operating system's kernel.

I'm not very sure, but if your main purpose is just to output some bytes via the serial port, then most of your code is not necessary, as you can simply write to a file that wraps the device driver to the port. There's a little more detail on this in this article.

If you really need to do bit-twiddling with the serial port chips, you can find some more information in the bottom line of this serial port mini-howto. Be warned that writing your own device driver is considered advanced.


EDIT: I just noticed your question mentions the parallel port but the port number in your code (3F8) is that for one of the serial ports. Hint: If the plug you're connecting to is a 9 pin port, then it's definitely a serial port. If it's a 25 pin port and female (holes, not pins) then it's probably a parallel port, if male it's probably a serial port. Or you could measure voltages: Serial port signals go up to +/- 9V or so, while the parallel port signals are from 0 to 5V.

Instead of writing to an address outside your address space (which would make it PC-only if it would work), just write to a file (/dev/lp0, or wherever your parport is) instead.
Your LCD seems to talk serial, so why not use the serial port instead? Then your program would write to /dev/ttyS0 or something similar.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top