MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态

AFX_MANAGE_STATE  MFC对于跨模块之间的调用破费心机,设计了一条STATE机制.而且设计的颇为麻烦.费了老鼻子劲终于探究了一二而已.转一篇分析的比较好的文章.http://hi.baidu.com/rootlife/blog/item/2f37e354ad8cdc5bd10906be.html这里补充几点:1._afxthreadstate 是全局的,至于每个线程中维护一个_afxthread 阅读详情
  MFC的模块状态:从AfxGetApp()和AFX_MANAGE_STATE()看MFC的模块状态收藏

新一篇: Mac OS X Programming读书笔记4 - Windows | 旧一篇: Mac OS X Programming读书笔记3 - 事件处理

1.      Introduction

当我们在用MFC编程的时候,我们经常用到AfxGetApp()来获得当前的CWinApp的Instance。看看MFC的源代码中AfxGetApp()的实现,你会发现AfxGetApp()的实现并不像一般情况下面那样直接:

_AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()

       { return afxCurrentWinApp; }

#define afxCurrentWinApp    AfxGetModuleState()->m_pCurrentWinApp

AfxGetApp()调用的是AfxGetModuleState(),该函数返回一个AFX_MODULE_STATE的指针,其中的一个成员保存着当前的CWinApp的指针。可AfxGetModuleState()的作用又是什么呢?

 

此外,当我们在开发MFC DLL程序的时候,我们会在每个输出的DLL函数前面加上一句AFX_MANAGE_STATE:

void SomeMFCDllFunction()

