(转贴)Windows CE 5.0下串口驱动硬件FIFO控制Bug分析及修正方法

2023-05-16

转贴自:驱动开发网

原贴地址:http://bbs.driverdevelop.com/read.php?tid=109193&fpage=0&toread=&page=1

作者:周群威

摘要:详细分析了Windows CE 5.0下串口驱动程序中硬件FIFO控制的一个Bug,并给出了修改方法,对修改前后的驱动程序的性能进行了测试,测试结果表明改进后的驱动性能得到了很大的提升。
   
关键词:Windows CE    WinCE   串口驱动   串口丢包 

仔细阅读Windows CE 5.0下串口驱动关于硬件FIFO控制后,发现一个Bug,该Bug的表现是通过注册表设置的硬件FIFO大小无效,实际的驱动只会将硬件FIFO触发点设置成最小值(无FIFO)和最大值(7/8满FIFO)时触发中断,这一Bug导致了在Windows CE5.0下用高波特率(如115200)的总线外扩标准16C2550串口芯片连续接收大量数据时容易出现丢包现象。(实际测试时使用PXA270外部总线扩展SC16C2550B串口芯片,在115200的波特率下很容易出现丢包现象(无硬件流控),如果在通信过程中有其它驱动产生中断(如插入USB Device,则这种现象更为严重))。
1. Windows CE 5.0下串口驱动硬件FIFO控制Bug分析
首先我我们看CPdd16550::GetWaterMarkBit()函数,该函数的作用是查表得出硬件FIFO触发点设置的掩码位。该函数的源代码在WINCE500/public/common/oak/drivers/serial/ oo16550/pdd16550.cpp中(约第467行)。CPdd16550::GetWaterMarkBit()函数的实现代码如程序清单 1.1所示。
程序清单 1.1 CPdd16550::GetWaterMarkBit()函数
/*
* 硬件FIFO触发点设置掩码位表
*/
static PAIRS s_HighWaterPairs[] = {
    {SERIAL_1_BYTE_HIGH_WATER, 0},
    {SERIAL_4_BYTE_HIGH_WATER, 4},
    {SERIAL_8_BYTE_HIGH_WATER, 8},
    {SERIAL_14_BYTE_HIGH_WATER, 14}
};

BYTE  CPdd16550::GetWaterMarkBit()
{
    BYTE bReturnKey = (BYTE)s_HighWaterPairs[0].Key;
    for (DWORD dwIndex=dim(s_HighWaterPairs)-1;dwIndex!=0; dwIndex --) {    /* 从表尾开始查找    */
        if (m_dwWaterMark>=s_HighWaterPairs[dwIndex].AssociatedValue) {      /* 找到            */
            bReturnKey = (BYTE)s_HighWaterPairs[dwIndex].Key;            /* 记录掩码位的值 */
            break;
        }
    }
    return bReturnKey;                                            /* 返回掩码位       */
}

该程序中,PAIRS结构体在WINCE500/PUBLIC/COMMON/OAK/INC/pdd16550.h中定义,它的原型如程序清单 1.2所示。
程序清单 1.2 PAIRS结构体
typedef struct  __PAIRS {
    ULONG   Key;
    ULONG   AssociatedValue;
} PAIRS, *PPAIRS;

SERIAL_1_BYTE_HIGH_WATER、SERIAL_4_BYTE_HIGH_WATER等宏定义在WINCE500 /PUBLIC/COMMON/OAK/INC/hw16550.h中,如程序清单 1.3所示。
程序清单 1.3 相关宏定义
#define SERIAL_1_BYTE_HIGH_WATER   ((UCHAR)0x00)
#define SERIAL_4_BYTE_HIGH_WATER   ((UCHAR)0x40)
#define SERIAL_8_BYTE_HIGH_WATER   ((UCHAR)0x80)
#define SERIAL_14_BYTE_HIGH_WATER  ((UCHAR)0xc0)

