【问题标题】:Serial communication with LPC1786与 LPC1786 的串行通信
【发布时间】:2013-03-21 15:03:39
【问题描述】:

我如何通过串行端口向 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???”作为回应。而且大多数时候没有什么可读的。

【问题讨论】:

  • 你运行的波特率是多少?这类问题总是有波特率不匹配的味道。我在您的代码中看到 9600,在评论中看到 115200 并且不知道它在主机端是什么:P
  • 我正在测试不同的速度。主机 -> 速度 9600 波特;stty:/dev/ttymxc4 intr = ^C;退出 = ^\;擦除 = ^?;杀死 = ^U; eof = ^D; eol = ; eol2 = ;开始 = ^Q;停止 = ^S;悬念 = ^Z; rprnt = ^R;错误 = ^W;下一个 = ^V;冲洗 = ^O;最小值 = 1;时间=0; -parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts -ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc -ixany -imaxbel opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0 isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke
  • 这很奇怪。你确定你的处理器的输入时钟是正确的吗?
  • 是的,时钟是正确的。我认为这与 有关。因为从 LPC 的输出中我们可以读取“同步”,如果速度或回合率出现问题,我们会在那里看到“猴子”字符串。我正在根据 解析响应,并且没有一个简单的响应。
  • 很公平。老实说,我不知道其他情况,除非你的电缆有点坏。您使用的是哪个开发板,还是定制设计?

标签: c linux embedded serial-port lpc


【解决方案1】:

根本问题是您的代码表明您没有(正确)初始化 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 的指南。

【讨论】:

  • 不调用 tcsetattr 是主要问题。我浏览了指南并实施了一些更改。我觉得很愚蠢……我花了多少时间在这个 grrr 上。现在它工作正常。谢谢。
【解决方案2】:

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

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

  • 查看数据表:电压电平是否匹配?例如“真”RS232 vs TTL,12v vs 5v vs 3v
  • 断开电缆或电路连接:接地,如果差分进行 TX+/TX- 等匹配,rx 是否会转到 tx? (尤其是定制或手工制作的电缆)

这些更通用:

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

这些是比较少见的检查:

  • 检查提供串行外设波特率的任何输入时钟设置。
  • 拆开示波器,查看信号是否损坏(您的电平变化有多“方正”,它们是否与您认为的硬件电压电平相匹配)

【讨论】:

    【解决方案3】:

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

    解决此问题时,您需要检查接收器端的溢出、帧错误等。检查信号并用示波器测量波特率。您无法在没有示波器的情况下开发嵌入式应用程序,它与调试器一样重要。

    【讨论】:

      【解决方案4】:

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

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

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

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

      【讨论】:

      • 这是一个很好的建议。当我告诉他这个问题时,这就是我的一位高级同事所做的。
      猜你喜欢
      • 1970-01-01
      • 2012-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多