{

AFX_MANAGE_STATE(AfxGetStaticModuleState())

…

 

AFX_MANAGE_STATE又是起什么作用呢?从字面上看来,它是Manage某种State,而AfxGetStaticModuleState又是获得State的,那么State究竟是什么呢?

在MFC中,States用来保存某种相关的状态信息,分为下面几类:

1.     Process State,和某个单独的进程绑定起来

2.     Thread State,和某个单独的线程绑定

3.     Module State,和Module相关

前两种State和一般的全局变量十分类似,只是根据需求的不同被绑定于不同的进程/线程,如多线程支持等。而Module State本身比较特别,Module State根据情况的不同,可以是全局,线程,或者进程相关的State,并且可以根据要求快速切换。

2.      Process State

常见的Process State有:

1.     _AFX_WIN_STATE

2.     _AFX_DB_STATE

3.     _AFX_DEBUG_STATE

4.     _AFX_SOCK_STATE

5.     ……

从字面上面可以很容易猜出这些状态的用处。

MFC通过下面的宏来定义Process State:

#define PROCESS_LOCAL(class_name, ident_name) /

       AFX_COMDAT CProcessLocal<class_name> ident_name;

#define EXTERN_PROCESS_LOCAL(class_name, ident_name) /

       extern CProcessLocal<class_name> ident_name;

PROCESS_LOCAL用CProcessLocal模板类定义了一个CProcessLocal<class_name>的一个实例作为状态变量,而EXTERN_PROCESS_LOCAL则使在头文件中声明此状态变量。CProcessLocal的定义如下:

class AFX_NOVTABLE CProcessLocalObject

{

public:

// Attributes

       CNoTrackObject* GetData(CNoTrackObject* (AFXAPI* pfnCreateObject)());

 

// Implementation

       CNoTrackObject* volatile m_pObject;

       ~CProcessLocalObject();

};

 

template<class TYPE>

class CProcessLocal : public CProcessLocalObject

{

// Attributes

public:

       AFX_INLINE TYPE* GetData()

       {

              TYPE* pData = (TYPE*)CProcessLocalObject::GetData(&CreateObject);

              ENSURE(pData != NULL);

              return pData;

       }

       AFX_INLINE TYPE* GetDataNA()

              { return (TYPE*)m_pObject; }

       AFX_INLINE operator TYPE*()

              { return GetData(); }

       AFX_INLINE TYPE* operator->()

              { return GetData(); }

 

// Implementation

public:

       static CNoTrackObject* AFXAPI CreateObject()

              { return new TYPE; }

};

 

CProcessLocal的作用只是一个Wrapper,Hold一个TYPE*的指针,一旦用户调用GetData来获得这个指针,GetData会首先判断该指针是否为空,如果为空,则创建一个新的实例保存起来,否则返回已有的指针。前提条件是,TYPE必须从CNoTrackObject继承。任何从CNoTrackObject继承的类都拥有自己的new/delete,这样此对象便不会被Debug的内存分配系统所跟踪而误判为Leak。

CNoTrackObject* CProcessLocalObject::GetData(

       CNoTrackObject* (AFXAPI* pfnCreateObject)())

{

       if (m_pObject == NULL)

       {

              AfxLockGlobals(CRIT_PROCESSLOCAL);

              TRY

              {

                     if (m_pObject == NULL)

                           m_pObject = (*pfnCreateObject)();

              }

              CATCH_ALL(e)

              {

                     AfxUnlockGlobals(CRIT_PROCESSLOCAL);

                     THROW_LAST();

              }

              END_CATCH_ALL

              AfxUnlockGlobals(CRIT_PROCESSLOCAL);

       }

       return m_pObject;

}

 

3.      Thread State

和Process State类似,Thread State和某个线程绑定起来,Thread State有:

1.     _AFX_THREAD_STATE

2.     _AFXCTL_AMBIENT_CACHE

同样的,Thread State是被THREAD_LOCAL和EXTERN_THREAD_LOCAL定义,也有CThreadLocal和CThreadLocalObject来Hold住Thread State的指针。CThreadLocal和CProcessLocal的实现方式不太一样,CThreadLocal利用TLS(Thread Local Storage)来保存指针,而不是用成员变量。简单来说,Thread Local Storage是Windows支持的功能,可以在任意线程中保存多个DWORD数据,每个这样的DWORD数据所占的位置称之为Slot,分配数据需要分配一个Slot,获得和修改数据CThreadLocalObject::GetData的实现如下:

CNoTrackObject* CThreadLocalObject::GetData(

       CNoTrackObject* (AFXAPI* pfnCreateObject)())

{

    ENSURE(pfnCreateObject);

 

       if (m_nSlot == 0)

       {

              if (_afxThreadData == NULL)

              {

                     _afxThreadData = new(__afxThreadData) CThreadSlotData;

                     ENSURE(_afxThreadData != NULL);

              }

              m_nSlot = _afxThreadData->AllocSlot();

              ENSURE(m_nSlot != 0);

       }

       CNoTrackObject* pValue = static_cast<CNoTrackObject*>(_afxThreadData->GetThreadValue(m_nSlot));

       if (pValue == NULL)

       {

              // allocate zero-init object

              pValue = (*pfnCreateObject)();

 

              // set tls data to newly created object

              _afxThreadData->SetValue(m_nSlot, pValue);

              ASSERT(_afxThreadData->GetThreadValue(m_nSlot) == pValue);

       }

       return pValue;

}

CThreadLocalObject::GetData首先判断m_nSlot,如果m_nSlot == 0,说明该Thread State未曾分配,GetData函数将会使用_afxThreadData->AllocSlot函数分配一个新的TLS的Slot,保存在m_nSlot之中,然后调用GetThreadValue检查pValue是否为NULL,如果是,则创建一个新的对象然后调用SetValue把pValue设置到该Slot之中。_afxThreadData的类型为CThreadSlotData,是对TLS API的一个简单的封装。

_AFX_THREAD_STATE是一个很常用的Thread State,每个Thread,都会有自己的一份_AFX_THREAD_STATE。MFC提供了一个函数AfxGetThreadState来获得当前进程的Thread State,如果当前的线程还没有Thread State,该函数会创建一个新的Thread State。

_AFX_THREAD_STATE* AFXAPI AfxGetThreadState()

{

       _AFX_THREAD_STATE *pState =_afxThreadState.GetData();

       ENSURE(pState != NULL);

       return pState;

}

 

_AFX_THREAD_STATE中保存着下列信息:

1.     当前的m_pModuleState,每个线程都知道它当前的Module State,这个信息被用来获得当前的Module State,AfxGetModuleState正是这么做的:

AFX_MODULE_STATE* AFXAPI AfxGetModuleState()

{

       _AFX_THREAD_STATE* pState = _afxThreadState;

       ENSURE(pState);

       AFX_MODULE_STATE* pResult;

       if (pState->m_pModuleState != NULL)

       {

              // thread state's module state serves as override

              pResult = pState->m_pModuleState;

       }

       else

       {

              // otherwise, use global app state

              pResult = _afxBaseModuleState.GetData();

       }

       ENSURE(pResult != NULL);

       return pResult;

}

 

2.     之前的m_pModuleState,用来保存之前的Module State,用于Module State切换,可参考AFX_MANAGE_STATE

3.     其他信息,具体可以参考_AFX_THREAD_STATE的定义

4.      Module State

Module State保存着和Module相关的状态信息。Module是Windows的术语,代表任何一个可执行的代码文件, EXE和DLL都是Module的一种。Module State有下面几种:

1.     AFX_MODULE_STATE,保存MODULE的信息,是_AFX_BASE_MODULE_STATE和_AFX_DLL_MODULE_STATE的基类

2.     _AFX_BASE_MODULE_STATE,保存MFC Module的状态信息,没有定义其他的成员

3.     _AFX_DLL_MODULE_STATE,保存DLL的状态信息,没有定义其他的成员

4.     AFX_MODULE_THREAD_STATE,保存主线程的有关状态信息,虽然AFX_MODULE_THREAD_STATE是保存的线程的状态信息,但是它只保存Module的主线程的状态信息,所以可以看作是Module State的一种。

这些Module State保存了MFC中的大量重要信息:

1.     CWinApp指针

2.     实例句柄

3.     资源Module的句柄

4.     句柄表

5.     OLE相关信息

6.     窗口过程

7.     Activation Context

8.     ……

 

4.1      AFX_MODULE_STATE

AFX_MODULE_STATE的定义如下:

// AFX_MODULE_STATE (global data for a module)

class AFX_MODULE_STATE : public CNoTrackObject

{

public:

#ifdef _AFXDLL

       AFX_MODULE_STATE(BOOL bDLL, WNDPROC pfnAfxWndProc, DWORD dwVersion,

              BOOL bSystem = FALSE);

#else

       explicit AFX_MODULE_STATE(BOOL bDLL);

#endif

       ~AFX_MODULE_STATE();

 

       CWinApp* m_pCurrentWinApp;

       HINSTANCE m_hCurrentInstanceHandle;

       HINSTANCE m_hCurrentResourceHandle;

       LPCTSTR m_lpszCurrentAppName;

       // …… 其他成员,从略

};

可以看到:

1.     AFX_MODULE_STATE从CNoTrackObject继承。CNoTrackObject定义了自己的new/delete保证自己不会被各种调试版本的new/delete来Track,以免自己被错误的当作Leak。

2.     AFX_MODULE_STATE在DLL和非DLL(也就是EXE)的情况下具有不同的构造函数(和成员)

3.     AFX_MODULE_STATE在成员中保存了一些和Module相关的重要信息

实际上,AFX_MODULE_STATE并没有被直接使用,而是作为_AFX_BASE_MODULE_STATE和_AFX_DLL_MODULE_STATE的基类:

_AFX_BASE_MODULE_STATE被用于Module,其定义如下:

class _AFX_BASE_MODULE_STATE : public AFX_MODULE_STATE

{

public:

#ifdef _AFXDLL

       _AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcBase, _MFC_VER)

#else

       _AFX_BASE_MODULE_STATE() : AFX_MODULE_STATE(TRUE)

#endif

              { }

};

 

PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)

_AFX_DLL_MODULE_STATE和_AFX_BASE_MODULE_STATE类似,只是仅用于DLL:

class _AFX_DLL_MODULE_STATE : public AFX_MODULE_STATE

{

public:

       _AFX_DLL_MODULE_STATE() : AFX_MODULE_STATE(TRUE, AfxWndProcDllStatic, _MFC_VER)

              { }

};

 

static _AFX_DLL_MODULE_STATE afxModuleState;

这两个class都没有定义额外的成员,比较简单,只是传入到基类AFX_MODULE_STATE的参数不同。此外,他们定义的方式不太一样,前者使用的是PROCESS_LOCAL宏,定义了一个变量_afxBaseModuleState。后者只是简单的定义了一个static变量afxModuleState。

 

下面这些函数可以用来获得Module的State:

1.     AfxGetModuleState

AfxGetModuleState首先获得_afxThreadState的m_pModuleState,如果当前的Thread State的m_pModuleState返回NULL,说明当前的Thread State没有正确的初始化(通常的原因是创建线程的时候调用的是CreateThread函数而非AfxBeginThread),则使用_afxBaseModuleState。

AFX_MODULE_STATE* AFXAPI AfxGetModuleState()

{

       _AFX_THREAD_STATE* pState = _afxThreadState;

       ENSURE(pState);

       AFX_MODULE_STATE* pResult;

       if (pState->m_pModuleState != NULL)

       {

              // thread state's module state serves as override

              pResult = pState->m_pModuleState;

       }

       else

       {

              // otherwise, use global app state

              pResult = _afxBaseModuleState.GetData();

       }

       ENSURE(pResult != NULL);

       return pResult;

}

 

