嵌入式硬件篇---龙芯UART通信

embedded/2025/3/19 9:14:47/
cle class="baidu_pl">
cle_content" class="article_content clearfix">
content_views" class="markdown_views prism-atom-one-dark">cap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">

class="toc">

文章目录

  • 前言
  • 一、代码结构解析
    • 1. 头文件部分
      • 作用
    • 2. 宏定义与全局变量
    • 3. 主函数流程
      • 关键点
    • 4. UART发送函数
    • 5. 串口配置函数(set_port)
    • 6. GPIO控制函数
    • 7. PWM控制函数
  • 二、龙芯UART深度解析
    • 1. 硬件架构
      • 控制器类型
      • 时钟源
      • 寄存器映射
    • 2. 关键寄存器
    • 3. 驱动配置
      • 内核配置
      • 设备树配置
    • 4. 波特率计算
      • 公式
      • 示例
  • 三、代码优化建议
    • 错误处理增强
    • 非阻塞读取优化
    • PWM配置封装
  • 四、龙芯开发注意事项
    • 串口引脚复用
    • DMA模式启用
    • 硬件流控配置
    • 系统稳定性


前言

本文简单介绍了龙芯中的uart通信以及使用方法。


一、代码结构解析

1. 头文件部分

<code class="prism language-c">class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><stdio.h>       class="token comment">// 标准输入输出
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><stdlib.h>      class="token comment">// 系统函数库(如system)
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><time.h>        class="token comment">// 时间相关函数
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><unistd.h>      class="token comment">// POSIX API(如usleep)
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><fcntl.h>       class="token comment">// 文件控制(如open)
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><termios.h>     class="token comment">// 串口配置结构体
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><errno.h>       class="token comment">// 错误号定义
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><string.h>      class="token comment">// 字符串操作
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><sys/mman.h>    class="token comment">// 内存映射
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><sys/types.h>   class="token comment">// 系统数据类型
class="token macro property">class="token directive-hash">#class="token directive keyword">include class="token string"><sys/stat.h>    class="token comment">// 文件状态
code>

作用

ckquote>

作用:包含Linux环境下串口通信和系统操作所需的头文件。

ckquote>

2. 宏定义与全局变量

<code class="prism language-c">class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">EXPORT class="token string">"/sys/class/gpio/export"  class="token comment">// GPIO导出路径
class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">DEV_NAME class="token string">"/dev/ttyS2"            class="token comment">// 龙芯UART设备节点
class="token macro property">class="token directive-hash">#class="token directive keyword">define class="token macro-name">pwm1 class="token expression">class="token number">1                           class="token comment">// PWM通道定义
code>

龙芯特性

ckquote>
  1. 龙芯处理器(如LS2K1000)的UART设备节点通常为**/dev/ttyS0~ /dev/ttyS3**࿰c;对应硬件UART0~UART3。
  2. PWM通道路径需根据具体硬件确定࿰c;可能与SoC的PWM控制器映射相关。
ckquote>

3. 主函数流程

<code class="prism language-c">class="token keyword">int class="token function">mainclass="token punctuation">(class="token punctuation">) class="token punctuation">{class="token comment">// 初始化UARTuart_fd class="token operator">= class="token function">open_portclass="token punctuation">(DEV_NAMEclass="token punctuation">)class="token punctuation">;        class="token comment">// 打开串口设备class="token function">set_portclass="token punctuation">(uart_fdclass="token punctuation">, class="token number">115200class="token punctuation">, class="token number">8class="token punctuation">, class="token char">'N'class="token punctuation">, class="token number">1class="token punctuation">)class="token punctuation">; class="token comment">// 配置波特率等参数class="token keyword">whileclass="token punctuation">(class="token number">1class="token punctuation">) class="token punctuation">{class="token function">usleepclass="token punctuation">(class="token number">500000class="token punctuation">)class="token punctuation">;                  class="token comment">// 延时500msclass="token function">memsetclass="token punctuation">(read_bufclass="token punctuation">, class="token number">0class="token punctuation">, class="token keyword">sizeofclass="token punctuation">(read_bufclass="token punctuation">)class="token punctuation">)class="token punctuation">;class="token function">tcflushclass="token punctuation">(uart_fdclass="token punctuation">, TCOFLUSHclass="token punctuation">)class="token punctuation">;       class="token comment">// 清空缓冲区nread class="token operator">= class="token function">readclass="token punctuation">(uart_fdclass="token punctuation">, read_bufclass="token punctuation">, class="token number">4class="token punctuation">)class="token punctuation">;class="token comment">// 尝试读取数据write_bufclass="token punctuation">[class="token number">0class="token punctuation">] class="token operator">= class="token number">6class="token punctuation">;                 class="token comment">// 发送数据6class="token function">Uart_Sendclass="token punctuation">(uart_fdclass="token punctuation">, write_bufclass="token punctuation">, class="token number">1class="token punctuation">)class="token punctuation">; class="token comment">// 发送单字节class="token punctuation">}
class="token punctuation">}
code>

