장치 트리 오버레이를 사용하여(시작 시 C 응용 프로그램을 실행하지 않고) SC16IS752(SPI-UART 변환기)가 RS485 모드에서 작동하도록 하려고 합니다.
github의 공식 소스에서 SC16IS752에 대한 원래 적용 범위 소스를 얻었습니다.
줄을 추가하지 않으면 linux,rs485-enabled-at-boot-time;
다음과 같이 작동합니다. (RTS는 항상 높습니다)
이렇게 부품을 변경 fragment@1
하고 RS485를 추가했습니다. (하드웨어에서 14.xxxxMHz가 아닌 1.843200MHz 크리스털을 사용하고 있기 때문에 클럭 주파수도 변경했습니다.)
fragment@1 {
target = <&spi1>;
frag1: __overlay__ {
#address-cells = <1>;
#size-cells = <0>;
pinctrl-names = "default";
pinctrl-0 = <&spi1_pins &spi1_cs_pins>;
cs-gpios = <&gpio 18 1>;
status = "okay";
/* RS485 SUPPORT */
linux,rs485-enabled-at-boot-time;
rs485-rts-delay = <0 0>;
/* RS485 SUPPORT END */
sc16is752: sc16is752@0 {
compatible = "nxp,sc16is752";
reg = <0>; /* CE0 */
clocks = <&sc16is752_clk>;
interrupt-parent = <&gpio>;
interrupts = <24 2>; /* IRQ_TYPE_EDGE_FALLING */
gpio-controller;
gpio-cells = <2>;
spi-max-frequency = <4000000>;
/* I also tried to put it here */
/* but RTS is always HIGH */
/* RS485 SUPPORT */
/* linux,rs485-enabled-at-boot-time; */
/* rs485-rts-delay = <0 0>; */
/* RS485 SUPPORT END */
sc16is752_clk: sc16is752_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <1843200>;
};
};
};
};
파일을 컴파일해서 dts
넣고 오버레이를 사용하기 위해 /boot/overlays
적절한 줄을 추가했습니다 ./boot/config.txt
RTS 라인은 이제 항상 낮습니다(플래그 없음, 높음 - 위 그림 참조).
따라서 이 플래그는 커널/드라이버에서 읽히지만 데이터를 보낼 때 RTS는 아무 작업도 수행하지 않습니다. 다음과 같이 작동해야 합니다:
RS485 모드를 사용한 마지막 스크린샷은 아래와 같이 C 프로그램에서 RS485 모드를 켠 후 찍은 것입니다.
#include <fcntl.h>
#include <unistd.h>
#include <linux/serial.h>
/* Include definition for RS485 ioctls: TIOCGRS485 and TIOCSRS485 */
#include <sys/ioctl.h>
int main(int argc, char *artv[]){
/* Open your specific device (e.g., /dev/mydevice): */
int fd = open ("/dev/ttySC0", O_RDWR);
if (fd < 0) {
/* Error handling. See errno. */
return -1;
}
struct serial_rs485 rs485conf;
/* Enable RS485 mode: */
rs485conf.flags |= SER_RS485_ENABLED;
/* Set logical level for RTS pin equal to 1 when sending: */
rs485conf.flags |= SER_RS485_RTS_ON_SEND;
/* Set logical level for RTS pin equal to 0 after sending: */
rs485conf.flags &= ~(SER_RS485_RTS_AFTER_SEND);
rs485conf.delay_rts_before_send = 0;
rs485conf.delay_rts_after_send = 0; // zero! nie obsługiwane przez SC16IS752
if (ioctl (fd, TIOCSRS485, &rs485conf) < 0) {
/* Error handling. See errno. */
return -2;
}
/* Use read() and write() syscalls here... */
/* Close the device when finished: */
if (close (fd) < 0) {
/* Error handling. See errno. */
return -3;
}
return 0;
}
그래서 질문은C 프로그램을 사용하지 않고 수행하는 방법?
장치 트리에서 rs485 모드를 설정하는 것만으로는 충분하지 않은 이유는 무엇입니까?
드라이버에 기본 구성이 없고 SER_RS485_RTS_ON_SEND 및 SER_RS485_RTS_AFTER_SEND 플래그가 모두 0인 것 같습니다. 이것이 사실이라면 - (보너스 질문) 이 경우 이 드라이버에 대한 문제를 보고해야 합니까?
유용한 리소스:
나중에 수정/추가:
또한 시작 시 오버레이를 적용하고 이 코드를 실행할 때(포트에서 플래그를 읽어야 하는데 올바른지 확실하지 않음)도 확인했습니다.
/* Reading rs485conf struct from port */
if (ioctl (fd, TIOCGRS485, &rs485conf) < 0) {
/* Error handling. See errno. */
return -2;
}
printf("Before: ");
binprintf(rs485conf.flags); // function that prints int as binary
printf("\n");
모든 플래그가 비어 있습니다. 그럼... 부팅 후 오버레이가 RTS 상태를 변경했는데 포트의 플래그가 0인가요? 난 이해가 안 돼요.
답변1
SC16IS752가 RPi의 I2C를 통해 작동하도록 할 때처럼 누구든지 이 문제를 발견하면 간단한 대답은 다음과 같습니다.
- 드라이버 에 설명된
sc16is7xx.c
코드 호출이 없습니다 .uart_get_rs485_mode()
serial_core.c
다른 여러 직렬 드라이버에도 나타납니다. - 장치 트리 속성은
rs485-rts-active-low
RPi 5.3 이상 커널에만 추가된 것으로 보입니다(이 항목 참조).범죄).
첫 번째 문제를 해결하기 위해 드라이버를 약간 변경했습니다 sc16is7xx.c
. 다음을 참조하세요.범죄. 이 uart_get_rs485_mode()
함수는 장치 트리에서 관련 속성을 가져와서 struct serial_rs485
ioctl에서 사용하는 것과 동일하게 에 기록합니다 TIOCSRS485
. 이러한 변경 사항은 아직 회귀 테스트를 거치지 않았지만 현재 내 브레드보드 SC16IS752 인터페이스에서는 안정적으로 작동합니다.
이 커밋은 5.4 커널을 기반으로 하므로 이 rs485-rts-active-low
속성을 지원하므로 MAX3072 라인 드라이버와 잘 작동합니다.
이것은 내 적용 범위 파일의 일부입니다.
fragment@1 {
target = <&i2c_arm>;
__overlay__ {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
sc16is752: sc16is752@48 {
compatible = "nxp,sc16is752";
reg = <0x48>; /* i2c address */
clocks = <&sc16is752_clk>;
interrupt-parent = <&gpio>;
interrupts = <18 2>; /* IRQ_TYPE_EDGE_FALLING */
gpio-controller;
#gpio-cells = <2>;
i2c-max-frequency = <400000>;
linux,rs485-enabled-at-boot-time;
rs485-rts-active-low;
};
};
};
작동 방식을 보여주는 오실로스코프 이미지는 다음과 같습니다.
참고: D8=SCL
, D9=SDA
, D10=_IRQ
, D11=TXD
, D12=_RTS
, D13=RXD
, Analog1=one RS485 line
, Analog2=RXD
(D13과 동일). 명령 응답은 원격 ModBus 장치에서 나옵니다. _RTS
이중 부정이 있기 때문에 전송 중에는 전압이 높다(3.3V)는 점에 유의하세요 .