_afxBaseModuleState是用PROCESS_LOCAL定义的:

PROCESS_LOCAL(_AFX_BASE_MODULE_STATE, _afxBaseModuleState)

它代表整个MFC Module的State。当你的程序是动态链接到MFC DLL的时候,该State只有一份。如果你的程序是静态链接到MFC的话,有几个模块(EXE/DLL)静态链接到MFC,MFC的代码就有几份,那么_afxBaseModuleState也就有几份。

 

2.     AfxGetStaticModuleState

AfxGetStaticModuleState在不同的Project下面有着不同的行为:在DLL项目中,AfxGetSaticModuleState返回afxModuleState,也就是定义好的_AFX_DLL_MODULE_STATE,而在非DLL项目中,AfxGetStaticModuleState直接调用AfxGetModuleState。可以看到,在DLL的情况下,必须使用AfxGetStaticModuleState才可以获得DLL本身的Module State。

#ifdef _AFXDLL

 

static _AFX_DLL_MODULE_STATE afxModuleState;

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = &afxModuleState;

       return pModuleState;

}

 

#else

 

AFX_MODULE_STATE* AFXAPI AfxGetStaticModuleState()

{

       AFX_MODULE_STATE* pModuleState = AfxGetModuleState();

       return pModuleState;

}

#endif

 

3.     AfxGetAppModuleState

AfxGetAppModuleState是最简单的,直接返回_afxBaseModuleState:

AFX_MODULE_STATE* AFXAPI AfxGetAppModuleState()

{

       return _afxBaseModuleState.GetData();

}

从上面的讨论可以看出,当前处于那个MFC Module的状态之中,返回的就是那个MFC Module所相关联的CWinApp对象。如果你有多个Module都是动态链接到MFC DLL的话,那么AfxGetAppModuleState返回的总是同一个CWinApp。

 

5.      AFX_MANAGE_STATE

AFX_MANAGE_STATE的作用切换到指定的Module State,当出了作用域的时候将Module State恢复到原来的值。是在不同的Module State之中切换,原因有2:

