当前位置: 首页 > wzjs >正文

企业网站打包下载网站维护和推广方案

企业网站打包下载,网站维护和推广方案,中国网站建设20强,昆明网站推广8888168HAL 库都是拿C 写的,想注册回调函数的话,也只能是C 的函数,不能用成员函数作为回调。现在有个需求,要给一个I2C 设备写个驱动,希望把驱动整体封装成个类,这样比较灵活。要是还得把I2C 的回调函数放在类外面…

HAL 库都是拿C 写的,想注册回调函数的话,也只能是C 的函数,不能用成员函数作为回调。现在有个需求,要给一个I2C 设备写个驱动,希望把驱动整体封装成个类,这样比较灵活。要是还得把I2C 的回调函数放在类外面,那就太不“整洁”了。此外,放在外面的回调函数没办法直接引用到设备驱动对象,必须有个全局的指针变量,让它指向驱动对象,然后回调函数里再使用这个全局的指针去找对象。STM32DUINO 框架里就是这么设计的,只是它们稍微取了点巧,大致原理如下:

// 驱动类,或者驱动结构体
struct Driver{I2C_HandleTypeDef handle;// ... 其他一堆成员变量// ... 其他一堆成员函数
};// 驱动对象
Driver driver_instance;// 调用HAL 库函数
HAL_I2C_Master_Transmit_DMA(&driver_instance.handle, addr, buf_ptr, count);// HAL 库的回调函数。想在回调里使用C++ 代码,必须把回调放在CPP 文件里,所以要加上extern "C"
extern "C" {void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2cHandle) {// 根据handle 结构体在Driver 类中的偏移量,拿到指向driver_instance 对象的指针auto offset = offsetof(Driver, handle);Driver *driver_ptr = reinterpret_cast<Driver*>(I2cHandle - offset);// 拿到了驱动对象,之后就随便弄了// driver_ptr->.......
}}

把HAL 库的Handle 结构体嵌进驱动对象里,再用这个handle 成员变量去调用各种HAL 函数,那么回调函数传进来的*I2cHandle 当然就是指向这个成员变量的指针。有了成员变量的地址,就可以根据成员变量在驱动对象中的偏移量,拿到驱动对象的地址。也是挺巧妙的,优点是不用单独定义个隐藏的全局变量,用户使用的时候会自己定义Driver 对象。

不过这种做法不适合我。我习惯把Cube 生成的代码简单改改就直接用,而且还是拿脚本自动改。Cube 会在它生成的main.c 里定义好各种handle 结构,我就在它的main 函数里调用我自己的入口函数app()。这样做的好处是可以分离Cube 自动生成的代码,我可以把我的代码放在app.cpp 文件里,以后如果改了配置,只要把Cube 新生成的代码复制过来改一下就好了,我可不想在它生成的代码里照着它规定好的格式填空。

于是,既然handle 都已经在main.c 里定义好了,我肯定不想一个一个自己定义Driver 对象,再去改生成好的配置代码。

所以我用的是另一种比较脏的方法,就是直接修改HAL 库的头文件,在I2C_HandleTypeDef 结构体定义里加一个成员void *PtrToCallbackObject,用来指向我的驱动对象。

typedef struct __I2C_HandleTypeDef
#else
typedef struct
#endif  /* USE_HAL_I2C_REGISTER_CALLBACKS */
{I2C_TypeDef                *Instance;      /*!< I2C registers base address               */// ...#if (USE_HAL_I2C_REGISTER_CALLBACKS == 1)void *PtrToCallbackObject;   // 指向回调函数关联的对象// ...void (* AddrCallback)(struct __I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode);  /*!< I2C Slave Address Match callback */void (* MspInitCallback)(struct __I2C_HandleTypeDef *hi2c);                /*!< I2C Msp Init callback                     */void (* MspDeInitCallback)(struct __I2C_HandleTypeDef *hi2c);              /*!< I2C Msp DeInit callback                   */#endif  /* USE_HAL_I2C_REGISTER_CALLBACKS */
} I2C_HandleTypeDef;// 回调
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2cHandle) {// 直接拿到驱动对象的指针Driver *driver_ptr = reinterpret_cast<Driver*>(I2cHandle.PtrToCallbackObject);// driver_ptr->.......
}

这样只是改了头文件的一行代码,几乎不会引起任何兼容性问题。虽然如果HAL 库要更新,那就得重新改,但是相信大伙很多人用的库都是复制粘贴祖传下来的,根本不知道版本是什么。而且就算更新以后忘记改了,代码直接不能编译,会提示你缺个PtrToCallbackObject 成员,所以不会出错。最后,这个Handle 结构体里面已经定义了这么多不知道有没有用的变量,我再加一个指针,不会造成什么负担。此外,就算不用C++,在C 里面往往也会用结构体模拟对象,增加这个成员也是有用的。

