详细介绍:Day52 串口通信原理与IMX6ULL UART驱动开发

news/2025/10/11 11:54:32/文章来源:https://www.cnblogs.com/yxysuanfa/p/19134699

day52 串口通信原理与IMX6ULL UART驱动开发

本日内容聚焦于嵌入式系统中至关重要的串行通信技术。我们将从基础概念入手,深入剖析其工作原理,并最终在 IMX6ULL 开发板上实现一个完整的 UART 驱动程序,包括数据的发送、接收以及标准库 stdio 的移植,使我们能够像在 PC 上一样使用 printfscanf 进行调试和交互。

一、串口通信核心概念

串口通信是嵌入式系统中最基础、最常用的主机间数据交换方式。理解其底层逻辑是进行外设驱动开发的前提。

1.1 通信的基本维度

通信方式可以从三个主要维度进行分类:

  • 传输方式 (Transmission Mode):

    • 串行 (Serial): 数据位按顺序一位接一位地在单根数据线上传输。优点是布线简单、成本低、抗干扰能力强,适合长距离通信。缺点是传输速率相对较低。
    • 并行 (Parallel): 数据位在多根数据线上同时传输。优点是传输速率高(理论速率为串行的 N 倍,N 为数据线数)。缺点是布线复杂、易受干扰、成本高,适合短距离高速通信(如芯片内部总线)。
  • 同步方式 (Synchronization Mode):

    • 异步 (Asynchronous): 发送方和接收方没有共享的时钟信号。双方必须预先约定好相同的波特率(Baud Rate),通过数据帧中的起始位和停止位来同步数据的开始和结束。这种方式简单灵活,但传输效率略低(因需额外的起始/停止位)。
    • 同步 (Synchronous): 发送方和接收方共享一个时钟信号(通常由一根独立的时钟线 SCL 提供)。数据在时钟信号的边沿被采样,无需起始/停止位,传输效率高。但需要额外的时钟线,协议更复杂。例如 IIC、SPI 协议。
  • 通信方向 (Direction Mode):

    • 单工 (Simplex): 数据只能在一个方向上传输。一方固定为发送端,另一方固定为接收端。例如:广播电台 -> 收音机。
    • 半双工 (Half-Duplex): 数据可以在两个方向上传输,但同一时刻只能有一个方向。双方需分时使用信道。例如:对讲机。
    • 全双工 (Full-Duplex): 数据可以同时在两个方向上传输。双方可以同时发送和接收数据。例如:电话通话。

在这里插入图片描述

这张图主要展示了计算机通信中的几种数据传输方式及串口通信的典型模式,可从“串行/并行传输”“同步/异步传输”“通信制式(单工/半双工/全双工)”和“串口(UART)通信”几个维度解析:

1. 串行传输与并行传输(图中前两个模块对比)

2. 同步与异步传输(结合串行模块理解)

  • 同步传输
    依赖统一的时钟信号(图中上方的“方波”就是时钟),发送方和接收方用同一个时钟来同步数据位的收发(时钟跳变时采样数据)。优点:传输效率高;缺点:必须有时钟线,布线或协议更复杂。
  • 异步传输
    不依赖统一时钟,而是通过起始位、停止位等“帧格式”来同步(如串口UART)。发送方随机发数据,但每段数据前加起始位,后加停止位,接收方通过检测起始位来同步采样。优点:无需时钟线,布线简单;缺点:每帧有额外的起始/停止位,传输效率略低。

3. 通信制式(单工、半双工、全双工)

  • 单工:只能单向传输(如广播,电台→收音机,只能电台发,收音机收)。
  • 半双工:能双向传输,但同一时间只能一个方向(如对讲机,A讲时B只能听,B讲时A只能听)。
  • 全双工:能同时双向传输(如打电话,你说的同时也能听对方说)。

4. 串口(UART)通信(下方模块)

图中标注“串口:异步串行全双工通信方式”,是最典型的异步串行全双工场景:

5. 应用指令(底部文字)

