2

我如何通过串行端口向 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 系统。当我在我的 PC 上编译代码并运行它时。我明白了:

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

女巫有点毁了我的一天。对于写作和阅读,我正在使用 write & read 功能。我敢打赌这与我打开串口的方式有关。但是有什么不对。我尝试了不同的设置,但收效甚微。在最好的情况下,我得到“?????1???”作为回应。而且大多数时候没有什么可读的。

4

4 回答 4

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 端口尚未初始化为您想要或需要的操作状态,因此没有什么可能按您预期的那样运行。

这是对串行端口进行编程的指南。

于 2013-03-21T19:06:12.987 回答
1

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

这两个是某种初始设计级别检查。有时您最终会重新访问它们:

  • 检查数据表:电压电平是否匹配?例如“真”RS232 vs TTL,12v vs 5v vs 3v
  • 拔掉你的电缆或电路连接:接地,如果差分 TX+/TX- 等匹配,rx 会去 tx 吗?(特别是如果它是定制或手工制作的电缆)

这些更通用:

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

这些是罕见的检查:

  • 检查提供串行外设波特率的任何输入时钟设置。
  • 打破示波器并查看信号是否损坏(您的电平变化如何“方正”,它们是否与您认为的硬件电压电平相匹配)
于 2013-03-21T17:04:28.540 回答
1

除了其他答案中提到的问题外,一个可能的原因是馈入 MCU UART 的预分频器时钟错误。UART 需要 +- 3% 的时钟精度。如果您的预分频器不是那么准确,那么您将遇到问题中描述的那种问题:数据在大多数情况下看起来都很好,然后突然之间就会出现垃圾。

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

于 2013-03-22T07:21:54.533 回答
1

我本质上是一个硬件人,所以当这样的事情发生时,我倾向于从底层开始:

  • 拿出示波器或逻辑分析仪,查看传输的位。检查波特率。检查字符。为您解释位的范围在这里有很大的帮助:)

  • 如果它们正常,请检查字节是否正常进入嵌入式处理器。检查中断服务程序。在进入时设置一个位并在退出前清除它。检查进入的字符是否超出 ISR。

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

于 2013-03-22T12:11:51.930 回答