配置串口奇偶校验位
1 概述
串口校验位(Parity)用于检测数据传输中的错误。常见的校验方式有奇校验(odd)、偶校验(even)和无校验(none)。本文介绍如何配置串口校验位,并提供了相应的应用指导。
1.1背景
部分客户在使用CM0产品串口功能时,需要配置串口校验位以实现数据传输的可靠性。本文将介绍如何配置串口校验位,并提供相应的应用指导。
1.2 适用范围
本应用适用于所有的CM0设备。
2 应用指导
下文仅以ED-IPC1100设备的RS485为例,介绍安装和配置串口校验位的步骤。
2.1 串口映射(须先确认)
在进行安装前,请先确认设备的串口映射与蓝牙 overlay 设置,确保 /dev/serial0 指向预期的硬件设备 /dev/ttyAMA0。
2.1.1 切换 overlay
sudo nano /boot/firmware/config.txt
2.1.2 禁用蓝牙(优先串口稳定性)
disable-bt:/dev/serial0 -> ttyAMA0,禁用蓝牙,PL011(硬件 UART)用于串口(推荐用于稳定通信)。- 如下图添加
dtoverlay=disable-bt,保存并重启设备。

2.1.3 保留蓝牙(使用 miniuart)
miniuart-bt:/dev/serial0 -> ttyAMA0,保留蓝牙但使用 mini UART,波特率可能受 CPU 频率影响(可能不稳定)。- 如下图添加
dtoverlay=miniuart-bt,保存并重启设备。