“从终端输入 led on 输出:亮灯……” 是串口通信的应用场景示例:通过串口给设备发指令(如led on),设备解析后执行对应动作(亮灯、蜂鸣器开关等),体现了串口在“指令控制”中的实用价值。
总结:这张图通过对比和实例,把“串行/并行”“同步/异步”“通信制式”“串口UART”这几个通信核心概念串联起来,帮助理解不同传输方式的特点和应用场景。

1.2 串口数据帧格式 (TTL电平为例)

串口通信的数据是以“帧”为单位进行传输的。一个典型的帧包含以下几个部分:

  1. 空闲状态 (Idle State): 在没有数据传输时,数据线保持高电平
  2. 起始位 (Start Bit): 一个低电平脉冲,标志着一个数据帧的开始。接收方检测到这个下降沿,便开始准备接收后续数据。
  3. 数据位 (Data Bits): 实际要传输的数据,通常是 7 或 8 位。按照 LSB (Least Significant Bit, 最低位) 优先的原则发送。
  4. 校验位 (Parity Bit, 可选): 用于简单的错误检测。
    • 无校验 (None, N): 不使用校验位。
    • 奇校验 (Odd, O): 保证数据位 + 校验位中“1”的总数为奇数。
    • 偶校验 (Even, E): 保证数据位 + 校验位中“1”的总数为偶数。
    • 固定值校验: 校验位恒为 0 或 1。
  5. 停止位 (Stop Bit): 一个或多个高电平脉冲,标志着一个数据帧的结束。常见的有 1 位、1.5 位或 2 位停止位。
10100011
主机A - 主机B
串行
并行
11000101
串口:异步串行全双工通信方式

1.3 电气标准与物理层问题

不同的电气标准解决了不同距离和抗干扰需求的问题。

  • TTL (Transistor-Transistor Logic):

    • 定义: 由芯片引脚直接产生的电压电平。具体电压值取决于芯片的工作电压(如 5V、3.3V、1.8V)。
    • 特点: 电平范围小(如 3.3V 系统下,高电平 ~3.3V,低电平 ~0V),抗干扰能力弱传输距离短(通常限制在 10~20 米内,实际应用中多用于同一块电路板上的芯片间通信)。
    • 问题: 导线存在内阻,长距离传输会导致电压衰减和串扰,使得接收端无法正确识别高低电平。
  • RS232:

    • 定义: IEEE 制定的标准,规定了逻辑电平。
      • 逻辑高电平 (1): -3V 至 -15V
      • 逻辑低电平 (0): +3V 至 +15V
    • 特点: 使用负逻辑(负电压表示高,正电压表示低),电压幅度大,抗干扰能力强,传输距离可达 20~30 米。采用三根线(TX, RX, GND),是全双工通信。
  • RS485:

    • 定义: 一种差分传输标准。
    • 特点: 使用两根信号线 A 和 B,通过比较 A 和 B 之间的电压差来识别信息。电压范围分别为 +7V 到 +12V 和 -7V 到 -12V。这种差分信号传输方式极大地提高了抗共模干扰能力。传输距离可达 1200 米。由于在同一时刻,两根线都用于传输同一个比特的信息,因此它是半双工通信。

二、IMX6ULL UART 外设原理分析

IMX6ULL 的 UART 模块是一个复杂的异步串行收发器,我们需要理解其寄存器配置才能正确驱动它。

2.1 时钟树分析

UART 模块需要一个稳定的时钟源。根据《IMX6ULL参考手册》,其时钟路径如下:

  1. 时钟源: 来自 CCM (Clock Control Module) 的 uart_clk_root
  2. 默认配置:uart_clk_root 默认由 pll3_sw_clk (即 PLL3) 提供,频率为 480MHz。
  3. 分频: 经过一个静态分频器(6分频),得到 80MHz 的 uart_serial_clk
  4. 最终时钟:uart_serial_clk 直接作为 UART 模块的时钟源(UARTx_CLK),用于产生波特率。

注意: 我们在初始化时通常不需要修改这个时钟路径,直接使用默认的 80MHz 时钟即可满足常见波特率的需求。

2.2 关键寄存器详解

以下是 UART 初始化和操作所需的关键寄存器及其位域说明:

