接口定义
整机接口定义
LBA3588S提供了丰富的接口,具体如下图

| 丝印 | 设备节点 | 备注 |
|---|---|---|
| USB1 | Type-A USB3.0 host | |
| USB2 | Type-A USB3.0 host | |
| USB3 | Type-A USB3.0 host | |
| PWR LED | 电源灯 | |
| 4G LED | 4G灯 4G/5G 拨号 | |
| SYS LED | work1 | 系统灯 |
| STA LED | work2 | STA灯 |
| RS485 | /dev/ttyS9 | 串口,默认波特率9600 |
| UART1 | /dev/ttyS4 | 串口,默认波特率9600 |
| UART2 | /dev/ttyS6 | 串口,默认波特率9600 |
| RS232_1 | /dev/ttysWK0 | 串口RS232,默认波特率9600 |
| RS232_2 | /dev/ttysWK1 | 串口RS232,默认波特率9600 |
| RS232_3 | /dev/ttysWK2 | 串口RS232,默认波特率9600 |
| RS232_4 | /dev/ttysWK3 | 串口RS232,默认波特率9600 |
| HDMI | card0-HDMI-A-1 | HDMI输出,最高支持4K@60fps |
| Type-C | 可转接USB和DP信号 | |
| MIC | 输入声音,录制音频文件 | |
| LINE | 播放音频文件 | |
| ETH | eth0 | 千兆网卡 |
| WIFI | wlan0 | 2.4/5GHz |
UART 使用
串口是一种常见的通信接口,用于与外部设备进行串行通信。LBA3588S提供了多个串口,分别对应不同的设备节点。在使用串口之前,需要确保串口连接正确,以及波特率和其他参数设置一致。
RS485设备文件为/dev/ttyS9。在开发板设备上运行下列命令:
发送字符串到主机
- Cmd
- C
echo "neardi RS485 test..." > /dev/ttyS9
create serial_send.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <string.h>
#include <stdlib.h>
void usage(const char *prog_name) {
printf("Usage: %s <port> <message> [baudrate] [timeout]\n", prog_name);
printf(" <port> - The serial port to use (e.g., /dev/ttyS0)\n");
printf(" <message> - The message to send\n");
printf(" [baudrate] - The baud rate (optional, default is 9600)\n");
printf(" [timeout] - The timeout in seconds (optional, default is 1)\n");
}
int main(int argc, char *argv[]) {
if (argc < 3) {
usage(argv[0]);
return 1;
}
const char *port = argv[1];
const char *message = argv[2];
int baudrate = (argc > 3) ? atoi(argv[3]) : 9600;
int timeout = (argc > 4) ? atoi(argv[4]) : 1;
int fd = open(port, O_WRONLY | O_NOCTTY | O_SYNC);
if (fd == -1) {
perror("Unable to open serial port");
return 1;
}
// Set serial port configuration
struct termios tty;
if (tcgetattr(fd, &tty) != 0) {
perror("Error getting serial port attributes");
close(fd);
return 1;
}
// Set baud rate
cfsetospeed(&tty, baudrate);
cfsetispeed(&tty, baudrate);
// Set serial port mode
tty.c_cflag &= ~PARENB; // No checksum
tty.c_cflag &= ~CSTOPB; // 1 stop bit
tty.c_cflag &= ~CSIZE; // Clear character bit settings
tty.c_cflag |= CS8; // 8 data bits
tty.c_cflag |= CREAD | CLOCAL; // Start the receiver, ignore control lines
// Set timeout
tty.c_cc[VTIME] = timeout; // Read operation timeout (10ms unit)
tty.c_cc[VMIN] = 0; // Read without waiting for characters
// Apply serial port settings
if (tcsetattr(fd, TCSANOW, &tty) != 0) {
perror("Error setting serial port attributes");
close(fd);
return 1;
}
// Send data
write(fd, message, strlen(message));
printf("Message sent: %s\n", message);
// Close serial port
close(fd);
return 0;
}
gcc -o serial_send serial_send.c
./serial_send /dev/ttyS9 "neardi RS485 test ..." 9600 1
主机中的串口终端即可接收到字符串 “neardi RS485 test…” 开发板接收数据:
接收主机发送的字符串
- Cmd
- C
cat /dev/ttyS9
create serial_reader.c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#define DEFAULT_SERIAL_PORT "/dev/ttyS0"
#define DEFAULT_BAUD_RATE 115200
// Map baud rate string to corresponding baud rate constant
speed_t get_baud_rate(int baud) {
switch (baud) {
case 9600:
return B9600;
case 19200:
return B19200;
case 38400:
return B38400;
case 57600:
return B57600;
case 115200:
return B115200;
case 230400:
return B230400;
case 460800:
return B460800;
case 921600:
return B921600;
default:
return B115200; // Default baud rate 115200
}
}
// Print help information
void print_usage() {
printf("Usage: serial_reader -p <port> -b <baud_rate>\n");
printf(" -p <port> Serial port device (default: /dev/ttyS9)\n");
printf(" -b <baud_rate> Baud rate (default: 115200)\n");
}
int main(int argc, char *argv[]) {
int baud_rate = DEFAULT_BAUD_RATE;
const char *serial_port = DEFAULT_SERIAL_PORT;
// Parse command line arguments
int opt;
while ((opt = getopt(argc, argv, "p:b:h")) != -1) {
switch (opt) {
case 'p':
serial_port = optarg;
break;
case 'b':
baud_rate = atoi(optarg);
if (baud_rate <= 0) {
fprintf(stderr, "Invalid baud rate: %s\n", optarg);
print_usage();
return 1;
}
break;
case 'h':
default:
print_usage();
return 0;
}
}
// Open serial device
int serial_fd = open(serial_port, O_RDONLY | O_NOCTTY);
if (serial_fd == -1) {
perror("Failed to open the serial port");
return 1;
}
// Set serial port parameters
struct termios tty;
if (tcgetattr(serial_fd, &tty) != 0) {
perror("Failed to get serial port attributes");
close(serial_fd);
return 1;
}
// Configure baud rate
speed_t baud = get_baud_rate(baud_rate);
cfsetospeed(&tty, baud); // Set output baud rate
cfsetispeed(&tty, baud); // Set input baud rate
// Configure serial port
tty.c_cflag &= ~PARENB; // Disable parity checking
tty.c_cflag &= ~CSTOPB; // 1 stop bit
tty.c_cflag &= ~CSIZE; // Clear data bit mask
tty.c_cflag |= CS8; // 8 data bits
tty.c_cflag &= ~CRTSCTS; // Disable hardware flow control
tty.c_cflag |= CREAD | CLOCAL; // Enable receive and local connections
tty.c_iflag &= ~(IXON | IXOFF | IXANY); // Disable software flow control
tty.c_iflag &= ~ICANON; // Disable canonical mode
tty.c_iflag &= ~ECHO; // Disable echo
tty.c_iflag &= ~ECHOE; // Disable echo input
tty.c_iflag &= ~ISIG; // Disable signal characters
tty.c_oflag &= ~OPOST; // Disable output processing
tty.c_oflag &= ~ONLCR; // Disable newline conversion
// Application serial port configuration
if (tcsetattr(serial_fd, TCSANOW, &tty) != 0) {
perror("Failed to set serial port attributes");
close(serial_fd);
return 1;
}
// Loop to read serial port data and output
char read_buffer[256];
while (1) {
int n = read(serial_fd, read_buffer, sizeof(read_buffer) - 1);
if (n < 0) {
perror("Failed to read from the serial port");
close(serial_fd);
return 1;
} else if (n == 0) {
continue; // No data to read, continue looping
}
read_buffer[n] = '\0'; // Make sure the string ends
printf("%s", read_buffer); // Output the read data
}
close(serial_fd);
return 0;
}
gcc -o serial_reader serial_reader.c
./serial_reader -p /dev/ttyS9 -b 9600
同样,UART1和UART2设备文件分别是/dev/ttyS4和/dev/ttyS6。
RS232 使用
RS232使用方法与RS485、UART1和UART2类似,只需替换设备文件即可。
HDMI/DP 说明
xrandx命令可以查看当前HDMI连接:
neardi@3588:~$ xrandr
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 16384 x 16384
HDMI-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
1920x1080 60.00*+ 60.00 50.00 30.00 24.00
4096x2160 24.00
3840x2160 30.00 25.00 24.00
1920x1080i 60.00 50.00
1280x720 60.00 60.00 50.00 50.00 30.00 24.00
720x576 50.00 50.00
720x480 59.94 59.94 59.94
DP-1 disconnected (normal left inverted right x axis y axis)
完整节点:
HDMI1:/sys/devices/platform/display-subsystem/drm/card0/card0-HDMI-A-1/
DP:/sys/devices/platform/display-subsystem/drm/card0/card0-DP-2/
ETH 说明
可以通过调试串口、ssh或者adb来查看IP地址,例如:
neardi@3588:~$ ifconfig -a
enP2p33s0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.1.65 netmask 255.255.255.0 broadcast 192.168.1.255
inet6 fe80::7df7:e74d:497e:345d prefixlen 64 scopeid 0x20<link>
ether 62:ea:fb:ca:95:e7 txqueuelen 1000 (Ethernet)
RX packets 2548 bytes 210938 (210.9 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 338 bytes 46899 (46.8 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
device interrupt 140 base 0xd000
Wi-Fi 说明
通过如下命令查看当前Wi-Fi型号:
cat /sys/bus/sdio/devices/mmc2\:0001\:1/vendor
cat /sys/bus/sdio/devices/mmc2\:0001\:1/device
0x02d0:0xaae8:AP6275S.0x024c:0xb852:RTL8852.0x024c:0xd723:RTL8723DS.0x024c:0xc821:RTL8821CS.0x1ffe:0x6316:FD7352S。
Connect Wi-Fi:
-
Cmd
-
C
-
Search Wi-Fi:
sudo nmcli device wifi rescan
- Show all Wi-Fi:
nmcli dev wifi list
- Connect Wi-Fi:
sudo nmcli device wifi connect neardi_5G password neardi_pwd
• neardi_5G 是WiFi 网络(SSID) 的名称。
• neardi_pwd 是连接到该WiFi 网络所需的密码。
• sudo 用于确保nmcli 具有管理网络连接所需的权限,因为在某些系统上连接到WiFi 网络可能需要管理权限。
create connect_wifi.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void connect_to_wifi(const char *ssid, const char *password) {
char command[256];
// Create the WPA configuration file without the -e option
snprintf(command, sizeof(command), "echo 'network={\\n ssid=\"%s\"\\n psk=\"%s\"\\n}' | sudo tee /etc/wpa_supplicant/wpa_supplicant.conf", ssid, password);
if (system(command) != 0) {
perror("Failed to create wpa_supplicant.conf");
return;
}
// Run wpa_supplicant
if (system("sudo wpa_supplicant -B -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf") != 0) {
perror("Failed to start wpa_supplicant");
return;
}
// Obtain an IP address
if (system("sudo dhclient wlan0") != 0) {
perror("Failed to obtain an IP address");
}
}
int main() {
const char *ssid = "neardi_5G";
const char *password = "neardi_pwd";
connect_to_wifi(ssid, password);
return 0;
}
gcc connect_wifi.c -o connect_wifi
sudo ./connect_wifi
LED 说明
完整节点:
SYS LED:cat /sys/devices/platform/leds/leds/work1/brightness
STA LED:cat /sys/devices/platform/leds/leds/work2/brightness
MIC 使用
使用以下命令可以录制音频文件,支持wav、mp3等格式。
录制双声道的16位小端格式的音频,采样率为48000Hz,然后保存为001.wav文件。
- Cmd
- C
- Python
arecord -Dhw:0,0 -r48000 -f S16_LE -c2 > 001.wav
• -Dhw:0,0 指定了录音设备,0,0 是card 0 device 0,也就是第一个声卡的第一个设备。
• -r48000 指定了采样率,单位是Hz,48000表示每秒采样48000次。
• -f S16_LE 指定了采样格式,S16_LE表示有符号的16位小端格式,也就是每个采样点占用2个字节,低位在前,高位在后。
• -c2 指定了声道数,2表示双声道,也就是立体声。
• > 001.wav 指定了输出文件,>表示重定向标准输出到文件,001.wav表示文件名,wav表示文件格式。
create audio_record.c
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
#define SAMPLE_RATE 44100 // Replace SAMPLE_RATE with a local variable
#define CHANNELS 2 // Replace CHANNELS with a local variable
int main(int argc, char *argv[]) {
const char *device = "hw:0,0"; // Set the audio device
snd_pcm_t *pcm_handle;
snd_pcm_hw_params_t *params;
unsigned int sample_rate = SAMPLE_RATE; // Use a modifiable local variable
int channels = CHANNELS; // Use a modifiable local variable
int pcm, dir;
snd_pcm_uframes_t frames = 32;
FILE *file = fopen("001.wav", "wb");
if (!file) {
perror("Unable to create audio file");
return 1;
}
// Open PCM device
if ((pcm = snd_pcm_open(&pcm_handle, device, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
fprintf(stderr, "Unable to open PCM device %s: %s\n", device, snd_strerror(pcm));
fclose(file);
return 1;
}
// Set hardware parameters
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(pcm_handle, params);
snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(pcm_handle, params, channels); // Use the variable channels
snd_pcm_hw_params_set_rate_near(pcm_handle, params, &sample_rate, &dir); // Use the variable sample_rate
// Apply parameters
if ((pcm = snd_pcm_hw_params(pcm_handle, params)) < 0) {
fprintf(stderr, "Unable to set hardware parameters: %s\n", snd_strerror(pcm));
snd_pcm_close(pcm_handle);
fclose(file);
return 1;
}
// Get buffer size
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
int buffer_size = frames * channels * 2; // 2 bytes per channel
char *buffer = (char *)malloc(buffer_size);
// Write WAV file header
fwrite("RIFF", 1, 4, file);
fwrite("----", 1, 4, file); // Placeholder
fwrite("WAVE", 1, 4, file);
fwrite("fmt ", 1, 4, file);
int subchunk1_size = 16;
short audio_format = 1;
fwrite(&subchunk1_size, 4, 1, file);
fwrite(&audio_format, 2, 1, file);
fwrite(&channels, 2, 1, file); // Use the variable channels
fwrite(&sample_rate, 4, 1, file); // Use the variable sample_rate
int byte_rate = sample_rate * channels * 2;
fwrite(&byte_rate, 4, 1, file);
short block_align = channels * 2;
fwrite(&block_align, 2, 1, file);
short bits_per_sample = 16;
fwrite(&bits_per_sample, 2, 1, file);
// Write WAV data header
fwrite("data", 1, 4, file);
fwrite("----", 1, 4, file); // Placeholder
printf("Starting recording...\n");
// Start recording
int total_data_size = 0;
while (1) {
pcm = snd_pcm_readi(pcm_handle, buffer, frames);
if (pcm == -EPIPE) {
snd_pcm_prepare(pcm_handle);
} else if (pcm < 0) {
fprintf(stderr, "Recording failed: %s\n", snd_strerror(pcm));
break;
}
fwrite(buffer, 1, buffer_size, file);
total_data_size += buffer_size;
}
// Update WAV file size
fseek(file, 4, SEEK_SET);
int file_size = total_data_size + 36;
fwrite(&file_size, 4, 1, file);
fseek(file, 40, SEEK_SET);
fwrite(&total_data_size, 4, 1, file);
// Clean up resources
free(buffer);
snd_pcm_drain(pcm_handle);
snd_pcm_close(pcm_handle);
fclose(file);
printf("Recording complete\n");
return 0;
}
gcc audio_record.c -o audio_record -lasound
./audio_record
Install the PyAudio library:
sudo apt update
sudo apt install python3-pip
sudo apt install portaudio19-dev
pip3 install pyaudio
create audio_record.py
import wave
import pyaudio
# Audio format parameters
FORMAT = pyaudio.paInt16 # 16-bit PCM
CHANNELS = 2
RATE = 48000 # Sample rate
CHUNK = 4096 # Buffer size
# Create a PyAudio object
p = pyaudio.PyAudio()
# Open an audio stream
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
# Open a WAV file for writing
wf = wave.open('001.wav', 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
print("Recording...")
# Record audio data
try:
while True:
data = stream.read(CHUNK)
wf.writeframes(data)
except KeyboardInterrupt:
print("Recording stopped.")
# Clean up
print("Recording complete. Saved as 001.wav")
stream.stop_stream()
stream.close()
p.terminate()
wf.close()
python audio_record.py
LINE 使用
使用第一个声卡的第一个设备播放001.wav文件。
- Cmd
- C
- Python
aplay -D hw:0,0 001.wav
• -D hw:0,0 指定了播放设备,hw:0,0 是card 0 device 0,也就是第一个声卡的第一个设备。
• 001.wav 指定了音频文件,wav表示文件格式,001表示文件名。
Install the ALSA library and its development headers:
sudo apt update
sudo apt install libasound2-dev
create audio_play.c
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
int main(int argc, char *argv[]) {
const char *device = "hw:0,0"; // Set audio device
const char *filename = "001.wav"; // Audio file path
snd_pcm_t *pcm_handle;
snd_pcm_hw_params_t *params;
unsigned int sample_rate = 44100; // Sample rate
int pcm, dir;
snd_pcm_uframes_t frames;
FILE *file;
char *buffer;
int buffer_size;
// Open audio file
file = fopen(filename, "rb");
if (!file) {
perror("Unable to open audio file");
return 1;
}
// Open PCM device
if ((pcm = snd_pcm_open(&pcm_handle, device, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
fprintf(stderr, "Unable to open PCM device %s: %s\n", device, snd_strerror(pcm));
fclose(file);
return 1;
}
// Set hardware parameters
snd_pcm_hw_params_alloca(¶ms);
snd_pcm_hw_params_any(pcm_handle, params);
snd_pcm_hw_params_set_access(pcm_handle, params, SND_PCM_ACCESS_RW_INTERLEAVED);
snd_pcm_hw_params_set_format(pcm_handle, params, SND_PCM_FORMAT_S16_LE);
snd_pcm_hw_params_set_channels(pcm_handle, params, 2);
snd_pcm_hw_params_set_rate_near(pcm_handle, params, &sample_rate, &dir);
// Apply parameters
if ((pcm = snd_pcm_hw_params(pcm_handle, params)) < 0) {
fprintf(stderr, "Unable to set hardware parameters: %s\n", snd_strerror(pcm));
snd_pcm_close(pcm_handle);
fclose(file);
return 1;
}
// Get frame size and buffer size
snd_pcm_hw_params_get_period_size(params, &frames, &dir);
buffer_size = frames * 4; // 2 channels, each sample is 2 bytes
buffer = (char *) malloc(buffer_size);
// Play audio
while (fread(buffer, 1, buffer_size, file) > 0) {
if ((pcm = snd_pcm_writei(pcm_handle, buffer, frames)) == -EPIPE) {
snd_pcm_prepare(pcm_handle);
} else if (pcm < 0) {
fprintf(stderr, "Playback failed: %s\n", snd_strerror(pcm));
}
}
// Cleanup
free(buffer);
snd_pcm_drain(pcm_handle);
snd_pcm_close(pcm_handle);
fclose(file);
printf("Playback completed\n");
return 0;
}
gcc audio_play.c -o audio_play -lasound
./audio_play
Install the PyAudio and wave libraries:
sudo apt update
sudo apt install python3-pyaudio
create audio_play.py
import pyaudio
import wave
def play_audio(filename):
# Open WAV audio file
with wave.open(filename, 'rb') as wf:
# Initialize PyAudio
p = pyaudio.PyAudio()
# Configure audio stream
stream = p.open(format=p.get_format_from_width(wf.getsampwidth()),
channels=wf.getnchannels(),
rate=wf.getframerate(),
output=True)
# Read and play audio data
data = wf.readframes(1024)
while data:
stream.write(data)
data = wf.readframes(1024)
# Stop and close audio stream
stream.stop_stream()
stream.close()
# Terminate PyAudio
p.terminate()
print("Playback completed")
# Play file
play_audio('001.wav')
python3 audio_play.py