我们来分析一下CPdd16550::GetWaterMarkBit()函数,它的返回值只能是0x00、0x40、0x80和0xC0四个中的一个。而要准确地计算出它的返回值,我们需要得到CPdd16550的一个成员变量m_dwWaterMark的值,m_dwWaterMark的值在CPdd16550::Init()函数中初始化,我们再来看看CPdd16550::Init()函数的实现代码,如程序清单 1.4所示。
程序清单 1.4 CPdd16550::Init()函数
BOOL CPdd16550::Init()
{
    if ( CSerialPDD::Init() && IsKeyOpened() && m_XmitFlushDone!=NULL) {
        // IST Setup .
        DDKISRINFO ddi;
        if (GetIsrInfo(&ddi)!=ERROR_SUCCESS) {
            return FALSE;
        }
        m_dwSysIntr = ddi.dwSysintr;
        if (m_dwSysIntr !=  MAXDWORD && m_dwSysIntr!=0 )
            m_hISTEvent= CreateEvent(0,FALSE,FALSE,NULL);
       
        if (m_hISTEvent!=NULL) {
            if (!InterruptInitialize(m_dwSysIntr,m_hISTEvent,0,0)) {
                m_dwSysIntr = MAXDWORD ;
                return FALSE;
            }
        }
        else
            return FALSE;
        // Get Device Index.
        if (!GetRegValue(PC_REG_DEVINDEX_VAL_NAME,
(PBYTE)&m_dwDevIndex, PC_REG_DEVINDEX_VAL_LEN)) {
            m_dwDevIndex = 0;
        }
/*
* 从注册表读取硬件FIFO大小
*/
        if (!GetRegValue(PC_REG_SERIALWATERMARK_VAL_NAME,                     (1)
(PBYTE)&m_dwWaterMark,sizeof(DWORD))) {
            m_dwWaterMark = 8;
        }
        if (!MapHardware() || !CreateHardwareAccess()) {
            return FALSE;
        }
        return TRUE;
    }
    return FALSE;
}

程序清单 1.4(1)从注册表读取硬件FIFO的大小到CPdd16550的成员变量m_dwWaterMark中,如果注册表中没有这个设置值,则使用默认值8。即8个字节的硬件FIFO。
最后我们来看看串口驱动是怎么设置串口FIFO硬件流控的。如程序清单 1.5所示。
程序清单 1.5 CPdd16550::InitReceive()函数
BOOL    CPdd16550::InitReceive(BOOL bInit)
{
    m_HardwareLock.Lock();   
    if (bInit) {        
        BYTE uWarterMarkBit = GetWaterMarkBit();       ( 1 )/* 读取硬件FIFO触发点设置掩码位*/
        if (uWarterMarkBit> 3)                          ( 2 )/* 检查合法性                */
            uWarterMarkBit = 3;
        m_pReg16550->Write_FCR(m_pReg16550->Read_FCR() |
SERIAL_FCR_RCVR_RESET |
SERIAL_FCR_ENABLE |
(uWarterMarkBit<<6));  ( 3 ) /* 设置硬件FIFO触发点          */
        m_pReg16550->Write_IER(m_pReg16550->Read_IER() | SERIAL_IER_RDA);
        m_pReg16550->Read_LSR(); // Clean Line Interrupt.
    }
    else {
        m_pReg16550->Write_IER(m_pReg16550->Read_IER() & ~SERIAL_IER_RDA);
    }
    m_HardwareLock.Unlock();
    return TRUE;
}

程序清单 1.5(1)获取串口硬件FIFO触发点掩码位,然后检查它的合法性(程序清单 1.5(2))如果大于最大值3,则取最大值3(因为硬件FIFO的触发点只有四个等级,最大值为3)。程序清单 1.5(2)将硬件FIFO触发点掩码位写入到串口硬件的FCR(FIFO控制寄存器)中。
注:对于标准16C2550的串口,FCR的第7~6(两位)对应硬件FIFO触发点设置。共四个等级,00B1字节触发;01B4字节触发;10B8字节触发;11B14字节触发。对于标准16C2550串口FIFO的大小是16字节。
由前面对CBulPdd16550::GetWaterMarkBit()函数的分析可知GetWaterMarkBit()函数的返回值是0x00、0x40、0x80和0xC0四个中的一个,在默认情况下的返回值是0x80。由于GetWaterMarkBit()函数的返回值的后三个值都大于3,这样,就导致了只要串口驱动注册表中硬件FIFO的设置值大于3,驱动就会将硬件FIFO的触发点设置在7/8的位置上(14字节),这样,当连续接收大量数据时,如果串口IST不能及时读走FIFO中的数据(发生中断时FIFO再接收两个字节就满),将导致串口通信出现丢失数据的情况,当系统任务繁重时这种情况就会更加严重。
2. 修正方法
由前面的分析可知,这个Bug主要是由CBulPdd16550::GetWaterMarkBit()函数引起的,可以有以下几个方法来修正这个Bug:
方法一:修改程序清单 1.3的宏定义如程序清单 2.1所示,加粗的代码为修改了的地方。
程序清单 2.1 修改宏定义
#define SERIAL_1_BYTE_HIGH_WATER   ((UCHAR)0x00)
#define SERIAL_4_BYTE_HIGH_WATER   ((UCHAR)0x01)
#define SERIAL_8_BYTE_HIGH_WATER   ((UCHAR)0x02)
#define SERIAL_14_BYTE_HIGH_WATER  ((UCHAR)0x03)