1.     在不同的MFC DLL和MFC EXE的Module State之间切换,保持正确的AFX_MODULE_STATE,最常见的问题是在DLL输出的函数之中无法获得DLL本身相关的资源,这就是没有正确维护Module State的原因造成的,因为当前Resource DLL的句柄就保存在Module State之中。

2.     切换Activation Context,不同的Module必然有着不同的Activation Context,需要切换。这是属于Side By Side的内容,以后我会专门写一篇文章来讲述Side By Side和manifest的相关信息。

一般的用法如下:

void SomeMFCDllFunction()

{

AFX_MANAGE_STATE(AfxGetStaticModuleState())

…

注意这里使用的是AfxGetStaticModuleState,而非AfxGetModuleState。原因是在DLL项目中,AfxGetStaticModuleState返回的是DLL本身的Module State,而AfxGetModuleState则是返回当前线程相关的Module State,由于一般DLL输出的函数是被其他Module调用,那么大部分情况下当前线程的Module State都是错误的,所以必须得使用DLL本身的Module State。

 

AFX_MANAGE_STATE只是一个宏,如下:

struct AFX_MAINTAIN_STATE2

{

       explicit AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pModuleState) throw();

       ~AFX_MAINTAIN_STATE2();

 

protected:

#ifdef _AFXDLL

       AFX_MODULE_STATE* m_pPrevModuleState;

       _AFX_THREAD_STATE* m_pThreadState;

#endif

 

       ULONG_PTR m_ulActCtxCookie;

       BOOL m_bValidActCtxCookie;

};

 

#define AFX_MANAGE_STATE_NO_INIT_MANAGED(p) AFX_MAINTAIN_STATE2 _ctlState(p);

#define AFX_MANAGE_STATE(p) _AfxInitManaged(); AFX_MANAGE_STATE_NO_INIT_MANAGED(p)

可以看到AFX_MANAGE_STATE声明了一个栈上的局部变量_ctrlState,类型为AFX_MAINTAIN_STATE2。这是一个很常用的Pattern,AFX_MAINTAIN_STATE2在构造函数的时候会将当前的Module State切换为参数中指定的Module State:

AFX_MAINTAIN_STATE2::AFX_MAINTAIN_STATE2(AFX_MODULE_STATE* pNewState) throw()

{

#ifdef _AFXDLL

       m_pThreadState = _afxThreadState.GetData();

       ASSERT(m_pThreadState);

       if(m_pThreadState)

       {

              m_pPrevModuleState = m_pThreadState->m_pModuleState;

              m_pThreadState->m_pModuleState = pNewState;

       }

       else

       {

              // This is a very bad state; we have no good way to report the error at this moment

              // since exceptions from here are not expected

              m_pPrevModuleState=NULL;

              m_pThreadState=NULL;

       }

#endif

 

       if (AfxGetAmbientActCtx() &&

              pNewState->m_hActCtx != INVALID_HANDLE_VALUE)

       {

              m_bValidActCtxCookie = AfxActivateActCtx(pNewState->m_hActCtx, &m_ulActCtxCookie);

       }

       else

       {

              m_bValidActCtxCookie = FALSE;

       }

}

然后在析构函数的时候将其恢复回来:

// AFX_MAINTAIN_STATE2 functions

_AFXWIN_INLINE AFX_MAINTAIN_STATE2::~AFX_MAINTAIN_STATE2()

{

#ifdef _AFXDLL

       // Not a good place to report errors here, so just be safe

       if(m_pThreadState)

       {

              m_pThreadState->m_pModuleState = m_pPrevModuleState;

       }

#endif

 

       if (m_bValidActCtxCookie)

       {

              BOOL bRet;

              bRet = AfxDeactivateActCtx(0, m_ulActCtxCookie);

              ASSERT(bRet == TRUE);

       }

}