2.2.1 UART Receiver Register (URXD)
2.2.2 UART Transmitter Register (UTXD)
  • 地址:UARTx_UTXD
  • 功能: 写寄存器,用于发送数据。
  • 关键位域:
    • [TX_DATA] b0-7: 需要发送的数据。当软件向此字段写入数据时,UART 硬件会自动开始发送过程。
2.2.3 UART Control Register 1 (UCR1)
2.2.4 UART Control Register 2 (UCR2)
  • 地址:UARTx_UCR2
  • 功能: 控制接收器、发送器、数据格式等。
  • 关键位域:
    • [UARTEN] b0: 软件复位位。写 0 触发复位,复位完成后硬件自动置 1。复位需持续 4 个模块时钟周期。
    • [RXEN] b1: 接收器使能位。置 1 启用接收功能。
    • [TXEN] b2: 发送器使能位。置 1 启用发送功能。
    • [WS] b5: 字长选择位。置 1 选择 8 位数据,清 0 选择 7 位数据。
    • [STPB] b6: 停止位数量选择位。清 0 选择 1 位停止位,置 1 选择 2 位停止位。
    • [PREN] b8: 奇偶校验使能位。清 0 禁用校验,置 1 启用校验。
    • [IRTS] b14: 忽略 RTS 引脚流控位。置 1 忽略 RTS 流控信号(我们通常不使用流控,故置 1)。
2.2.5 UART Control Register 3 (UCR3)
2.2.6 UART FIFO Control Register (UFCR)
  • 地址:UARTx_UFCR
  • 功能: 控制 FIFO 和参考时钟分频。
  • 关键位域:
    • [RFDIV] b7-b9: 参考时钟分频器。控制参考时钟的分频比。我们使用默认的 80MHz 时钟,故设置为 1 分频(值为 5,因为 RFDIV = 0b101 对应 1 分频)。
2.2.7 UART Status Register 2 (USR2)
2.2.8 波特率配置寄存器
  • UART BRM Incremental Register (UBIR):
    • 地址:UARTx_UBIR
    • 功能: 存储波特率调制增量值。
    • 关键位域:[INC] b0-b15: UBIR 值。
  • UART BRM Modulator Register (UBMR):
    • 地址:UARTx_UBMR
    • 功能: 存储波特率调制器值。
    • 关键位域:[MOD] b0-b15: UBMR 值。
  • 计算公式:
    BaudRate = Ref Freq / (16 x ((UBMR + 1) / (UBIR + 1)))
    其中 Ref Freq 是模块时钟频率(80MHz)。对于 115200 波特率,经过计算,UBIR = 999, UBMR = 43401

三、代码实现:UART 驱动开发

3.1 引脚复用与电气配置

在使用 UART 之前,必须将对应的 GPIO 引脚复用为 UART 功能,并配置其电气特性。

// 引脚复用配置
IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX, 0); // 将 UART1_RX 引脚复用为 UART1_RX 功能
IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX, 0); // 将 UART1_TX 引脚复用为 UART1_TX 功能
// 引脚电气特性配置 (0x10B0 是一个常用配置,代表 100KΩ 下拉电阻,100MHz 频率,开漏输出等)
IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0);
IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0);

3.2 UART 初始化函数 (uart1_init)

该函数负责初始化 UART1 外设,使其处于可用状态。

