【使用C++开发MCU】02-IIC实例之读取温度
为什么使用C++进行MCU开发
我从18年开始在STM32等上使用C++编程,在医疗器械行业进行IVD仪器开发,在此之前的项目开发中我是使用C语言。初次在MCU上使用C++,我有很多疑惑:C语言不挺好的吗?MCU上居然可以使用C++? 为什么选择C++?
工作七八年了,以前都没写过博客,现在开始记录一点东西吧!
尽管18年时使用C语言进行MCU开发已经相当熟练,但C++我是刚入茅庐,才会有那些疑问,并还专门请教了部门经理。这几年,随着工作经验的积累,愈发的认通C++在产品开发中的优点,那些疑惑也随之解开。
使用C++进行MCU开发,不代表只用C++,C语言也是可以混用的,特别是原厂提供的一些SDK,可以用C++封装这层SDK,后续、上层驱动业务进行C++开发。
场景描述
这里使用NXP的S32K1系列MCU,使用TI的TMP101温度传感器做示例。开发环境使用NXP的S32DS,使用其C库SDK,编程语言为C++。为了使用C++演示,建立工程时选择C++语言,不选择SDK,SDK部分由我们自行导入工程。
软件架构
这里进行演示,架构较为简单,在SDK基础上封装IIC驱动CI2C(C++),基于IIC驱动实现TMP101驱动CTmp(C++),板级相关时钟、引脚封装在CBoard中(C++),最后App中的main.cpp实现读取温度。
工程结构
基于上述软件架构[在SDK基础上封装IIC驱动CI2C(C++),基于IIC驱动实现TMP101驱动CTmp(C++),板级相关时钟、引脚封装在CBoard中(C++),最后App中的main.cpp实现读取温度。]实现工程结构:
CI2C类
参见NXP S32K1 IIC Driver接口与实现实现该C++类。
头文件:CI2C.h中主要实现初始化、读从机数据、写从机数据三大接口,为了省事,将板机相关的从机枚举、从机地址和波特率等也塞在了这里。
#ifndef CI2C_H_
#define CI2C_H_#include "stdint.h"
#include "lpi2c.h"class CI2C{public:void init(void);void deinit(void);bool read(uint8_t slave, uint8_t addr, uint8_t *data, uint16_t len);bool write(uint8_t slave, uint8_t addr, const uint8_t *data, uint16_t len);static CI2C *getInstance(void);enum SLAVE{SLAVE_TMP101 = 0x00,SLAVE_COUNT};private:static CI2C *pI2CInstance;void config(uint8_t slave);const uint32_t I2C_NO = INST_LPI2C;const uint32_t I2C_MAX_LEN = 128U;const uint32_t I2C_TOUT = 100U;uint8_t addr[SLAVE_COUNT] ={0x4A,//SLAVE_TMP101};uint32_t buad[SLAVE_COUNT] ={400000,//SLAVE_TMP101};};#endif /* CI2C_H_ */
源文件:CI2C.cpp则是上述接口的具体实现。
void CI2C::init(void)
{LPI2C_DRV_MasterInit(CI2C::I2C_NO, &lpi2c_MasterConfig0, &lpi2c_MasterState);
}void CI2C::deinit(void)
{LPI2C_DRV_MasterDeinit(CI2C::I2C_NO);
}bool CI2C::read(uint8_t slave, uint8_t addr, uint8_t *data, uint16_t len)
{bool rtv = true;config(slave);if( STATUS_SUCCESS == LPI2C_DRV_MasterSendDataBlocking(CI2C::I2C_NO, &addr, 1, false, CI2C::I2C_TOUT)){if(data && len && (STATUS_SUCCESS == LPI2C_DRV_MasterReceiveDataBlocking(CI2C::I2C_NO, data, len, true, CI2C::I2C_TOUT))){rtv = true;}else{rtv = false;}}else{rtv = false;}return rtv;
}bool CI2C::write(uint8_t slave, uint8_t addr, const uint8_t *data, uint16_t len)
{bool rtv = true;config(slave);uint8_t *ptrans = new uint8_t[CI2C::I2C_MAX_LEN];uint8_t translen = 1;if(ptrans){*(ptrans+0) = addr;if(len != 0){if(data &&(len<CI2C::I2C_MAX_LEN-1)){memcpy((uint8_t*)(ptrans+1),data,len);translen += len;}else{rtv = false;}}if(rtv && (STATUS_SUCCESS == LPI2C_DRV_MasterSendDataBlocking(CI2C::I2C_NO, ptrans, translen, true, CI2C::I2C_TOUT))){rtv = true;}else{rtv = false;}}delete ptrans;return rtv;
}void CI2C::config(uint8_t slave)
{lpi2c_baud_rate_params_t baud;baud.baudRate = CI2C::buad[slave];LPI2C_DRV_MasterSetBaudRate(CI2C::I2C_NO,LPI2C_FAST_MODE, baud);LPI2C_DRV_MasterSetSlaveAddr(CI2C::I2C_NO, CI2C::addr[slave], false);
}
由于该款S32K1只有一个IIC模组,为了显得使用C++正规一点,整了一个单例,在其它文件中,只需要通过II2C对象去访问相关函数即可。
#define II2C CI2C::getInstance()CI2C* CI2C::pI2CInstance = NULL;CI2C *CI2C::getInstance(void)
{if(CI2C::pI2CInstance == NULL){CI2C::pI2CInstance = new CI2C;}return CI2C::pI2CInstance;}
CTmp类
这是温度传感器TMP101类,只有几个寄存器,使用简单,在此不赘叙,只需要对照其DataSheet进行IIC访问即可。
头文件:
#ifndef CTMP101_H_
#define CTMP101_H_#include "CI2C.h"class CTmp{public:float gettmp(void);private:const float res = 0.0625;enum{TMP_REG_TMP = 0x00,TMP_REG_CFG = 0x01,TMP_REG_TLOW = 0x02,TMP_REG_THIGH = 0x03};};#endif /* CTMP101_H_ */
源文件:
#include "CTmp101.h"
#include "II2C.h"
float CTmp::gettmp(void)
{bool rtv = true;float ftmp = 0.0;uint16_t uiTmp = 0;uint8_t ucRead[2] = {0};rtv = II2C->read(II2C->SLAVE_TMP101, CTmp::TMP_REG_TMP, ucRead, 2);uiTmp = (ucRead[0]<<0x08)|ucRead[1];uiTmp >>= 4;ftmp = res*uiTmp;return ftmp;
}
App应用
应用层实现在main.cpp中,先完成板卡时钟、引脚初始化,接着进行IIC外设初始化,最后读取温度值。
#include "S32K146.h"
#include "CBoard.h"
#include "II2C.h"
#include "CTmp101.h"int main()
{CBoard mybrd;mybrd.clk_init();mybrd.pin_init();mybrd.pwr_Init();II2C->init();float fVal = 0.0;CTmp mTmp;while(1){fVal = mTmp.gettmp();}return 0;
}
结语
时间流逝的好快,一下子就工作了七年,怀念在深圳工作的那5年!
刚开始写博客,语言组织可能不是太好,还望海涵,也欢迎指出博文中不足与改进点。
【使用C++开发MCU】02-IIC实例之读取温度相关推荐
- 【使用C++开发MCU】05-CAN实例之NXP S32K1 FlexCAN模块
文章目录 概述 FlexCAN模块框图 协议引擎Protocol Engine (PE) 控制器主机接口Controller Host Interface (CHI) 总线接口单元Bus Interf ...
- 【使用C++开发MCU】04-CAN实例之CAN FD协议快速入门
概述 随着现代技术的进步,自90年代开始使用的CAN协议[Classical CAN protocol (ISO 11898-1:2015) ]在各个邻域具有广泛应用但也面临巨大的压力. 因此,本专栏 ...
- python基础代码事例-零基础学习Python开发练习100题实例(2)
零基础学习Python开发练习100题实例(2) 2018-02-26 13:11:39 1934浏览 11.题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后每个 ...
- ST官方的IIC实例解析(第一部分)
ST官方的IIC实例解析 LM75A的管脚描述 输入/输出(引脚属性) 引脚标识 描述 输入 VCC 供电电压 输入 GND 参考地 输入 A2~A0 低3位地址引脚 输入 SDA IIC的数据总线 ...
- delphi2010 开发及调试WebService 实例
delphi2010 开发及调试WebService 实例 基于Delphi的WebService编写 Delphi编写soap服务器与客户端程序 Delphi XE5通过WebService开发We ...
- 3万6千字爆肝,前端进阶不得不了解的函数式编程开发,含大量实例,手写案例,所有案例均可运行
3w6爆肝,前端进阶不得不了解的函数式编程开发,含大量实例,手写案例,所有案例均可运行 认识函数式编程 函数相关复习 函数是一等公民 高级函数 函数作为参数 案例 1,模拟 forEach 案例 2, ...
- python零基础实例-零基础学习Python开发练习100题实例(1)
零基础学习Python开发练习100题实例(1) 2018-02-25 09:37:59 2864浏览 1.题目:有四个数字:1.2.3.4,能组成多少个互不相同且无重复数字的三位数?各是多少? 程序 ...
- 企业级的开发组件02 - DevExpress DXperience Universal 2011.2.5 Final
郑重声明,如果引用,请注明出处:(原创 博客园:天之子) 企业级的开发组件02 - DevExpress DXperience Universal 2011.2.5 Final(2011-12-01 ...
- Android开发中StackOverflowError错误实例分析
http://blog.csdn.net/mozhizun/article/details/7051300 http://blog.csdn.net/gaomatrix/article/details ...
最新文章
- 开源代码“All in One”:6 份最新「Paper + Code」等你复现 | PaperDaily #12
- access如何保存小数点后_跟宇哥学习Access数据库是怎样一种体验?(1)
- Linux 安装卸载软件及管理软件仓库
- 飞鸽传书(IPMSG)协议(翻译稿)
- Java-三元运算符
- BugkuCTF-Crypto题给你私钥吧
- 理论基础 —— 排序 —— 归并排序
- Magento教程 23:如何获取销售报表?
- mysql中起飞到达城市查询_让mysql慢慢起飞 - 初识慢日志
- MySQL C 语言应用程序接口开发教程
- 【源码小记】jQueryの事件绑定
- (转)财富取决于极少的大高潮,幸福取决于较多的小高潮
- java中的常见算法
- JavaSE基础学习
- SPSS教程:手把手教你设置哑变量以及解读结果
- 对抗 | 利用de4dot解密被混淆的.NET代码
- 几种常见的距离计算公式
- [bzoj4874]筐子放球
- XCTF 3rd-HITB CTF-2017 arrdeepee 复现
- Source must not be null\n\tat org.springframework.util.Assert.notNull(Assert.java:101)