views:

37

answers:

3

Hello everyone,

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?

+1  A: 

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.

Carl Smotricz
A: 

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.

MattBianco
Sorry. Your LCD does *not* seem to talk serial. I was confused by your question subject.
MattBianco
uhm, begin if not as a kernel module design for the LCD device or design a code to send in the form of loose bits word in hex
Backglass
A: 

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)
Artelius
This one well is necessary to design a module in order that it works or it is possible to do perfectly activating diverse bits of the port?
Backglass
Maybe someone has already written a driver. See if http://lcd-linux.sourceforge.net/ is any good. Also, does my suggestion fix your problem?
Artelius