2.1.4 验证映射
readlink -f /dev/serial0
2.2 配置串口校验位设置服务
2.2.1 创建安装文件
sudo nano serial-service-installer.sh
将以下脚本内容复制到文件中:
#!/bin/bash
set -e
SCRIPT_NAME="serial-service-installer.sh"
SERVICE_NAME="serial-parity.service"
INSTALL_PATH="/usr/local/bin/serial-parity-daemon"
SERVICE_FILE="/etc/systemd/system/$SERVICE_NAME"
CONFIG_FILE="/etc/serial-parity.conf"
# 默认配置
SERIAL_PORT="/dev/ttyAMA0"
BAUD_RATE="9600"
PARITY_MODE="even"
log() {
echo "[INFO] $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
warn() {
echo "[WARN] $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
error() {
echo "[ERROR] $(date '+%Y-%m-%d %H:%M:%S') - $1"
}
manage_config() {
local action="$1"
local file_path="$2"
case "$action" in
"ensure")
if [ ! -f "$file_path" ]; then
mkdir -p "$(dirname "$file_path")" 2>/dev/null || true
cat > "$file_path" << 'EOF'
# 串口奇偶校验配置
#偶校验even|奇校验odd|无校验none
PARITY_MODE=even
#接口配置
SERIAL_PORT=/dev/ttyAMA0
#波特率配置
BAUD_RATE=9600
EOF
chmod 644 "$file_path" 2>/dev/null || true
log "创建配置文件: $file_path"
fi
;;
"load")
if [ -f "$file_path" ]; then
source "$file_path"
fi
;;
esac
}
check_root() {
if [[ $EUID -ne 0 ]]; then
error "此操作需要root权限,请使用 sudo 执行"
exit 1
fi
}
check_serial_device() {
local device="$1"
if [ ! -e "$device" ]; then
warn "串口设备 $device 不存在,但继续安装"
return 1
fi
if [ ! -r "$device" ] || [ ! -w "$device" ]; then
warn "对串口设备 $device 权限不足"
return 1
fi
log "串口设备 $device 检查通过"
return 0
}
create_daemon_script() {
local daemon_path="$1"
log "创建主服务程序..."
cat > "$daemon_path" << 'DAEMON_EOF'
#!/bin/bash
# 串口奇偶校验守护进程
CONFIG_FILE="/etc/serial-parity.conf"
log() {
echo "$(date '+%Y-%m-%d %H:%M:%S') - $1"
}
apply_serial_settings() {
(
case "$PARITY_MODE" in
"even")
stty -F "$SERIAL_PORT" speed "$BAUD_RATE" cs7 parenb -parodd -cstopb
;;
"odd")
stty -F "$SERIAL_PORT" speed "$BAUD_RATE" cs7 parenb parodd -cstopb
;;
*)
stty -F "$SERIAL_PORT" speed "$BAUD_RATE" cs8 -parenb -cstopb
;;
esac
) >/dev/null 2>&1
if [ $? -eq 0 ]; then
log "串口设置成功: 模式=$PARITY_MODE, 波特率=$BAUD_RATE"
return 0
else
log "串口设置失败"
return 1
fi
}
set_config() {
local new_value="$1"
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
case "$new_value" in
"even"|"odd"|"none")
sed -i "s/^PARITY_MODE=.*/PARITY_MODE=$new_value/" "$CONFIG_FILE"
PARITY_MODE="$new_value"
log "设置校验模式: $PARITY_MODE"
;;
*)
if [[ "$new_value" =~ ^[0-9]+$ ]] && [ "$new_value" -ge 300 ] && [ "$new_value" -le 4000000 ]; then
sed -i "s/^BAUD_RATE=.*/BAUD_RATE=$new_value/" "$CONFIG_FILE"
BAUD_RATE="$new_value"
log "设置波特率: $BAUD_RATE"
else
echo "错误: 无效参数 '$new_value'"
echo "用法: $0 set {even|odd|none|波特率}"
return 1
fi
;;
esac
apply_serial_settings
}
show_help() {
cat <<'EOF'
串口奇偶校验服务
用法: /usr/local/bin/serial-parity-daemon set {none|odd|even|波特率}
设置示例:
sudo serial-parity-daemon set odd # 奇校验
sudo serial-parity-daemon set 115200 # 115200波特率
服务管理:
sudo systemctl {start|stop|status} serial-parity.service
EOF
}
main_service() {
[ -f "$CONFIG_FILE" ] && source "$CONFIG_FILE"
log "启动串口服务: $SERIAL_PORT, $BAUD_RATE, $PARITY_MODE"
[ ! -e "$SERIAL_PORT" ] && {
log "错误: 串口设备不存在"
exit 1
}
apply_serial_settings || exit 1
log "服务运行中"
while true; do
sleep 3600
done
}
case "${1:-}" in
"start") main_service ;;
"set")
[ -n "$2" ] && set_config "$2" || {
echo "用法: $0 set {even|odd|none|波特率}"
exit 1
}
;;
"help"|"-h"|*) show_help ;;
esac
DAEMON_EOF
chmod +x "$daemon_path"
log "主服务程序创建完成: $daemon_path"
}
create_systemd_service() {
log "创建systemd服务文件..."
cat > "$SERVICE_FILE" << SERVICE_EOF
[Unit]
Description=Serial Port Parity Configuration Service
After=multi-user.target
[Service]
Type=simple
ExecStart=$INSTALL_PATH start
Restart=always
RestartSec=5
User=root
Group=dialout
[Install]
WantedBy=multi-user.target
SERVICE_EOF
log "systemd服务文件创建完成: $SERVICE_FILE"
}
install_service() {
check_root
log "开始安装串口服务..."
check_serial_device "$SERIAL_PORT"
mkdir -p "$(dirname "$INSTALL_PATH")"
[ -f "$INSTALL_PATH" ] && {
backup="$INSTALL_PATH.backup.$(date +%Y%m%d_%H%M%S)"
cp "$INSTALL_PATH" "$backup"
log "已备份现有文件: $backup"
}
create_daemon_script "$INSTALL_PATH"
create_systemd_service
manage_config "ensure" "$CONFIG_FILE"
systemctl daemon-reload
systemctl enable "$SERVICE_NAME"
log "服务安装完成"
}
start_service() {
check_root
systemctl start "$SERVICE_NAME" && log "服务启动成功" || {
error "服务启动失败"
exit 1
}
}
self_cleanup() {
log "安装完成,清理安装脚本..."
cat > /tmp/cleanup-$$.sh << 'CLEANUP_EOF'
#!/bin/bash
sleep 3
[ -f "$1" ] && rm -f "$1"
rm -f "$0"
CLEANUP_EOF
chmod +x /tmp/cleanup-$$.sh
nohup /tmp/cleanup-$$.sh "$0" >/dev/null 2>&1 &
}
show_help() {
cat <<'EOF'
串口服务安装脚本
用法: sudo ./serial-service-installer.sh install
EOF
}
main() {
case "${1:-}" in
"install")
install_service
start_service
self_cleanup
;;
*) show_help ;;
esac
}
[[ "${BASH_SOURCE[0]}" == "${0}" ]] && main "$@"
2.2.2 安装脚本并生成unit
sudo chmod +x serial-service-installer.sh
sudo ./serial-service-installer.sh install
2.2.3 查看服务状态
sudo systemctl status serial-parity.service
2.3 更改串口配置
2.3.1 切换奇偶校验和波特率(默认偶校验、9600)
sudo nano /etc/serial-parity.conf

2.3.3 修改校验位或波特率后重启服务生效
sudo systemctl stop serial-parity.service
sudo systemctl start serial-parity.service
说明:
- even/odd 常配 7 数据位(cs7);none 使用 8 数据位(cs8)。
2.4 常用操作
- 启动:
sudo systemctl start serial-parity.service - 停止:
sudo systemctl stop serial-parity.service - 开机自启:
sudo systemctl enable serial-parity.service - 取消自启:
sudo systemctl disable serial-parity.service - 查看状态:
sudo systemctl status serial-parity.service