#include "uart.h"
#include "MCIMX6Y2.h"
#include "fsl_iomuxc.h"
void uart1_init(void)
{
// 1. 配置引脚复用和电气特性
IOMUXC_SetPinMux(IOMUXC_UART1_RX_DATA_UART1_RX, 0);
IOMUXC_SetPinMux(IOMUXC_UART1_TX_DATA_UART1_TX, 0);
IOMUXC_SetPinConfig(IOMUXC_UART1_RX_DATA_UART1_RX, 0x10B0);
IOMUXC_SetPinConfig(IOMUXC_UART1_TX_DATA_UART1_TX, 0x10B0);
// 2. 软件复位 UART (写 0 到 UCR2[0])
UART1->UCR2 &= ~(1 << 0);
// 3. 配置 UCR2 寄存器
unsigned int t;
t = UART1->UCR2; // 读取当前值
t |= (1 << 14);  // [IRTS] 忽略 RTS 流控
t &= ~(1 << 8);  // [PREN] 清除奇偶校验使能 (无校验)
t &= ~(1 << 6);  // [STPB] 清除停止位选择 (1位停止位)
t |= (1 << 5);   // [WS] 设置字长为 8 位
t |= (1 << 2);   // [TXEN] 使能发送器
t |= (1 << 1);   // [RXEN] 使能接收器
UART1->UCR2 = t; // 写回配置
// 4. 配置 UCR3 寄存器
UART1->UCR3 |= (1 << 2); // [RXDMUXSEL] 设置为多路复用模式 (必须为 1)
// 5. 配置 UFCR 寄存器 (设置分频为 1)
UART1->UFCR &= ~(7 << 7); // 清除 RFDIV 位域 (b7-b9)
UART1->UFCR |= (5 << 7);  // 设置 RFDIV = 0b101 (1分频)
// 6. 配置波特率 (UBIR 和 UBMR)
// 注意: 必须先写 UBIR,再写 UBMR
UART1->UBIR = 999;   // 设置 UBIR
UART1->UBMR = 43401; // 设置 UBMR
// 7. 使能 UART 模块 (最后一步)
UART1->UCR1 |= (1 << 0); // [UARTEN] 使能 UART
}

3.3 数据发送函数 (putc, puts)

  • putc: 发送单个字符。
  • puts: 发送字符串,并在末尾追加换行符。