这样,在程序清单 1.5 CPdd16550::InitReceive()函数中,当调用GetWaterMarkBit()函数时,就能得到正确的掩码位。
方法二:修改程序清单 1.5(3)的代码如程序清单 2.2加粗的代码所示。这跟方法一的原理是一样的。
程序清单 2.2修改CPdd16550::InitReceive()函数
m_pReg16550->Write_FCR(m_pReg16550->Read_FCR() |
SERIAL_FCR_RCVR_RESET |
SERIAL_FCR_ENABLE |
                                (uWarterMarkBit));         ( 3 ) /* 设置硬件FIFO触发点      */

方法三:修改CBulPdd16550::GetWaterMarkBit()函数,如程序清单 2.3加粗的代码所示。
程序清单 2.3 修改CPdd16550::GetWaterMarkBit()函数
BYTE  CPdd16550::GetWaterMarkBit()
{
    BYTE bReturnKey = (BYTE)s_HighWaterPairs[0].Key;
    for (DWORD dwIndex=dim(s_HighWaterPairs)-1;dwIndex!=0; dwIndex --) {    /* 从表尾开始查找    */
        if (m_dwWaterMark>=s_HighWaterPairs[dwIndex].AssociatedValue) {      /* 找到            */
            bReturnKey = (BYTE)s_HighWaterPairs[dwIndex].Key;            /* 记录掩码位的值 */
            break;
        }
    }
    return ((bReturnKey >> 6) & 0x03);                                /* 返回掩码位       */
}
由于CBulPdd16550::GetWaterMarkBit()函数被声明为虚函数,因此,我们可以继承CBulPdd16550类来生成一个新的类CExtPdd16550FUART,在该类中重新实现GetWaterMarkBit()函数并修正这个Bug,这样,就可以在不改动微软驱动源代码的情况下轻松修正这个Bug。其实现源代码如程序清单 2.4所示。(推荐大家用这个方法)此代码放到/WINCE500/PLATFORM/MAINSTONEII/src/drivers/serial/ms2_serial.cpp中。(对于MAINSTONEII平台)
程序清单 2.4 重新实现GetWaterMarkBit()函数
/*
*  硬件FIFO掩码位表
*/
static PAIRS s_HighWaterPairs[] = {
        {SERIAL_1_BYTE_HIGH_WATER, 0},
        {SERIAL_4_BYTE_HIGH_WATER, 4},
        {SERIAL_8_BYTE_HIGH_WATER, 8},
        {SERIAL_14_BYTE_HIGH_WATER, 14}
    };
/****************************************************************************************
** Function name:   CExtPdd16550FUART
** Descriptions:    外扩串口对象
**------------------------------------------------------------------------------------------------------------
** Modified by:     周群威
** Modified Date:   2008-02-16
**-----------------------------------------------------------------------------------------------------------
******************************************************************************************/
class CExtPdd16550FUART : public CPdd16550 {
public:

