• CodeSys中编程实现串口通讯【基于树莓派4B】


    第一步:Linux中启用串口设备。【以树莓派4B为例】

       树莓派4B有6个串口,参考上一篇《树莓派4B串口配置与开发》,在 /boot/config.txt 中添加一行,开启 uart2 功能:

      dtoverlay=uart2

       重启后,查看是否有多出来一个 /dev/AMA1 设备:

    $ ls -l  /dev/tty*
    crw-rw---- 1 root dialout 204, 64 Jul 20 11:52 /dev/ttyAMA0
    crw-rw---- 1 root dialout 204, 65 Jul 20 11:59 /dev/ttyAMA1
    crw------- 1 root root      5,  3 Jul 20 11:52 /dev/ttyprintk
    crw--w---- 1 root tty       4, 64 Jul 20 11:52 /dev/ttyS0

      也可以config.txt 中添加多行(uart2,uart3,uart4,uart5)启动多个串口功能 (对应 ttyAMA1,ttyAMA2,ttyAMA3 和 ttyAMA4).

    可以用下面命令查看 uart2 对应的GPIO针脚映射:

    # dtoverlay -h  uart2 
    
    Name:   uart2
    
    Info:   Enable uart 2 on GPIOs 0-3. BCM2711 only.
    
    Usage:  dtoverlay=uart2,
    
    Params: ctsrts                  Enable CTS/RTS on GPIOs 2-3 (default off)

    从输出可见,GPIO针脚为0-3, 其中针脚0和1分别为TxD和RxD,针脚2-3为流控 CTS/RTS.  此处针脚0-1为BCM编码号物理引脚号为27-28.

     

    第二步: 使用python代码,测试 uart2 功能是否正确

       硬件接线: 将 GPIO引脚0 和 1 短接,实现自发自收

       软件测试:python控制台中,执行如下代码测试

    >>> import serial
    >>> ted = serial.Serial(port="/dev/ttyAMA1", baudrate=9600)
    >>> ted.write("Hello World".encode("gbk"))
    11
    >>> ted.read(11)
    b'Hello World'
    >>>

    能收到字串‘Hello World’表示 uart2 功能和接线均一切正常。

     

    第三步:编辑 CodeSys 配置文件,映射 /dev/ttyAMA* 到 COMx 端口号。

       在老版本的CodeSys 中,需要编辑 "/ect/CODESYSControl.cfg" 末尾添加:

    [SysCom]
    Linux.Devicefile = /dev/ttyUSB
    portnum := COM.SysCom.SYS_COMPORT1;

    这样,在codesys中指定串口号1,代表使用的设备为 /dev/ttyUSB0, 非常不直观。

    从codesys v3.5 SP15 起(据说),改为在文件 /etc/CODESYSControl_User.cfg 里这么设置:

    [SysCom]
    Linux.Devicefile.1=/dev/ttyS0
    Linux.Devicefile.2=/dev/ttyAMA1
    Linux.Devicefile.4=/dev/ttyUSB0

    这样, Com1 即为 ttyS0, Com2即为 ttyAMA1, Com4 即为 ttyUSB0,依次类推。支持多个串口,方便多了。 

    如上面设置,映射关系 uart2 --> ttyAMA1 --->  Com2, 所以codesys中指定端口号为 2 (即Com2)即可。 

     

    第四步: CodeSys中编程实现串口收发功能

         参考 youtube 上的学习视频: https://www.youtube.com/watch?v=NFREG2U07Rg

          只需参考codesys编程部分即可,代码我在他基础上又做了修改完善,

    (1)程序块导入3个库: Memory, Serial Communication, Util

    (2)定义部分

    PROGRAM SerialPort
    VAR
        (*打开端口部分*)
    	Open_0: COM.Open;
    	Open_xExecute: BOOL := TRUE;   //默认打开端口
    	aParams : ARRAY [1..7] OF COM.PARAMETER := [
            (udiParameterId := COM.CAA_Parameter_Constants.udiPort,             udiValue := 2),
        	(udiParameterId := COM.CAA_Parameter_Constants.udiBaudrate,         udiValue := 9600),
        	(udiParameterId := COM.CAA_Parameter_Constants.udiParity,           udiValue := INT_TO_UDINT(COM.PARITY.NONE) ),
        	(udiParameterId := COM.CAA_Parameter_Constants.udiStopBits,         udiValue := INT_TO_UDINT(COM.STOPBIT.ONESTOPBIT) ),
       		(udiParameterId := COM.CAA_Parameter_Constants.udiTimeout,          udiValue := 0),
        	(udiParameterId := COM.CAA_Parameter_Constants.udiByteSize,         udiValue := 8),
        	(udiParameterId := COM.CAA_Parameter_Constants.udiBinary,           udiValue := 0)
        ];
    	hCom: CAA.HANDLE;
    	
        (* read模块 *)
    	BLINK0: BLINK;
    	Read_0: COM.Read;
    	bReadData : ARRAY[1..80] OF BYTE;
    	read_szSize: CAA.SIZE;
    	
    	sReadData : STRING;
    	
    	(* write模块 *)
    	Write_0: COM.Write;
    	write_xExecute: BOOL;  //执行write操作
    	bWriteData : ARRAY[1..80] OF BYTE;
    	sWriteData : STRING;
    	sWriteDataLast : STRING;  //上一次 Write值
    END_VAR
    折叠

    (3)梯形图部分

      先要 打开串口 (串口参数在定义部分已预设定):

    注意此处,参数 xExecute 需始终为 True,否则 会关闭串口 hCom=0 !

    读串口部分的代码:

    使用 blink 定期读取,读出的内容放到数组 bReadData 中,读出长度为 read_szSize.

    为了防止读入空(读出为空是常态,有内容 是少数)时 覆盖掉前面值,非空时才拷贝和更新到某个string,代码如下:

    这样,仅在有新内容读出时,才更新值到 sReadData 中。末尾的 MEM.MemFill() 用于写入 string 的结束字符 '\0' .

    下面到了 写串口 的部分。基本思路也是差不多,字符串中有新值时,才将 字符串内容 拷贝到 数组中用于写出,并使能一次写动作,代码如下:

    之后开始真正的 串口写 动作:

    代码后半行,如果写成功,就把此次内容保存到 sWriteDataLast 字串里,用于下一次比较,内容不同时才触发一次 COM.Write() 写动作。

    需要注意的是,若写动作发生error,会一直卡住 不更新 sWriteDataLast,所以加上并联条件 Write_0.xError , 不管成功/Error失败 均结束此次写动作!就算写失败,想再一次尝试,也必须将 sWriteData 改为其他才能再次触发 写动作。

     

    (4)CodeSys中测试串口读写功能

       若串口正确打开, 则 hCom 的值非空,否则 hCom=0 表示失败。

       blink产生的信号定时读一遍数据,有新内容显示在字串 sReadData 中;

       字串 sWriteData 中的内容会通过串口写出去,只有更新 sWriteData 值的瞬间才会触发一次写操作,不管是否写出成功。

     

    以上代码,使用 树莓派4B, Codesys 3.5.18.2 ,Codesys Control for Linux ARM64 SL 测试通过。

     

    使用树莓派 自带的 uart2 (ttyAMA1)和  usb转ttl串口(ttyUSB0) 均测试通过。

     

     

                                                             2022年7月21日

     

     

     

     

  • 相关阅读:
    哪个电脑录屏软件好用又免费?十大好用的免费录屏软件排行
    我看到的“无条件的爱”,常常是子女给父母的
    k8s 基础入门
    BL200EC如何与欧姆龙相连
    Herodotus——无需bridge借助Storage proof实现的以太坊跨层数据访问
    C#SOLID原则(面向对象设计的准则)
    JVM线程的几种状态
    Linux环境下Minio的安装部署与启动教程(完整版)
    《最新出炉》系列入门篇-Python+Playwright自动化测试-46-鼠标滚轮操作
    Shiro之缓存管理
  • 原文地址:https://www.cnblogs.com/zhw618/p/16502058.html