有了这个方便的修改以后,回到开头,现在可以把回调函数放在驱动类里面了:


class Driver {private:I2C_HandleTypeDef _handle;  // 指向设备要使用的I2C handlepublic:Driver(I2C_HandleTypeDef h) : _handle(h) {}void init() {// 注册回调函数,先把对象的指针放进去_handle->PtrToCallbackObject = reinterpret_cast<void *>(this);// 用这些lambda 作为回调函数。捕获列表必须为空,否则不能作为普通函数指针使用,// 所以lambda 里不能直接操作this 指针,必须从handle 里获取。// WARNING: 注意,这些回调是从I2C 中断调用的// TX 完成回调auto master_tx_complete_callback = [](I2C_HandleTypeDef *h) {// 获取this 指针auto t = reinterpret_cast<Driver *>(h->PtrToCallbackObject);// 发送完成时,调用成员函数t->on_tx_complete();};// 错误回调auto error_callback = [](I2C_HandleTypeDef *h) {auto t = reinterpret_cast<Driver *>(h->PtrToCallbackObject);// 发生错误时t->on_error();};// 注册回调函数_handle.MasterTxCpltCallback = master_tx_complete_callback;_handle.ErrorCallback = error_callback;}
};

这样有什么优点?可以把驱动代码全部放在头文件里,用的时候include 一下就行了,多方便。


文章转载自:

http://GfZYCud2.ftnhr.cn
http://Zu7kzxmH.ftnhr.cn
http://wNpNwoMr.ftnhr.cn
http://270xB0GS.ftnhr.cn
http://1RV7C0Vv.ftnhr.cn
http://UEMVjew5.ftnhr.cn
http://WOxmxK0B.ftnhr.cn
http://EoPrMN2X.ftnhr.cn
http://V8h2Jk9K.ftnhr.cn
http://LXaiXMZI.ftnhr.cn
http://fVaSpTxd.ftnhr.cn
http://v8eIaBgI.ftnhr.cn
http://o883lWN1.ftnhr.cn
http://RonUpXUe.ftnhr.cn
http://NZWeaO1Y.ftnhr.cn
http://tjbx8gXR.ftnhr.cn
http://60FTAKgC.ftnhr.cn
http://3ghNmMEr.ftnhr.cn
http://hChQIFLi.ftnhr.cn
http://HdZGZ23t.ftnhr.cn
http://cwfwSGcy.ftnhr.cn
http://nCxqIpYp.ftnhr.cn
http://fwRJyqeB.ftnhr.cn
http://lkRRxMFx.ftnhr.cn
http://utsZDl26.ftnhr.cn
http://RCJN97nT.ftnhr.cn
http://krp85HYA.ftnhr.cn
http://2HMkhxEx.ftnhr.cn
http://XT6NT9jK.ftnhr.cn
http://kYF6yyxx.ftnhr.cn
http://www.dtcms.com/wzjs/628024.html

相关文章:

  • 做农产品交易网站有哪些深圳盐田网站建设
  • 大型html5浅蓝色网站设计公司dede模板东莞网站建设十大品牌
  • 网站建设 运维 管理包括网站创建公司哪家好
  • 网站制作的文章做微商网站公司
  • 网站收录排名你自己做的网站怎么发布到网上
  • word如何做网站做网站宁波有什么的网络公司
  • 17做网站 一件代发wordpress如和安装
  • 用jsp做的网站的代码成都网站建设优化推广
  • 建设银行网站登录密码网络营销主要做什么
  • 启东市住房和城乡建设局网站哪些网站可以做ppt赚钱
  • 贵 建设厅网站文件百度旧版本下载
  • 做网站有什么平台查看一个网站的源代码做评价
  • 做网站空间多大网站开发专业就业指导
  • 手机网站成功案例杭州seo顾问
  • ui设计师与网站编辑有什么关系好看的网站设计
  • 网站开发课程培训win10本地安装wordpress
  • 限时抢购网站源码广州代理记账公司
  • 网站敏感词汇网站系统排名
  • 做网站赚不了钱电子商务网站建设实验指导
  • 如何重启网站服务器开发商交房必备条件
  • 建设企业网站可信度网建天地小区
  • 大理北京网站建设建站公司不给源码
  • 池州专业网站建设专业简历制作
  • 安阳企业网站优化排名做网站背景图片浪漫爱情
  • 网站备案不通过软件开发用什么软件编程
  • 各大网站推广平台创建百度网站
  • 做化工的外贸网站都有什么地方珠海市工程造价信息网
  • 宁波建设工程主管部门网站省住房和城乡建设厅官方网站
  • 网站建设尢金手指专业WordPress 虎嗅主题免费
  • 自做网站域名重定向wordpress网站之间互联