    CExtPdd16550FUART (LPTSTR lpActivePath, PVOID pMdd, PHWOBJ pHwObj)
        : CPdd16550 (lpActivePath,pMdd, pHwObj) {
    };
    ~CExtPdd16550FUART()
    {
    }
/******************************************************************************************
** Function name:   CExtPdd16550FUART::GetWaterMarkBit
** Descriptions:    获取串口硬件FIFO触发点掩码
** Input:          无
** Output:         无
** Return:         串口硬件FIFO触发点掩码
** Note:           PDD16550实现方法有Bug,所以在这里重新实现该方法,详见该函数的注释
** Created by:      MicroSoft
** Created Date:    未知
**----------------------------------------------------------------------------------------------------------------
** Modified by:     周群威
** Modified Date:   2008-02-16
**-------------------------------------------------------------------------------------------------------------
******************************************************************************************/
    virtual BYTE GetWaterMarkBit()
    {
        BYTE bReturnKey = (BYTE)s_HighWaterPairs[0].Key;
        for (DWORD dwIndex=dim(s_HighWaterPairs)-1;dwIndex!=0; dwIndex --) {     /*  查表     */
            if (m_dwWaterMark>=s_HighWaterPairs[dwIndex].AssociatedValue) {     /*  找到      */
                bReturnKey = (BYTE)s_HighWaterPairs[dwIndex].Key;
                break;
            }
        }
        /*
         *  原来的代码(在Public目录下串口驱动的PDD16550类中的实现方法是直接返回bReturnKey
         *  导至在后面设置硬件FIFO时发现FIFO触发点掩码位>3,所以将硬件FIFO触发点设到了最大
         *  值上而不管注册表的的设置值是多少,从而导至了当串口接收大量数据时由于中断服务线程
         *  的延时容易引起串口接收丢包(因为串口中断时,FIFO已经要满了,如果中断服务线程没有及时
         *  读走数据则新发过来的数据由于没有FIFO而丢失)
         */
        return ((bReturnKey >> 6) & 0x03);
    }
};

/****************************************************************************************
** Function name:   CreateSerialObject
** Descriptions:     创建串口驱动PDD层对象
** Input:           lpActivePath,串口驱动注册表路径
**                pMdd,串口驱动MDD层对象指针
**                pHwObj,串口驱动硬件操作函数结构
**                DeviceArrayIndex,串口类型
** Output:          无
** Return:          串口对象指针
** Note:           
** Created by:      MicroSoft
** Created Date:    未知
**------------------------------------------------------------------------------------------------------------------
** Modified by:     周群威
** Modified Date:   2008-02-16
**-----------------------------------------------------------------------------------------------------------------
******************************************************************************************/
CSerialPDD * CreateSerialObject(LPTSTR lpActivePath,
PVOID pMdd,
PHWOBJ pHwObj,
DWORD DeviceArrayIndex)
{
    CSerialPDD * pSerialPDD = NULL;
    switch (DeviceArrayIndex ) {                      /*  根据串口类型生成不同的串口对象实例*/
        case 0:default:
            pSerialPDD = new CPdd16550(lpActivePath,pMdd, pHwObj);
            break;
        case 0x80:
            pSerialPDD = new CBulPdd16550FUART (lpActivePath,pMdd, pHwObj);
            break;
        case 0x81:
            pSerialPDD = new CBulPdd16550BUART(lpActivePath,pMdd, pHwObj);
            break;
        case 0x82:
            pSerialPDD = new CBulPdd16550SUART(lpActivePath,pMdd, pHwObj);
            break;
        case 0x84:                                /*  外扩串口在这时定义为0x84     */
            DEBUGMSG(1,(_T("Load Ext Uart /r/n")));
            pSerialPDD = new CExtPdd16550FUART(lpActivePath,pMdd, pHwObj);
            break;
    }
    if (pSerialPDD && pSerialPDD->Init()!= TRUE) {       /*  初始化串口驱动PDD层对象     */
        delete pSerialPDD;
        pSerialPDD = NULL;
    }
    return pSerialPDD;
}
经以上修改后再重新测试串口的性能,发现在没有USB Device插入中断时,串口连续收发大量数据时的正确率为100%(专门写了一个两个外扩串口数据对发测试程序,一次收发100字节再比较)。而没有修改前的正确率为96%左右。如果在测试过程中有USB Device插入的话(有中断产生),则在插入时可能丢失几个字节,这可以通过换用更大FIFO的串口芯片来解决,也可以通过注册表来提高串口驱动IST的优先级来解决,实践表明,只要串口IST的优先级小于100(因为在Windows CE 5.0驱动的默认优先级中,USB Device的最高,为100),串口就不会丢包了。
3. 参考资料
Platform Builder帮助文档
Windows CE 5.0串口驱动源代码

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