可以看到,AFX_MAINTAIN_STATE2将当前_afxThreadState在m_pThreadState中存起来,然后将所指向的Module State保存在m_pPrevModuleState中。在析构函数中,则使用保存起来的m_pPrevModuleState恢复到m_pThreadState的Module State。除了保存恢复Module state之外,AFX_MAINTAIN_STATE2也会在切换Activation Context。这个Activation Context被用来查找Side By Side Assemblies,我以后会专门写一篇文章讲述Side By Side和Manifest相关的一些信息。这次就写到这里。

Cadence Spectre仿真保姆级教程:从DC/AC到PSS/PV,手把手教你搞定模拟电路分析 作为业界标准的Cadence Spectre仿真器,以其精确的算法和丰富的分析类型,成为每个模拟IC工程师必须掌握的利器。本文将带你从零开始,系统掌握Spectre仿真的核心技能,从最基础的DC工作点分析到复杂的PSS相位噪声仿真,每个步骤都配有详细的操作指导和实用技巧。记得我第一次使用Spectre仿真一个简单的两级运放时,花了整整三天时间才得到正确的AC响应曲线。过程中踩过的坑、浪费的时间,现在想来都是宝贵的学习资源。与传统的AC分析不同,STB分析可以在不破坏环路的情况下评估稳定性。 阅读详情

相关推荐

汇编语言与接口技术(第4版)清华大学出版社 第2章 80*86微处理器 课后题答案

汇编语言与接口技术(第4版)清华大学出版社 第2章 80*86微处理器 课后题答案

m0_51658788的博客 3606

AFX_MANAGE_STATE(AfxGetStaticModuleState())

以前写MFC的DLL的时候,总会在自动生成的代码框架里看到提示,需要在每一个输出的函数开始添加上AFX_MANAGE_STATE (AfxGetStaticModuleState())。一直不明白这样做的含义,也一直没有这样做,而且代码也工作得好好的,所以感觉这好像一句废话。 最近的项目中,需要在DLL里使用MFC生成界面,这才发现一旦资源放在不同的动态库里,而且还和多线程搅和在一起的时候,事情就...

1616

STM8库函数开发手册(3) //UART1、内部EEPROM、FLASH操作库、IIC(硬、软)

STM8S 微控制器家族的通用同步异步收发器(UART1,UART2 或者UART3)提供了一种灵活的方法与使用工业标准NRZ 异步串行数据格式的外部设备之间进行全双工数据交换。STM8 的UART 提供范围的波特率选择,并且支持多处理器通讯。UART 也支持LIN(局部互联网)协议版本1.3,2.0,和2.1 以及在主模式下的J2602。 UART1 和UAR...

finedayforu的博客 2520

正确使用AFX_MANAGE_STATE宏管理MFC模块状态, AFX_MANAGE_STATE宏作用,真的很重要!!!

在 DLL 中使用 MFC 时,每个线程都需要正确的 MFC 模块状态,以确保使用 MFC 功能的正确性。在使用 MFC(Microsoft Foundation Classes)开发 DLL(动态链接库)时,正确管理 MFC 模块状态是确保功能正常运行的关键。在使用 MFC 开发 DLL 时,正确设置 MFC 模块状态是确保功能正常运行的基本步骤。宏是 MFC 提供的用于设置线程的 MFC 模块状态的工具。宏的重要性,以及在 DLL 中正确设置 MFC 模块状态的步骤。在 DLL 中的导出函数中,使用。

qq_44859843的博客 1553

从XSA到Linux应用:Petalinux与Vitis的嵌入式开发全流程解析

本文详细解析了从XSA文件到Linux应用的嵌入式开发全流程,重点介绍了Petalinux与Vitis工具链的使用技巧和实战经验。通过XSA硬件描述、Petalinux工程搭建、系统镜像优化及Vitis开发配置等关键步骤,帮助开发者高效完成ZYNQ平台开发,解决常见问题并提升开发效率。

weixin_29195217的博客 192

高通平台Android稳定性调试笔记:手把手教你用T32、Crash Utility分析Kernel Panic与RAM Dump

