与LPC1786串行通信

时间:2013-03-21 15:03:40

标签: c linux embedded serial-port lpc

我要通过串口向LPC 1786微控制器发送一些命令。要完成此任务,请使用此代码打开串行端口。

struct termios tio;
int tty_fd;

memset(&tio,0,sizeof(tio));
tio.c_iflag = 0;
tio.c_oflag = 0;
tio.c_cflag = CS8|CREAD|CLOCAL;           // 8n1, see termios.h for more information
tio.c_lflag = 0;
tio.c_cc[VMIN] = 1;
tio.c_cc[VTIME] = 5;

tty_fd = open(device, O_RDWR | O_NONBLOCK);
cfsetospeed(&tio, B9600);            // 115200 baud
cfsetispeed(&tio, B9600);            // 115200 baud
tcflush(tty_fd, TCIFLUSH);

这适用于使用(iMX53)的嵌入式Linux系统。当我在我的电脑上编译代码并运行它。我明白了:

sent:    ?
recieve: Sinchronized<CR><LF>
sent:    Sinchronized<CR><LF>
recieve: Synchronized<CR>OK<CR><LF>
sent:    16000<CR><LF>
recieve: 16000<CR>OK<CR><LF>
女巫很好。当我交叉编译并将其上传到系统时,我得到了这个。

Sent:  ?
HEX:   0x53 0x79 0x6E 0x63 0x68 0x72 0x6F 0x6E 0x69 0x7A 0x65 0x64 0xA 0xA 0x53 0x79 0x6E 0x63 0x68 0x72 0x6F 0x6E 0x69 0x7A 0x65 0xA
ASCII: SynchronizedSynchronizedOKOKnchronized1K024K024chronized1

Sent:  ?
HEX:   0xA 0xA 0xA 0xA 0xA 0xA 0xA 0x30 0xA 0xA 0x31 0xA 0xA 0xA 0xA 0xA 0xA 0x34 0xA 0xA 0x31 0xA 0xA 0xA 0xA 0xA 0xA 0xA 0xA 0xA 0A
ASCII: 014141hronized1111111ronized1
女巫那种废墟我的日子。对于写作和阅读,我正在使用写作和阅读读功能。我打赌这与我打开串口的方式有关。但是错了。我尝试了不同的设置,但收效甚微。在最好的情况下作为回应我得到“????? 1 ???”。大部分时间都没有什么可读的。

4 个答案:

答案 0 :(得分:3)

根本问题是你的代码表明你没有(正确)初始化tty端口。本质上,初始化不会调用tcsetattr()来安装您尝试指定的更新配置。

初始化tty端口的正确方法是打开端口,获取当前属性,在程序退出时保存恢复的当前属性,修改属性以及安装属性。并始终测试系统调用的返回码。

    tty_fd = open(device, O_RDWR | O_NONBLOCK);
    if (tty_fd< 0) {
        syslog(LOG_DEBUG, "failed to open: %d, %s", tty_fd, strerror(errno));
        exit (-1);
    }
    rc = tcgetattr(tty_fd, &tio);
    if (rc < 0) {
        syslog(LOG_DEBUG, "failed to get attr: %d, %s", rc, strerror(errno));
        exit (-2);
    }
    savetio = tio;    /* preserve original settings for restoration */

    spd = B9600;
    cfsetospeed(&tio, (speed_t)spd);
    cfsetispeed(&tio, (speed_t)spd);

    cfmakeraw(&tio);

    tio.c_cc[VMIN] = 1;
    tio.c_cc[VTIME] = 5;

    tio.c_cflag &= ~CSTOPB;
    tio.c_cflag &= ~CRTSCTS;    /* no HW flow control? */
    tio.c_cflag |= CLOCAL | CREAD;
    rc = tcsetattr(tty_fd, TCSANOW, &tio);
    if (rc < 0) {
        syslog(LOG_DEBUG, "failed to set attr: %d, %s", rc, strerror(errno));
        exit (-3);
    }

当然也可能有布线和硬件问题仍有待解决,但由于tty端口尚未初始化为您想要或需要的运行状态,因此没有任何东西可能按预期运行。

以下是programming the serial port的指南。

答案 1 :(得分:1)

这个问题有很多很好的调试评论,但是这里有一个用于检查串行链接的项目的汇总列表:(添加一些我自己的&倾向于开发系统的开发)

这两种是初步的设计级别检查。有时你最终会重新访问它们:

  • 检查数据表:电压电平是否匹配?例如“真”RS232对TTL,12v对5v对3v
  • 熄灭您的电缆或电路连接:接地,如果差分执行TX + / TX-等匹配,rx是否转到tx? (特别是如果它是定制或手工制作的电缆)

这些更为通用:

  • 检查波特率是否匹配
  • 检查两端的数据,停止位和流量控制设置是否匹配
  • 较低的波特率是否有效?
  • 可能尝试备用电缆吗?
  • 可能尝试使用不同的PC(有一个奇怪的接地回路,笔记本电脑的AC电源会导致问题一次)
  • 如果可能,将一端设为“已知良好”数量。

这些是罕见的检查:

  • 检查任何输入时钟设置,以提供串行外设的波特率。
  • 打破范围并查看信号是否已损坏(您的电平变化“方形”如何,它们是否与您认为的硬件电压电平相匹配)

答案 2 :(得分:1)

除了其他答案中提到的问题之外,一个可能的原因是送到MCU UART的预定时器时钟错误。 UART要求时钟精度为±3%。如果您的预缩放器不准确,您将完全问题中描述的问题类型:数据在大多数情况下看起来很好,然后突然间你会变得垃圾。

在对此进行故障排除时,您需要检查接收器侧的超限,帧错误等。检查信号并用示波器测量波特率。如果没有示波器,无法开发嵌入式应用程序,它就像调试器一样重要。

答案 3 :(得分:1)

我是一个内心的硬件人,所以当这样的事情发生时,我倾向于从底部开始:

  • 取出示波器或逻辑分析仪,查看发送的位。检查波特率。检查字符。为您解释这些位的范围在这里是一个巨大的帮助:)

  • 如果没问题,请检查进入嵌入式处理器的字节是否正常。检查中断服务程序。在输入时设置一点并在退出前清除它。检查进入的角色是否没有超过ISR。

从那里开始工作 - 是否有一些低级别的驱动程序从ISR获取数据?