(转贴)Windows CE 5.0下串口驱动硬件FIFO控制Bug分析及修正方法 的相关文章

  • 块元素、行内元素、行内块元素区别及其作用

    块元素 块级元素独占一行 默认会新起一行 xff0c 如 xff1a div p h1 根据这个特性可以实现盒子水平居中margin 0 auto 原理 块级元素独占一行设置大小后水平方向会剩余空间 设置auto左右会自动分配剩余空间 行内
  • Ubuntu安装Docker 时遇到的一个问题

    Ubuntu安装Docker 详细步骤和结果展示 https docs docker com engine install ubuntu 问题描述 xff1a ubuntu 的包管理是通过 apt get 来做的 xff0c 但是默认的 a
  • win10 能Ping通却无法访问虚拟机Ubuntu 14.04 samba的问题(已解决)

    windows系统版本 xff1a Win10 虚拟机版本 xff1a VMware Workstation 12 Pro Ubuntu版本 xff1a 14 04 在更新windows10补丁之前 xff0c Win10是能访问Ubunt
  • c51单片机学习笔记-LED流水灯库函数实验

    目的 xff1a 实现 LED 流水灯 xff0c 只需循环让 D1 D8 指示灯逐个点亮再从D8 D1逐个点亮 xff0c 循环下去 方法 xff1a 利用移位库函数 xff0c 点亮 D1 且把 D2 D8 熄灭 xff0c 延时一段时
  • 关于STM32F405单片机控制雷达模块lidar_lite_v3程序及说明

    include 34 stm32f4 iic h 34 include 34 lidar lite v3 h 34 include 34 stm32f4 delay h 34 uint8 t WriteBuffer 61 0x55 Read
  • 常用串口调试工具比较(详细)

    目前有许多免费的串口调试工具 xff0c 比较常用的有 xff1a 1 友善串口调试助手 xff08 v2 6 5 xff09 优点 xff1a 1 xff09 使用方便 xff0c 不丢包 xff1b 2 xff09 串口自动识别 xff
  • FreeRTOS 变量名,函数名,宏的命名规则(2)

    前言 内容均来自野火相关书籍 xff0c 写博客是为了方便查看 xff1b 博客内容并不完善 xff0c 慢慢补充 xff1b 函数名 xff1a 包含函数返回值的类型 函数所在的文件名和函数的功能 例 xff1a vTaskPriorit
  • 头文件包含顺序的建议

    使用标准的头文件包含顺序可增强可读性 避免隐藏依赖 xff0c 建议的包含顺序如下 xff1a C或C 43 43 等源文件中按照以下顺序包含 xff0c 建议按照稳定度排序 xff1a c cpp对应的头文件 C C 43 43 标准库的
  • [问题解决方案] ubuntu 14.04 分辨率调整 -- xrandr命令

    问题描述 xff1a 自己在安装ubuntu kylin 14 04 TLS系统成功后 xff0c 在调整分辨率的时候 xff08 系统设置 显示 xff09 发现分辨率的选项只有1024x768以及800x600两个选项 xff0c 而台
  • 1、烧录系统到sd卡,从sd卡启动系统

    烧写系统到sd卡 硬件 xff1a 用的是友善之臂的NanoPC T4工业级开发板 步骤 xff1a 1 准备好一个sd卡 xff08 class10以上高速SDHC卡 xff09 和一个读卡器 大小最好16g以上 xff0c 保证空间充裕
  • 12、Gazebo的安装问题

    一 Gazebo的安装问题 1 安装的官网的网址 xff1a http gazebosim org tutorials cat 61 install amp tut 61 install ubuntu amp ver 61 9 0 2 安装
  • 11、ros依赖包安装问题

    一 问题 在ROS编译过程中经常会遇到找不到ROS包的情况 xff0c 那么一般情况下该如何解决问题呢 xff1f 我们通常用apt来进行安装 xff0c 实际上有时候apt在处理依赖关系上是没有aptitude那么智能的 xff0c 所以
  • 12、TX2(ARM架构)平台换源

    关于换源的教程可参考一下其他博主的两篇文章 ARM架构换源 Ubuntu 国内源介绍 针对本机的换源操作如下 xff1a 进入配置目录 span class token function cd span etc apt 备份sources
  • VirtualBox 每天自动创建快照

    需求很简单 每天自动对虚拟机创建一个快照 避免忘记备份 同时给自己减少一点工作量 主要思路就是通过VBoxManage的命令行操作和windows的任务计划程序来完成定时备份的工作 VBoxManage 使用帮助如下 C Program F
  • c51单片机学习笔记-动态数码管实验(un)

    目的 xff1a 控制动态数码管从左至右显示数字 0 7 编译软件 xff1a keil5 过程 1 xff09 首先将 51 单片机的头文件包含进来 xff0c 然后定义 38 译码器的控制引脚 xff0c 并将共阴数码管 0 F 断码数
  • 在py-faster-rcnn/lib里make时报错: unrecognized command line option ‘-Wdate-time’

    在py faster rcnn lib里make时报错 xff1a c 43 43 pthread shared Wl O1 Wl Bsymbolic functions Wl Bsymbolic functions Wl z relro
  • C/C++ 日常学习总结(第十九篇)多线程详解

    这些讲解多线程文章都是非常好的 xff0c 我这边就归结出一个 lt 多线程详解 gt 出来 xff0c 感谢各位原创作者的辛苦劳动 xff0c 这些收藏起来方便自己消化 1 多线程笔试面试题汇总 解答地址 xff1a 概念问答 2 深入分
  • python3 算法题:七进制加法

    题目 xff1a 要求键盘输入两个七进制 0 6 数 xff0c 以空格分开 xff0c 计算两者之和输出 xff0c 例如 xff1a 输入 xff1a 16 1 输出 xff1a 20 思路 xff1a 这个题目跟十进制加法一样 xff
  • python3 实现麻将胡牌问题

    题目描述 xff1a 清一色是麻将番种之一 xff0c 指由一种花色的序数牌组成的和牌 数字1 9 xff0c 每个数字最多有4张牌 我们不考虑具体花色 xff0c 我们只看数字组合 刻子 xff1a 三张一样的牌 xff1b 如 111
  • python3爬虫简单介绍

    本文是为了防止自己以后忘了 xff0c 小白可以参考 xff0c 大神请绕道 先来扫盲 xff0c 什么是爬虫 xff1a 爬虫就是一系列按照某种规则自动从网上爬取信息的代码或者脚本 本文代码功能 xff1a 从百度百科里面爬取20个和py