// 发送单个字符
void putc(unsigned char ch)
{
// 等待发送完成标志位 (TXDC) 置位
while ((UART1->USR2 & (1 << 3)) == 0)
; // 循环等待,直到发送缓冲区和移位寄存器都为空
// 将字符写入发送寄存器,触发发送过程
UART1->UTXD = ch;
}
// 发送字符串
void puts(const char *pStr)
{
// 遍历字符串,逐个字符发送
while (*pStr)
{
putc(*pStr++); // 发送当前字符,并指针后移
}
// 发送换行符
putc('
');
}

3.4 数据接收函数 (getc)

接收单个字符。

// 接收单个字符
unsigned char getc(void)
{
// 等待接收数据就绪标志位 (RDR) 置位
while ((UART1->USR2 & (1 << 0)) == 0)
; // 循环等待,直到接收缓冲区中有有效数据
// 从接收寄存器读取数据,并只保留低8位
return (unsigned char)(UART1->URXD & 0xFF);
}

3.5 移植 stdio 标准库

为了让我们的程序能够使用 printf, scanf 等标准库函数,需要将其重定向到我们自己实现的 putcgetc 函数。

3.5.1 添加必要函数

uart.c 文件中添加 raise 函数(否则链接时会报错)。

// stdio 库可能调用的空函数
void raise(int n)
{
// 为空即可,避免链接错误
}
3.5.2 修改 Makefile

为了支持 stdio 库,需要在编译和链接阶段添加相应的选项和库路径。

# ... (其他部分保持不变)
# 定义库路径变量
libpath = -lgcc -L/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/lib/gcc/arm-linux-gnueabihf/4.9.4/
# 指定头文件和源文件目录
incdirs = bsp imx6ull stdio/include
srcdirs = bsp project stdio/lib
# 编译规则 (增加 -fno-builtin 选项,禁用内置函数)
$(sobjs) : obj/%.o : %.S@mkdir -p obj$(cc) -Wall -Wa,-mimplicit-it=thumb -fno-builtin -nostdlib -c $(include) -o $@ $<
# 链接规则 (添加 libpath)
$(target).bin : $(objs)$(ld) -Timx6ull.lds -o$(target).elf $^ $(libpath)$(objcopy) -O binary -S -g $(target).elf $@$(objdump) -D $(target).elf > $(target).dis
3.5.3 在主程序中使用 stdio

现在可以在 main.c 中包含 <stdio.h> 并使用 printfscanf

#include "stdio.h" // 包含标准输入输出头文件
int main(void)
{
system_interrupt_init();
clock_init();
led_init();
beep_init();
gpt1_init();
uart1_init(); // 初始化 UART
int num1 = 0, num2 = 0;
while(1)
{
// 从串口接收两个整数
scanf("%d%d", &num1, &num2);
// 通过串口打印计算结果
printf("%d + %d = %d
", num1, num2, num1 + num2);
}
return 0;
}

四、实验验证

  1. 编译下载: 编译整个工程,生成 .bin 文件并烧录到开发板。
  2. 连接串口: 使用 USB-TTL 线将开发板的 USB_TTL 接口连接到电脑。
  3. 打开串口助手: 在电脑上打开串口调试助手,设置波特率为 115200,数据位 8,停止位 1,无校验。
  4. 观察结果: 上电后,程序会进入循环,等待用户输入。在串口助手中输入两个数字(如 12 34),然后按回车。程序会计算它们的和并通过串口返回结果(如 12 + 34 = 46)。

通过以上步骤,我们成功实现了 IMX6ULL 的 UART 通信功能,并完成了 stdio 标准库的移植,为后续的嵌入式开发打下了坚实的基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/934702.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

摸鱼混子回归 - ZERO

2025年10月11日,11:44。 前一段时间一直在跑实验,跑的稀巴烂,今天彻底收尾结束。 开始刷论文,进入无限循环模式。 (无奈但妥协.jpg)

vue3实现抓拍并上传

<template><video ref="videoRef" autoplay playsinline></video><canvas ref="canvasRef" class="hidden"></canvas><button @click="capture&…

2025 年国内润滑油厂商最新推荐榜:聚焦优质品牌实力,助力企业精准选品润滑油净化/过滤/回用/液压油润滑油过滤厂商推荐

当前工业领域对润滑油的需求持续增长,但市场上供应商资质不一、产品质量参差不齐的问题愈发凸显。部分企业在采购时面临产品缺乏溯源、适配性不足、服务响应滞后等难题,不仅增加设备运维成本,还可能因油品问题导致生…

纯前端实现项目过期

项目过期逻辑 /*** 项目有效期检查工具* 设置项目在指定日期后无法访问*/// 设置过期日期为2024年10月30日 const EXPIRY_DATE = new Date(2025-10-30 23:59:59)/*** 检查项目是否已过期* @returns {boolean} true表示…

基于形态学的权重自适应图像去噪的MATLAB实现

classdef MorphologicalAdaptiveDenoising% 基于形态学的权重自适应图像去噪类% 支持灰度图像和彩色图像的去噪propertiesstructuring_elementsalphabetaiterationsendmethodsfunction obj = MorphologicalAdaptiveDen…

2025 年油水分离器 / 气液分离器 / 液固分离器 / 水分离器 / 油分离器厂家推荐:西安同大技术沉淀与流体净化解决方案解析

2025 年分离设备行业迎来技术迭代与市场扩容期,全球市场规模已突破 1200 亿美元,中国贡献占比超 35%,成为推动行业发展的核心力量。化工、石油、天然气等领域对分离效率、工况适配性的要求持续升级,合成氨、甲醇、…

2025 年过滤器厂家最新推荐排行榜:聚焦烛式 / 金属 / 非金属 / 化工 / 精密过滤器等多类型设备,精选优质品牌助企业高效选型液固/高效/气固/催化剂过滤器厂家推荐

当前工业生产中,流体处理环节的过滤分离技术对生产安全、效益提升至关重要,化工、石油、天然气等领域常受原料杂质、设备磨损、环保达标难、特殊工况适配差等问题困扰,传统过滤设备易导致产品损失与生产中断。为帮助…

OOP-实验1

实验任务1 源代码task1.cpp点击查看代码 // 现代C++标准库、算法库体验 // 本例用到以下内容: // 1. 字符串string, 动态数组容器类vector、迭代器 // 2. 算法库:反转元素次序、旋转元素 // 3. 函数模板、const引用作…

2025 年立式/立式全钢板/青黄储/液压打包机厂家推荐榜:聚焦实用需求,精选高适配设备助力企业降本增效

随着工业生产精细化推进、环保回收产业规模化发展及企业降本增效需求升级,液压打包机已从传统工业辅助设备,逐步成为废纸回收、塑料加工、农业物料处理等领域的 “刚需工具”—— 它能通过压缩工艺大幅减少轻泡物料体…

308、清平调三首

308、清平调三首308、清平调三首 唐●李白 其一 云想衣裳花想容,春风拂槛露华浓。 若非群玉山头见,会向瑶台月下逢。【现代诗意译】 彩云羡慕她的衣裳 牡丹羡慕她的容貌 春风吹拂着栏杆 更显得她风姿绰约 在露水滋润…

2025管件厂家最新推荐榜:高品质管件与卓越工艺口碑之选

2025管件厂家最新推荐榜:高品质管件与卓越工艺口碑之选行业背景管件作为管道系统中不可或缺的组成部分,广泛应用于建筑、化工、能源、水利等众多领域。随着全球基础设施建设的不断推进以及工业生产的持续发展,管件市…

2025不锈钢管件厂家推荐榜:技术实力与诚信口碑双重保障

2025不锈钢管件厂家推荐榜:技术实力与诚信口碑双重保障在工业管道系统快速发展的今天,卡压式不锈钢管件以其安装便捷、密封性强、耐腐蚀等优势,成为众多工程项目的首选材料。随着市场竞争日趋激烈,如何在众多厂家中…

哪款剪贴板增强软件最好用?有什么剪贴板内容大全值得分享?多款剪切板历史免费版管理工具推荐

剪贴板是电脑中一个非常实用的功能,允许用户在不同的应用程序之间复制和粘贴文本、图像、文件等内容。然而,默认情况下,剪贴板只能存储最近一次复制的内容,这可能会限制我们的工作效率。 但是 Windows 上的剪贴板只…

EndNote文献管理工具!研究生必备软件!超详细下载安装教程(附下载地址)

软甲简介 EndNote是一款功能强大的参考文献管理工具,EndNote作为全球学术界广泛使用的专业软件,拥有强大的文献整理、引用写作和协同管理功能,被众多高校、导师、科研机构列为“标配”。软件获取地址 EndNote文献管…

鸿蒙应用开发从入门到实战(十九):样式复用案例

上一篇文章讲解了ArkUI中样式复用思想,本节继续使用自定义组件对商品列表进行优化。大家好,我是潘Sir,持续分享IT技术,帮你少走弯路。《鸿蒙应用开发从入门到项目实战》系列文章持续更新中,陆续更新AI+编程、企业…

2025 年最新推荐冰醋酸厂商综合实力排行榜: 厂商定制服务与仓储能力深度解析昆山/太仓/吴江区/吴中区/相城区/姑苏区冰醋酸厂商推荐

2025 年中国冰醋酸行业产能持续扩张,但市场供需矛盾、品质要求升级及环保政策趋严等问题凸显。华东、华北产区供应集中与中西部需求增长的运输成本差距加大,下游食品、医药领域对产品纯度要求愈发严苛,工业级纯度需…

中电金信:“源启大模型文本生成算法”成功通过互联网信息服务算法备案

近日,国家互联网信息办公室发布了第十三批深度合成服务算法备案信息的公告,中电金信自主研发的“源启大模型文本生成算法”正式通过备案。根据国家网信办等七部门联合公布的《生成式人工智能服务管理暂行办法》规定,…

【Qt开发】输入类控件(二)-> QTextEdit - 详解

【Qt开发】输入类控件(二)-> QTextEdit - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas",…

基于MATLAB的禁忌搜索算法解决物流网络枢纽选址问题

一、问题建模 1. 数学模型 目标函数:最小化总成本(建设成本+运输成本)\(S\):选中的枢纽集合 \(C_i\):候选点i的建设成本 \(w_{kj}\):需求点k到枢纽j的货物量 \(d_{ik}\):候选点i到需求点k的距离 \(x_{ijk}\):需…

springboot 项目部署是tomcat么

------------------------------------------------------ Spring Boot 项目的部署可以使用 Tomcat,但并非只能用 Tomcat。具体取决于项目的配置和需求,主要分为两种情况:** 内置服务器部署 (默认)和外部服务器部…