前面我们介绍了华大半导体开源的额温枪项目,顺带也分享了入门华大HC32L136平台的SDK,这样再去看项目代码才能学习到更多实际产品的软件设计思想,链接如下:
火爆全网开源额温枪同平台之华大HC32L136 SDK开发入门
今天,就来介绍下深圳市云之手科技有限公司的测温产品,出自陈工之手,这也是他个人目前开源的第二个项目,也是个非常成功的项目,产品已经实现大批量产。第一个开源DIY项目链接如下:
这是基于合泰BH67F2752方案,该方案最大的优势是成本非常低,我们先来看看产品硬件原理图:
1、红外式测温计产品原理图等
电路原理图
产品PCB 3D图纸
产品PCB实物图
产品实物图(公模)
为什么要采用公模?因为量产的项目产品属于商业机密,包括外观等等都是和客户签订了相应的保密合同,所以我们不能公开已经出货的产品的技术资料,但是我们还是可以以公模的方式公开,在一定程度上和原来的产品外观等等都有一定的区别,不过大致框架是一样的,不影响我们学习。
2、红外式测温计产品演示效果
3、红外式测温计产品软件框架
基于合泰官方提供测温Demo程序进行开发,也有合泰的其它方案,资料在文章末尾,感兴趣的朋友可以回复关键词获取。
(1)主程序框架
void main() { //判斷是否是上電復位或者是正常情況下的非正常復位 //如果成立則執行上電初始化動作,反之則執行WDT溢出初始化 if(_to == 0 || _pdf == 0) // WDT Reset { //上電復位或者是正常情況下的非正常復位 fun_Ram_CLear(); // CLR RAM fun_Sys_Init(); fun_Reset_Init(); } else { //WDT 溢出復位 fun_Reset_Init(); } fun_Uart_Init(); fun_Test_Function(); //蜂鸣器上电响一声 BEEP_ON(); Delay_Ms(200); BEEP_OFF(); /* fun_BAT_INIT();*/ SDK_TM.HaltTime = 110; //进入休眠模式 /* fun_CorrMode_Printf();*/ while(1) { //清除看門狗 GCC_CLRWDT(); // 工作循环 /* SDK_TM.HaltTime = 120; //Test 不要进入休眠 */ if(SDK_TM.HaltTime < HALT_TIME) { if(_tb0f) // 8ms中断标志位判断 { _tb0f = 0; //8ms标志位清零 fun_SysTimeScan(); fun_WorkModeScan(); //工作模式处理 fun_BeepScan(); //蜂鸣器处理 fun_BacklightScan(); //背光处理 fun_Key_Scan(); //按键扫描处理 //清除標誌位 ,在工作流程控制可使用gbv_500ms,由此地方統一清除 if (gbv_500ms) { gbv_500ms = 0; /*fun_LCD_Display_Mode();*/ } } // ADC 輪詢掃描 fun_ADC_Polling(); } // 休眠模式 else { fun_SysSleep(); } } }
(2)功能测试部分
void fun_Test_Function() { #if(TEST_MODE == TEST_LCD) fun_LCD_Test(); #endif #if(TEST_MODE == TEST_BEEP) fun_Beep_Test(); #endif #if(TEST_MODE == TEST_PERI) fun_Peripherals_Test(); #endif #if(TEST_MODE == TEST_UART) fun_Uart_Test(); #endif #if(TEST_MODE == TEST_NTC) fun_ADC_NTC_Test(); #endif #if(TEST_MODE == TEST_OPAZERO) fun_ADC_OPA_ZeroTest(); #endif #if(TEST_MODE == TEST_OPAVTP) fun_ADC_OPA_VTPTest(); #endif }
(3)背光处理
void fun_BacklightScan() { if(gbv_KeyStatus_L_4) { gbv_KeyStatus_L_4 = 0; fun_Uart_SendByte(0x11); Backlight = ~Backlight; } }
(4)测温工作模式处理
void fun_WorkModeScan(void) { //获取系统状态模式 switch(SDK_SYS.WorkMode) { //系统开关 case WORKMODE_POWERON: break; //系统唤醒模式 case WORKMODE_WAKEUP: //按键1唤醒开机 if(gbv_KeyStatus_1) { SDK_KEY.KeyStatus.U8 &= 0x01; SDK_KEY.KeyStatus_L.U8 = 0; fun_LCD_Init(); //上电初始化显示 fun_LCD_Display_Power(); //跳转到工作模式 GOTO_SCAN_MODE(); } break; //扫描模式 case WORKMODE_SCAN: { fun_LCD_Display_Update(); //获取NTC数值,返回1就是获取成功,返回0获取失败 if(fun_get_NTC()) { SDK_CAL.RES_Buff.U16 = fun_Rntc_Calculate(SDK_CAL.ADC_Res1.S16, SDK_CAL.ADC_Res2.S16); gbv_Flag_GetNTC = 1; } if(gbv_Flag_GetNTC) { gbv_Flag_GetNTC = 0; // 進入量測工作模式 //-----------------------------------------------------------------------// if(gbv_KeyStatus_1) { gbv_KeyStatus_1 = 0; if(SDK_SYS.DisMode == Mode_Body) { GOTO_MEAS_MODE(); } else if(SDK_SYS.DisMode == Mode_Room) { GOTO_AmbTemp_MODE(); } else if(SDK_SYS.DisMode == Mode_SurTmp) { GOTO_ObjTemp_MODE(); } gbv_Flag_GetNTC = 0; } if(gbv_KeyStatus_L_1) { gbv_KeyStatus_L_1 = 0; SET_HALT_Sleep(); //进入休眠模式 GOTO_WAKEUP_MODE(); } //长按按键2进入校验模式 if(gbv_KeyStatus_L_2) { gbv_KeyStatus_L_2 = 0; //跳转到校准模式 GOTO_CORR_MODE(); fun_LCD_Display_Cor(0); //校准模式打印 fun_CorrMode_Printf(); } //短按按键3切换摄氏度和华氏度显示 if(gbv_KeyStatus_3) { gbv_KeyStatus_3 = 0; SDK_SYS.Dis_CF_Flag++; if(SDK_SYS.Dis_CF_Flag == 3) SDK_SYS.Dis_CF_Flag = 1; if(SDK_SYS.Dis_CF_Flag == 1) //C { if(SDK_SYS.DisMode == Mode_Body) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(0, SDK_CAL.BodyTemp.U16); fun_Uart_SendASCII(SDK_CAL.BodyTemp.U16); } else if(SDK_SYS.DisMode == Mode_Room) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(0, SDK_CAL.AmbTemp.U16); fun_Uart_SendASCII(SDK_CAL.AmbTemp.U16); } else if(SDK_SYS.DisMode == Mode_SurTmp) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(0, SDK_CAL.ObjTemp.U16); fun_Uart_SendASCII(SDK_CAL.ObjTemp.U16); } } else if(SDK_SYS.Dis_CF_Flag == 2) //F { if(SDK_SYS.DisMode == Mode_Body) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(1, (SDK_CAL.BodyTemp.U16 * 1.8) + 32); fun_Uart_SendASCII((SDK_CAL.BodyTemp.U16 * 1.8) + 32); } else if(SDK_SYS.DisMode == Mode_Room) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(1, (SDK_CAL.AmbTemp.U16 * 1.8) + 32); fun_Uart_SendASCII((SDK_CAL.AmbTemp.U16 * 1.8) + 32); } else if(SDK_SYS.DisMode == Mode_SurTmp) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(1, (SDK_CAL.ObjTemp.U16 * 1.8) + 32); fun_Uart_SendASCII((SDK_CAL.ObjTemp.U16 * 1.8) + 32); } } } } //短按按键2切换模式显示 if(gbv_KeyStatus_2) { gbv_KeyStatus_2 = 0; SDK_SYS.DisMode ++; if(SDK_SYS.DisMode == 4) SDK_SYS.DisMode = 1; fun_LCD_Display____(); } //检测短按按键4 if(gbv_KeyStatus_4) { gbv_KeyStatus_4 = 0; SDK_SYS.Dis_Beep_Flag = ~SDK_SYS.Dis_Beep_Flag; } break; } //获取人体温度 case WORKMODE_MEAS: { if(fun_get_VTP()) { //将NTC的温度和VTP的ADC值带入 SDK_CAL.AmbTemp.U16 = fun_Tsen_Calculate(SDK_CAL.RES_Buff.U16); //将第一个校准点带入 SDK_CAL.ObjTemp.U16 = fun_Tobj_Calculate(SDK_CAL.AmbTemp.U16, SDK_CAL.ADC_Vtp.S16); //获取物表温度 SDK_CAL.ObjTemp.U16 = fun_ObjTemp_DataHandle(SDK_CAL.ObjTemp.U16); //获取人体温度 SDK_CAL.BodyTemp.U16 = fun_Temp_SurfaceToBody(SDK_CAL.ObjTemp.U16); //设置蜂鸣器模式 fun_BeepSet(BEEP_1); if(SDK_SYS.Dis_CF_Flag == 1) //C { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(0, SDK_CAL.BodyTemp.U16); fun_Uart_SendASCII(SDK_CAL.BodyTemp.U16); } else if(SDK_SYS.Dis_CF_Flag == 2) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(1, (SDK_CAL.BodyTemp.U16 * 1.8) + 32); fun_Uart_SendASCII((SDK_CAL.BodyTemp.U16 * 1.8) + 32); } //返回等待按键按下模式 GOTO_SCAN_MODE(); } else { //显示等待获取 fun_LCD_Display____(); } } break; //获取环境温度 case WORKMODE_AmbTemp: { //将NTC的温度和VTP的ADC值带入 SDK_CAL.AmbTemp.U16 = fun_Tsen_Calculate(SDK_CAL.RES_Buff.U16); //设置蜂鸣器模式 fun_BeepSet(BEEP_1); if(SDK_SYS.Dis_CF_Flag == 1) //C { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(0, SDK_CAL.AmbTemp.U16); fun_Uart_SendASCII(SDK_CAL.AmbTemp.U16); } else if(SDK_SYS.Dis_CF_Flag == 2) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(1, (SDK_CAL.AmbTemp.U16 * 1.8) + 32); fun_Uart_SendASCII((SDK_CAL.AmbTemp.U16 * 1.8) + 32); } //返回等待按键按下模式 GOTO_SCAN_MODE(); } //获取表面温度 case WORKMODE_ObjTemp: { if(fun_get_VTP()) { //将NTC的温度和VTP的ADC值带入 SDK_CAL.AmbTemp.U16 = fun_Tsen_Calculate(SDK_CAL.RES_Buff.U16); //将第一个校准点带入 SDK_CAL.ObjTemp.U16 = fun_Tobj_Calculate(SDK_CAL.AmbTemp.U16, SDK_CAL.ADC_Vtp.S16); //设置蜂鸣器模式 fun_BeepSet(BEEP_1); if(SDK_SYS.Dis_CF_Flag == 1) //C { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(0, SDK_CAL.ObjTemp.U16); fun_Uart_SendASCII(SDK_CAL.ObjTemp.U16); } else if(SDK_SYS.Dis_CF_Flag == 2) { //设置LCD显示温度,带小数点 LCD_DISPLAY_NUM(1, (SDK_CAL.ObjTemp.U16 * 1.8) + 32); fun_Uart_SendASCII((SDK_CAL.ObjTemp.U16 * 1.8) + 32); } //返回等待按键按下模式 GOTO_SCAN_MODE(); } else { //显示等待获取 fun_LCD_Display____(); } } //校准模式 case WORKMODE_CORR: { fun_CORR_MODE(); break; } default: GOTO_SCAN_MODE(); break; } }
开源项目资料下载
公众号后台回复:合泰测温 即可获取下载链接,如果有需要该方案或者需要根据现在的功能进行产品定制,可以直接联系云之手陈工。
往期精彩
火爆全网开源额温枪同平台之华大HC32L136 SDK开发入门
TKM32F499高性能MCU评估板试用之万事开头难,先点个灯来压压惊!