随机推荐

  • python3 使用urllib.request.urlopen及re.findall爬取网页图片并保持本地

    本例使用urllib及re正则表达式 xff0c 爬取网页上 xff08 王俊凯百度百科 xff09 所有以jpg结尾的图片 xff0c 并保存本地 import re from urllib span class token punctu
  • python3 爬取网页内容解析并存入MySQL数据库

    爬取网页内容解析并存入MySQL数据库 用到的第三方库 xff1a BeautifulSoup xff1a 解析网页内容 xff0c 建议安装方法 xff1a pip install beautifulsoup4 pymysql xff1a
  • python二维列表按照某列(字符串列)排序;忽略大小写+区分大小写

    python二维列表按照某列 xff08 字符串列 xff09 排序 xff1b 忽略大小写 43 区分大小写 使用list自带的sorted 方法 xff0c data 61 sorted data key 61 lambda x x 1
  • tkinter 出现两个窗口 tk(未响应) 解决方法

    问题 xff1a tkinter界面开发 xff0c 莫名出现一个叫 tk 未响应 的小窗口 xff0c 最后发现是因为自定义了窗口图标导致产生多余窗口 解决方法 xff1a 将设置窗口图标代码放到设置窗口大小代码之后即可 xff08 该方
  • python3适配pykml教程

    pykml是用python2写的 xff0c 由于python3和python2语法及函数名有所不同 xff0c python3使用的时候需要手动修改几个地方 xff0c 如下 xff1a 1 出现 xff1a ModuleNotFound
  • c51单片机学习笔记-独立按键实验

    目的 xff1a 通过开发板上的独立按键 K1 控制 D1 指示灯亮灭 编译软件 xff1a keil5 过程 xff1a xff08 1 xff09 定义独立按键控制脚 sbit KEY1 61 P3 1 sbit KEY2 61 P3
  • openpyxl为指定区域设置边框为粗匣框线

    前言 xff1a 最近在用openpyxl分析Excel数据 xff0c 为了让表格层次更分明 xff0c 想给制定区域添加粗匣框线 xff0c 网上没有找到现成的方法 xff0c 自己摸索了一下 xff0c 终于解决了 xff0c 现在记
  • ubuntu上网问题以及ping通网络设备

    问题一 xff1a ubuntu上网问题 如何ping www baidu com Ubuntu上网模式有两种 xff1a 桥接和NAT 1 桥接模式 xff1a 前提是 xff1a 主机是连接的无线网 xff0c 主机有线网卡的IP设置的
  • Python脚本调用C++动态库,C++调用Python脚本实操

    一 Python调用C 43 43 动态库 实现方法 xff1a 使用python 的ctypes 模块加载dll 首先 xff0c 需要用VS创建一个dll动态库 xff0c 网上方法很多 xff0c 就不细说了 xff0c 代码如下 x
  • 利用GPU训练时的常见错误

    1 CUDA VIDIBLE DEVICES 61 4 5 python3 main py 我想在集群条件下利用4 5号GPU xff0c 由于模型较小 xff0c 并不清楚是都可以指定4 5号GPU xff08 内存占用情况看不出来 后续
  • Jetson TX1底板的接口调试

    1 I2C总线上外设查询 I2C Tools的安装和使用 在控制台输入 sudo apt get install i2c tools 安装完成后可以使用命令验证安装成功 sudo i2cdetect l I2C设备查询使用 sudo i2c
  • 驱动——platform驱动总线三种匹配方式

    三种platform驱动匹配方式代码案例以及现象 方式一 xff1a 通过设置名字进行匹配 相关API简介 xff1a 1 platform device的API 分配对象 struct platform device const char
  • 开源框架APM工具--SkyWalking原理与应用

    一 分布式链路追踪简介 随着业务系统的不断发展 微服务架构的演进 xff0c 从原来的单体应用架构 垂直应用架构 分布式 SOA 架构到现在的微服务架构 xff0c 系统逐步走向微服务化以适应用户高并发请求等需求 在微服务架构中 xff0c
  • 什么是弹性云服务器?

    ecs云服务器是由CPU 内存 镜像 云硬盘组成的一种可随时获取 弹性可扩展的计算服务器 xff0c 同时它结合虚拟私有云 虚拟防火墙 数据多副本保存等能力 xff0c 为您打造一个高效 可靠 安全的计算环境 xff0c 确保您的服务持久稳
  • linux下修改MAC地址的问题解决

    在linux中 xff0c 修改MAC地址 ifdown eth0 ifconfig eth0 hw ether 12 xff1a 34 xff1a 56 xff1a 78 xff1a 90 xff1a 12 xff08 修改的MAC地址跟
  • 51串口发送数据的格式

    串行口控制寄存器SCON SCON的字节地址是98H xff0c 其格式如下 xff1a SM0 SM1 xff1a 串行口工作方式控制位 xff1a SM0 SM1 工作方式 功能 波特率 00 方式0 同步移位寄存器 fosc 12 0
  • c51单片机学习笔记-矩阵按键实验

    目的 xff1a 通过数码管显示矩阵按键 S1 S16 按下后键值 0 F 编译软件 xff1a keil5 过程 xff1a xff08 1 xff09 定义各端口 include 34 reg52 h 34 typedef unsign
  • CMake 添加第三方库的几种依赖方式

    转载链接 xff1a C 43 43 工程 xff1a 总结 CMake 添加第三方库依赖方式git submodule find library FetchContent CPM等 github地址 cpp cmake example 第
  • vue.js中v-for的使用及索引获取

    vue js中v for的使用及索引获取 1 v for 直接上代码 示例一 xff1a lt DOCTYPE html gt lt html gt lt head gt lt meta charset 61 34 utf 8 34 gt
  • (转贴)Windows CE 5.0下串口驱动硬件FIFO控制Bug分析及修正方法

    转贴自 xff1a 驱动开发网 原贴地址 xff1a http bbs driverdevelop com read php tid 61 109193 amp fpage 61 0 amp toread 61 amp page 61 1