目录

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


文章目录


前言

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


一、代码结构解析

1. 头文件部分

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

作用

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

2. 宏定义与全局变量

c 复制代码
#define EXPORT "/sys/class/gpio/export"  // GPIO导出路径
#define DEV_NAME "/dev/ttyS2"            // 龙芯UART设备节点
#define pwm1 1                           // PWM通道定义

龙芯特性

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

3. 主函数流程

c 复制代码
int main() {
    // 初始化UART
    uart_fd = open_port(DEV_NAME);        // 打开串口设备
    set_port(uart_fd, 115200, 8, 'N', 1); // 配置波特率等参数
    
    while(1) {
        usleep(500000);                  // 延时500ms
        memset(read_buf, 0, sizeof(read_buf));
        tcflush(uart_fd, TCOFLUSH);       // 清空缓冲区
        nread = read(uart_fd, read_buf, 4);// 尝试读取数据
        write_buf[0] = 6;                 // 发送数据6
        Uart_Send(uart_fd, write_buf, 1); // 发送单字节
    }
}

关键点

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

4. UART发送函数

c 复制代码
int Uart_Send(int fd, char *send_buf, int data_len) {
    return write(fd, send_buf, data_len); // 直接调用系统写函数
}

龙芯实现

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

5. 串口配置函数(set_port)

c 复制代码
int set_port(int fd, int nSpeed, int nBits, char nEvent, int nStop) {
    struct termios newtio;
    // 配置数据位、校验位、停止位
    newtio.c_cflag |= CLOCAL | CREAD; // 本地连接+使能接收
    // 波特率设置(关键代码段)
    cfsetospeed(&newtio, B115200);    // 输出波特率
    cfsetispeed(&newtio, B115200);    // 输入波特率
    // 应用配置
    tcsetattr(fd, TCSANOW, &newtio);
}

龙芯注意事项

1.波特率精度 依赖时钟分频器 ,需在硬件设计中确认UART时钟源频率。

2.若需更高波特率(如3Mbps) ,可能需要修改内核驱动中的分频参数。

6. GPIO控制函数

c 复制代码
void export_gpio(int gpio) {
    system("echo XX > /sys/class/gpio/export"); // 通过sysfs操作
}

龙芯GPIO特性

1.GPIO编号 需参考具体开发板手册,如LS2K1000的GPIO可能按Bank分组管理
2.部分GPIO可能复用为其他功能(如UART) ,需配置引脚复用寄存器

7. PWM控制函数

c 复制代码
int pwm_config(unsigned int pwm, unsigned int period, duty_cycle) {
    // 通过sysfs设置周期和占空比
    write(fd, buf_p, len_p); // 写入period值
    write(fd, buf_d, len_d); // 写入duty_cycle
}

龙芯PWM实现

1.PWM控制器可能集成在SoC中 ,需内核启用pwm-ls 等专用驱动。

2.周期(period)单位通常为纳秒(ns),需根据硬件限制设置合理值。

二、龙芯UART深度解析

1. 硬件架构

控制器类型

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

时钟源

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

寄存器映射

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

2. 关键寄存器

寄存器 功能 偏移地址

RBR 接收缓冲 0x00

THR 发送保持 0x00

IER 中断使能 0x01

FCR FIFO控制 0x02

LCR 线路控制 0x03

MCR Modem控制 0x04

LSR 线路状态 0x05

3. 驱动配置

内核配置

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

设备树配置

设备树配置:

uart0: serial@1fe40000 {

compatible = "ns16550a";

reg = <0x1fe40000 0x100>;

interrupts = <8>;

clock-frequency = <100000000>; // APB时钟

};

4. 波特率计算

公式

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

示例

示例:若时钟为100MHz ,要求115200波特率:

分频系数 = 100000000 / (16 * 115200) ≈ 54.25

实际写入分频寄存器值:54(误差约0.46%)

三、代码优化建议

错误处理增强

c 复制代码
// 在open_port中添加重试逻辑
int open_port(char *dir) {
    int fd, retries = 3;
    while(retries--) {
        fd = open(dir, O_RDWR | O_NOCTTY);
        if(fd >= 0) return fd;
        usleep(100000); // 等待100ms重试
    }
    return -1;
}

非阻塞读取优化

c 复制代码
// 使用select实现超时读取
fd_set readset;
FD_ZERO(&readset);
FD_SET(uart_fd, &readset);
struct timeval timeout = {0, 500000}; // 500ms超时
if(select(uart_fd+1, &readset, NULL, NULL, &timeout) > 0) {
    read(uart_fd, buf, len);
}

PWM配置封装

c 复制代码
void pwm_init(int pwm, int period, int duty) {
    pwm_export(pwm);
    pwm_config(pwm, period, duty);
    pwm_enable(pwm);
}

四、龙芯开发注意事项

串口引脚复用

确认硬件设计中UART的TX/RX引脚未被复用为GPIO或其他功能,需通过PINCTRL配置

DMA模式启用

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

c 复制代码
// 修改驱动源码(drivers/tty/serial/8250/8250_port.c)
up->dma = dma_request_slave_channel(dev, "rx-tx");

硬件流控配置

若需RTS/CTS流控,在termios中设置:

c 复制代码
newtio.c_cflag |= CRTSCTS;

系统稳定性

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

c 复制代码
int status;
ioctl(uart_fd, TIOCMGET, &status);
if(status & TIOCM_CTS) { /* 处理CTS状态 */ }

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


本文是转载文章,点击查看原文
如有侵权,请联系 xyy@jishuzhan.net 删除
相关推荐
正点原子2 小时前
【正点原子STM32MP257连载】第二章 ATK-DLMP257B使用前准备 #串口软件 #MobaXterm
linux·stm32·单片机·嵌入式硬件
ℳ๓. Sweet2 小时前
【STM32】在FreeRTOS下使用硬件SPI收发数据出现的时序耦合问题(WK2124芯片为例)
stm32·单片机·嵌入式硬件
charlie1145141913 小时前
IMX6ULL2025年最新部署方案2在Ubuntu24.04上编译通过Qt5.12.9且部署到IMX6ULL正点原子开发板上
linux·嵌入式硬件·qt·系统架构·嵌入式软件·移植教程
努力创造奇迹5 小时前
STM32 HAL库 实现485通信
stm32·单片机·嵌入式硬件
Tlog嵌入式5 小时前
STM32提高篇: 以太网通讯
网络·stm32·单片机·嵌入式硬件·mcu·iot
菜狗想要变强7 小时前
RVOS-7.实现抢占式多任务
linux·c语言·驱动开发·单片机·嵌入式硬件·risc-v
番茄老夫子7 小时前
适合stm32 前端adc使用的放大器芯片
stm32·单片机·嵌入式硬件
m0_疾风8 小时前
STM32
stm32·单片机·嵌入式硬件
硬匠的博客8 小时前
C/C++基础
stm32·单片机·嵌入式硬件
LaoZhangGong1238 小时前
MCU屏和RGB屏
经验分享·stm32·单片机·嵌入式硬件·fsmc