关键点

ckquote>
  1. tcflush(uart_fd, TCOFLUSH)用于清空输出缓冲区c;确保发送数据无残留。
  2. 龙芯UART时钟源由CPU时钟分频而来c;需确保波特率计算值与实际硬件匹配
ckquote>

UART_75">4. UART发送函数

<code class="prism language-c">class="token keyword">int class="token function">Uart_Sendclass="token punctuation">(class="token keyword">int fdclass="token punctuation">, class="token keyword">char class="token operator">*send_bufclass="token punctuation">, class="token keyword">int data_lenclass="token punctuation">) class="token punctuation">{class="token keyword">return class="token function">writeclass="token punctuation">(fdclass="token punctuation">, send_bufclass="token punctuation">, data_lenclass="token punctuation">)class="token punctuation">; class="token comment">// 直接调用系统写函数
class="token punctuation">}
code>

龙芯实现

ckquote>

龙芯UART驱动基于8250驱动框架c;用户空间通过write()直接操作设备节点

ckquote>

5. 串口配置函数(set_port)

<code class="prism language-c">class="token keyword">int class="token function">set_portclass="token punctuation">(class="token keyword">int fdclass="token punctuation">, class="token keyword">int nSpeedclass="token punctuation">, class="token keyword">int nBitsclass="token punctuation">, class="token keyword">char nEventclass="token punctuation">, class="token keyword">int nStopclass="token punctuation">) class="token punctuation">{class="token keyword">struct class="token class-name">termios newtioclass="token punctuation">;class="token comment">// 配置数据位、校验位、停止位newtioclass="token punctuation">.c_cflag class="token operator">|= CLOCAL class="token operator">| CREADclass="token punctuation">; class="token comment">// 本地连接+使能接收class="token comment">// 波特率设置(关键代码段)class="token function">cfsetospeedclass="token punctuation">(class="token operator">&newtioclass="token punctuation">, B115200class="token punctuation">)class="token punctuation">;    class="token comment">// 输出波特率class="token function">cfsetispeedclass="token punctuation">(class="token operator">&newtioclass="token punctuation">, B115200class="token punctuation">)class="token punctuation">;    class="token comment">// 输入波特率class="token comment">// 应用配置class="token function">tcsetattrclass="token punctuation">(fdclass="token punctuation">, TCSANOWclass="token punctuation">, class="token operator">&newtioclass="token punctuation">)class="token punctuation">;
class="token punctuation">}
code>

龙芯注意事项

ckquote>

1.波特率精度依赖时钟分频器c;需在硬件设计中确认UART时钟源频率。
2.若需更高波特率(如3Mbps)c;可能需要修改内核驱动中的分频参数。

ckquote>

6. GPIO控制函数

<code class="prism language-c">class="token keyword">void class="token function">export_gpioclass="token punctuation">(class="token keyword">int gpioclass="token punctuation">) class="token punctuation">{class="token function">systemclass="token punctuation">(class="token string">"echo XX > /sys/class/gpio/export"class="token punctuation">)class="token punctuation">; class="token comment">// 通过sysfs操作
class="token punctuation">}
code>

龙芯GPIO特性

ckquote>

1.GPIO编号需参考具体开发板手册࿰c;如LS2K1000的GPIO可能按Bank分组管理

ckquote> ckquote>