本文详细介绍了高通平台Android内核崩溃的分析方法,包括使用T32 Simulator和Crash Utility工具链解析Kernel Panic与RAM Dump。从环境配置、dump文件预处理到高级调试技巧,手把手教你如何定位和解决Android系统崩溃问题,特别适用于MSM/SA8155平台的开发者。

weixin_42543046的博客 526

MFC 模块切换 AFX_MANAGE_STATE(AfxGetStaticModuleState())

模块切换

weixin_45053845的博客 1016

YOLOv13添加OREPA模块 准确率提升10.56个点,map提升11.87个点。小目标轻量化

本文提出了一种新的OREPA(Optimal Recursive Edge-Preserving Attention)模块,通过结合递归和边缘保留注意力机制,显著提升了目标检测模型的性能。实验结果表明,添加OREPA模块后,准确率提升了10.56个百分点,mAP提升了11.87个百分点。OREPA模块包含三个核心组件:OREPA1处理特征图并保留边缘信息,Bottleneck_OREPA作为瓶颈模块降低计算量,OREPA类通过堆叠多个Bottleneck_OREPA增强网络表达能力。文章详细介绍了如何将OR

FJN110的博客 2761

转:MFC的模块状态(AfxGetApp()和AFX_MANAGE_STATE())

原文地址: http://hi.baidu.com/%CD%F8%C2%E7%C3%D4%CD%BE%C9%D9%C4%EA/blog/item/db8aa0c2bf5e0853b219a857.html1.      Introduction当我们在用MFC编程的时候,我们经常用到AfxGetApp()来获得当前的CWinApp的Instance。看看MFC的源代码中AfxGetApp()的

czg1984的专栏 959

基于STM32L4XX 、HAL库的DRV8825PWPR步进电机驱动器驱动程序应用设计

一、简介:DRV8825是德州仪器(TI)推出的一款高性能步进电机驱动器模块。它集成了微步进分度器、MOSFET H桥以及过流、欠压锁定和过热保护电路。主要特性:驱动能力: 最高电压45V,每相最大电流2.5A(需配合足够散热)。微步进: 支持全步、1/2、1/4、1/8、1/16、1/32微步模式,通过M0, M1, M2三个引脚控制。控制接口: 非常简单,只需要两个核心信号:(脉冲输入):每个上升沿脉冲驱动电机移动一个微步。(方向控制):高电平/低电平决定电机旋转方向。使能端: (睡眠模式,低电平有效)

PP_Cottage的博客 330

Android性能分析——hprof文件分析(一)

hprof  文件是 Java 堆转储文件(Heap Dump File)的标准格式,用于保存 Java 虚拟机(JVM)在某个时间点的内存快照。这种文件对于分析内存泄漏、内存使用情况和对象分配模式非常有用。

小旭的专栏 1877

MFC的模块状态:AfxGetApp()和AFX_MANAGE_STATE()

1. Introduction 当我们在用MFC编程的时候,我们经常用到AfxGetApp()来获得当前的CWinApp的Instance。看看MFC的源代码中AfxGetApp()的实现,你会发现AfxGetApp()的实现并不像一般情况下面那样直接: _AFXWIN_INLINE CWinApp* AFXAPI AfxGetApp()        { return af

chaozi2008的专栏 1026

2、实时DSP编程技术及其应用

本文详细介绍了实时数字信号处理(DSP)技术及其应用,涵盖三种流行的浮点DSP处理器系列的特点、开发工具和优化方法。通过具体的应用实例,如语音压缩、音乐信号处理和雷达信号处理,展示了如何在实际项目中应用这些技术,帮助工程师提高系统的性能和可靠性。

cicd6pipeline的博客 838
上一篇: IHTMLDocument2->get_frames()得到的是什么
下一篇: 开源盛世 Linux 资源导航 —★—
skyremember
博客等级 码龄20年 204粉丝 484原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值