RS232 算是比較簡單的介面,實際上所需要設定的部分也不多。我們先來看看原理圖與spec。
在這邊假設如果你的 RS232 腳位選擇 PD0 與 PD3 , 那接下來我們就可以去看看 mp1 的 spec。
從Spec 中可以找到 PD0 是 UART7 , 對應的我們需要去找到 UART7 的 AF 表格以及 UART7 在設備樹當中的位置。
uart7_idle_pins_mx: uart7_idle_mx-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 0, AF6)>; /* UART7_RX */
bias-disable;
drive-push-pull;
};
pins2 {
pinmux = <STM32_PINMUX('D', 3, ANALOG)>; /* UART7_TX */
};
};
下方的說明是替代功能怎麼看得,可以參照上方的圖片來看AF6 就是 UART。
STM32_PINMUX('D', 0, AF6)
## 'D' 表示 P'D'0
## '0' 表示 PD'0'
## AF6 是替代功能 6
需要透過 pinctrl 控制器來控制,所以我們要先定義在 pinctrl 設備樹當中。定義如下:
uart7_pins_mx: uart7_mx-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 0, AF6)>; /* UART7_RX */
bias-disable;
drive-push-pull;
};
pins2 {
pinmux = <STM32_PINMUX('D', 3, AF6)>; /* UART7_TX */
bias-disable;
drive-push-pull;
slew-rate = <0>;
};
};
uart7_idle_pins_mx: uart7_idle_mx-0 {
pins1 {
pinmux = <STM32_PINMUX('D', 0, AF6)>; /* UART7_RX */
bias-disable;
drive-push-pull;
};
pins2 {
pinmux = <STM32_PINMUX('D', 3, ANALOG)>; /* UART7_TX */
};
};
uart7_sleep_pins_mx: uart7_sleep_mx-0 {
pins {
pinmux = <STM32_PINMUX('D', 0, ANALOG)>, /* UART7_RX */
<STM32_PINMUX('D', 3, ANALOG)>; /* UART7_TX */
};
};
上方只是定義他的群組與用途,實際上功能會寫在pinctrl外面。透過 & 去 reference
&uart7{
pinctrl-names = "default", "idle", "sleep";
#下方的 pinctrl 0 1 2 , 就是我們上面所定義的分組 ,
#會依照 default idle sleep 去切換不同的使用分組設定
pinctrl-0 = <&uart7_pins_mx>;
pinctrl-1 = <&uart7_idle_pins_mx>;
pinctrl-2 = <&uart7_sleep_pins_mx>;
status = "okay";
};
最後在最上方的 aliases 當中要修改,原先是公板使用 usart6 , 我們要換成 uart7。
aliases {
serial1 = &uart7;
};
接收端程式
/* rs232_recv.c */
#include
#include
#include
#include
#include
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS1"
#define _POSIX_SOURCE 1
int main()
{
int fd, c=0, res;
struct termios oldtio, newtio;
char buf[256];
printf("Start...\n");
fd = open(MODEMDEVICE, O_RDWR|O_NOCTTY);
if (fd < 0) {
perror(MODEMDEVICE);
exit(1);
}
printf("Open...\n");
tcgetattr(fd, &oldtio);
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE|CS8|CLOCAL|CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
printf("Reading...\n");
while(1) {
res = read(fd, buf, 255);
buf[res]=0;
printf("res=%d buf=%s\n", res, buf);
if (buf[0] == '@') break;
}
printf("Close...\n");
close(fd);
tcsetattr(fd, TCSANOW, &oldtio);
return 0;
}
傳送端
/* rs232_send.c */
#include
#include
#include
#include
#include
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1
#define STOP '@'
int main()
{
int fd, c=0, res;
struct termios oldtio, newtio;
char ch;
static char s1[20];
printf("Start...\n");
fd = open(MODEMDEVICE, O_RDWR|O_NOCTTY);
if (fd < 0) {
perror(MODEMDEVICE);
exit(1);
}
printf("Open...\n");
tcgetattr(fd, &oldtio);
bzero(&newtio, sizeof(newtio));
newtio.c_cflag = BAUDRATE|CS8|CLOCAL|CREAD;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = ICANON;
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
printf("Writing...\n");
while(1) {
while((ch=getchar()) != STOP) {
s1[0]=ch;
res=write(fd, s1, 1);
}
s1[0]=ch;
s1[1]='\n';
res = write(fd, s1, 2);
break;
}
printf("Close...\n");
close(fd);
tcsetattr(fd, TCSANOW, &oldtio);
return 0;
}
可以直接透過指令來傳送
dmesg | grep "ttySTM"
fdtget /path/to/stm32mp1.dtb / full # 可以列出所有節點
stty -F /dev/ttyS1 # 可以查看串口設定
stty -F /dev/ttySTM1 115200 cs8 -parenb -cstopb
stty -F /dev/ttySTM1 -ixon -ixoff -crtscts
echo "helloword" > /dev/ttyS0 && cat /dev/ttyS0