2.部分GPIO可能复用为其他功能(如UARTc;需配置引脚复用寄存器

ckquote>

7. PWM控制函数

<code class="prism language-c">class="token keyword">int class="token function">pwm_configclass="token punctuation">(class="token keyword">unsigned class="token keyword">int pwmclass="token punctuation">, class="token keyword">unsigned class="token keyword">int periodclass="token punctuation">, duty_cycleclass="token punctuation">) class="token punctuation">{class="token comment">// 通过sysfs设置周期和占空比class="token function">writeclass="token punctuation">(fdclass="token punctuation">, buf_pclass="token punctuation">, len_pclass="token punctuation">)class="token punctuation">; class="token comment">// 写入period值class="token function">writeclass="token punctuation">(fdclass="token punctuation">, buf_dclass="token punctuation">, len_dclass="token punctuation">)class="token punctuation">; class="token comment">// 写入duty_cycle
class="token punctuation">}
code>

龙芯PWM实现

ckquote>

1.PWM控制器可能集成在SoC中c;需内核启用pwm-ls等专用驱动。
2.周期(period)单位通常为纳秒(ns)c;需根据硬件限制设置合理值。

ckquote>

UART_135">二、龙芯UART深度解析

1. 硬件架构

控制器类型

ckquote>

控制器类型:龙芯UART兼容NS16550A标准c;支持DMA和FIFO模式

ckquote>

时钟源

ckquote>

时钟源:通常由APB总线时钟分频得到c;例如LS2K1000的APB时钟为100MHz。

ckquote>

寄存器映射

ckquote>

寄存器映射:通过内存映射访问c;用户空间无需直接操作寄存器。

ckquote>

2. 关键寄存器

ckquote>

寄存器 功能 偏移地址
RBR 接收缓冲 0x00
THR 发送保持 0x00
IER 中断使能 0x01
FCR FIFO控制 0x02
LCR 线路控制 0x03
MCR Modem控制 0x04
LSR 线路状态 0x05

ckquote>

3. 驱动配置

内核配置

ckquote>

内核配置:确保启用CONFIG_SERIAL_8250和CONFIG_SERIAL_8250_CONSOLE。

ckquote>

设备树配置

ckquote>

设备树配置:
uart0: serial@1fe40000 {
compatible = “ns16550a”;
reg = <0x1fe40000 0x100>;
interrupts = <8>;
clock-frequency = <100000000>; // APB时钟
};

ckquote>

4. 波特率计算

公式

ckquote>

公式:波特率 = 时钟频率 / (16 * 分频系数)

ckquote>

示例

ckquote>

示例:若时钟为100MHzc;要求115200波特率:
分频系数 = 100000000 / (16 * 115200) ≈ 54.25
实际写入分频寄存器值:54(误差约0.46%)

ckquote>

三、代码优化建议

错误处理增强

<code class="prism language-c">class="token comment">// 在open_port中添加重试逻辑
class="token keyword">int class="token function">open_portclass="token punctuation">(class="token keyword">char class="token operator">*dirclass="token punctuation">) class="token punctuation">{class="token keyword">int fdclass="token punctuation">, retries class="token operator">= class="token number">3class="token punctuation">;class="token keyword">whileclass="token punctuation">(retriesclass="token operator">--class="token punctuation">) class="token punctuation">{fd class="token operator">= class="token function">openclass="token punctuation">(dirclass="token punctuation">, O_RDWR class="token operator">| O_NOCTTYclass="token punctuation">)class="token punctuation">;class="token keyword">ifclass="token punctuation">(fd class="token operator">>= class="token number">0class="token punctuation">) class="token keyword">return fdclass="token punctuation">;class="token function">usleepclass="token punctuation">(class="token number">100000class="token punctuation">)class="token punctuation">; class="token comment">// 等待100ms重试class="token punctuation">}class="token keyword">return class="token operator">-class="token number">1class="token punctuation">;
class="token punctuation">}
code>

非阻塞读取优化

<code class="prism language-c">class="token comment">// 使用select实现超时读取
fd_set readsetclass="token punctuation">;
class="token function">FD_ZEROclass="token punctuation">(class="token operator">&readsetclass="token punctuation">)class="token punctuation">;
class="token function">FD_SETclass="token punctuation">(uart_fdclass="token punctuation">, class="token operator">&readsetclass="token punctuation">)class="token punctuation">;
class="token keyword">struct class="token class-name">timeval timeout class="token operator">= class="token punctuation">{class="token number">0class="token punctuation">, class="token number">500000class="token punctuation">}class="token punctuation">; class="token comment">// 500ms超时
class="token keyword">ifclass="token punctuation">(class="token function">selectclass="token punctuation">(uart_fdclass="token operator">+class="token number">1class="token punctuation">, class="token operator">&readsetclass="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token constant">NULLclass="token punctuation">, class="token operator">&timeoutclass="token punctuation">) class="token operator">> class="token number">0class="token punctuation">) class="token punctuation">{class="token function">readclass="token punctuation">(uart_fdclass="token punctuation">, bufclass="token punctuation">, lenclass="token punctuation">)class="token punctuation">;
class="token punctuation">}
code>

PWM配置封装

<code class="prism language-c">class="token keyword">void class="token function">pwm_initclass="token punctuation">(class="token keyword">int pwmclass="token punctuation">, class="token keyword">int periodclass="token punctuation">, class="token keyword">int dutyclass="token punctuation">) class="token punctuation">{class="token function">pwm_exportclass="token punctuation">(pwmclass="token punctuation">)class="token punctuation">;class="token function">pwm_configclass="token punctuation">(pwmclass="token punctuation">, periodclass="token punctuation">, dutyclass="token punctuation">)class="token punctuation">;class="token function">pwm_enableclass="token punctuation">(pwmclass="token punctuation">)class="token punctuation">;
class="token punctuation">}
code>

四、龙芯开发注意事项

串口引脚复用

ckquote>

确认硬件设计中UARTTX/RX引脚未被复用为GPIO或其他功能࿰c;需通过PINCTRL配置

ckquote>

DMA模式启用

ckquote>

对于高速传输(>1Mbps)࿰c;可在内核驱动中启用DMA模式

ckquote>
<code class="prism language-c">class="token comment">// 修改驱动源码(drivers/tty/serial/8250/8250_port.c
upclass="token operator">->dma class="token operator">= class="token function">dma_request_slave_channelclass="token punctuation">(devclass="token punctuation">, class="token string">"rx-tx"class="token punctuation">)class="token punctuation">;
code>

硬件流控配置

ckquote>

若需RTS/CTS流控࿰c;在termios中设置:

ckquote>
<code class="prism language-c">newtioclass="token punctuation">.c_cflag class="token operator">|= CRTSCTSclass="token punctuation">;
code>

系统稳定性

ckquote>

长时间运行需监控UART错误状态:

ckquote>
<code class="prism language-c">class="token keyword">int statusclass="token punctuation">;
class="token function">ioctlclass="token punctuation">(uart_fdclass="token punctuation">, TIOCMGETclass="token punctuation">, class="token operator">&statusclass="token punctuation">)class="token punctuation">;
class="token keyword">ifclass="token punctuation">(status class="token operator">& TIOCM_CTSclass="token punctuation">) class="token punctuation">{ class="token comment">/* 处理CTS状态 */ class="token punctuation">}
code>

以上分析结合了代码逻辑与龙芯平台特性c;实际开发中需参考具体硬件手册调整参数。



http://www.ppmy.cn/embedded/173815.html

相关文章

Qt QML解决SVG图片显示模糊的问题

前言 在QML中直接使用SVG图片&#xff0c;使用Image控件加载资源&#xff0c;显示出来图片是模糊的&#xff0c;很影响使用体验。本文介绍重新绘制SVG图片&#xff0c;然后注册到QML中使用。 效果图&#xff1a; 左边是直接使用Image加载资源显示的效果 右边是重绘后的效果 …

Java集合的底层原理

目录 Collection Arraylist HashSet 介绍 哈希值 哈希表的基本概念 HashSet 的内部实现 HashMap 哈希碰撞的处理 总结 TreeSet 特点 红黑树的特性 红黑规则 TreeSet 的内部实现 1. 存储结构 2. 添加元素&#xff08;重点&#xff09; 3. 查找元素 4. 删除元…

DexClassLoader 动态加载机制

DexClassLoader 动态加载机制 DexClassLoader 是 Android 提供的 动态加载 DEX&#xff08;Dalvik Executable&#xff09;文件 的工具&#xff0c;允许应用在 运行时 加载 .dex 或 .apk 文件中的类&#xff0c;而不需要在编译时静态引入。 1. DexClassLoader 介绍 DexClassL…

使用PyMongo操作MongoDB(一)

使用PyMongo操作MongoDB MongoDB作为一款流行的NoSQL数据库&#xff0c;以其灵活的数据模型和强大的查询能力受到开发者青睐。通过PyMongo库&#xff0c;我们可以在Python中轻松实现与MongoDB的交互。本文将系统介绍PyMongo的安装、连接及数据库操作全流程。 一、环境准备 安…

Redis客户端Jedis、Lettuce 和 Redisson优缺点总结

https://developer.huawei.com/consumer/cn/blog/topic/03825550899620047 Redis 官方推荐的 Java 客户端有Jedis、Lettuce 和 Redisson。本文总结这些客服端的优缺点 1. Jedis Jedis 是老牌的 Redis 的 Java 实现客户端&#xff0c;提供了比较全面的 Redis 命令的支持&#…

总结 kotlin中的关键字和常用方法

Kotlin 的关键字分为 硬关键字&#xff08;Hard Keywords&#xff09;、软关键字&#xff08;Soft Keywords&#xff09; 和 修饰符关键字&#xff08;Modifier Keywords&#xff09;。以下是分类整理的关键字列表及其核心用途&#xff1a; 1. 硬关键字&#xff08;Hard Keywor…

【数据库】如何用索引优化查询性能

引言 在数据库查询中&#xff0c;索引是提升性能的关键工具。合理使用索引可以显著减少数据扫描量&#xff0c;加快查询速度。然而&#xff0c;索引的使用也需要谨慎&#xff0c;错误的索引策略可能导致性能下降甚至系统崩溃。本文将深入探讨如何通过索引优化查询性能&#xf…

函数(函数的概念、库函数、自定义函数、形参和实参、return语句、数组做函数参数、嵌套调用和链式访问、函数的声明和定义、static和extern)

一、函数的概念 •C语⾔中的函数&#xff1a;⼀个完成某项特定的任务的⼀⼩段代码 •函数又被翻译为子函数&#xff08;更准确&#xff09; •在C语⾔中我们⼀般会⻅到两类函数&#xff1a;库函数 ⾃定义函数 二、库函数 1 .标准库和头文件 •C语⾔的国际标准ANSIC规定了⼀…