云之手红外式测温计产品设计分享(基于合泰BH67F2752方案)

简介: 云之手红外式测温计产品设计分享(基于合泰BH67F2752方案)

640.png

前面我们介绍了华大半导体开源的额温枪项目,顺带也分享了入门华大HC32L136平台的SDK,这样再去看项目代码才能学习到更多实际产品的软件设计思想,链接如下:


火爆全网开源额温枪同平台之华大HC32L136 SDK开发入门


分享一个近期开源火爆全网的额温枪方案(硬件+源码)


今天,就来介绍下深圳市云之手科技有限公司的测温产品,出自陈工之手,这也是他个人目前开源的第二个项目,也是个非常成功的项目,产品已经实现大批量产。第一个开源DIY项目链接如下:


深圳云之手科技开源炫酷RGB灯板DIY项目


这是基于合泰BH67F2752方案,该方案最大的优势是成本非常低,我们先来看看产品硬件原理图:

1、红外式测温计产品原理图等


640.png

电路原理图

640.png

产品PCB 3D图纸

640.png

产品PCB实物图

640.png

产品实物图(公模)


为什么要采用公模?因为量产的项目产品属于商业机密,包括外观等等都是和客户签订了相应的保密合同,所以我们不能公开已经出货的产品的技术资料,但是我们还是可以以公模的方式公开,在一定程度上和原来的产品外观等等都有一定的区别,不过大致框架是一样的,不影响我们学习。

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开发入门


深圳云之手科技开源炫酷RGB灯板DIY项目


TKM32F499高性能MCU评估板试用之万事开头难,先点个灯来压压惊!


网红物联网开发板小熊派使用评测

目录
相关文章
|
9月前
|
存储 消息中间件 缓存
面试的系统设计题,给我整懵了。。。
先赞后看,Java进阶一大半小明(化名)坐在密不透风的会议室里,手握着笔,放在桌面上的是满满的两页面试题。其中一道系统设计题是这样。。。微博或者短信都有单条发送字数的限制,如果需要分享一个长网址,很容易越出限制,短链服务可以将长网址变成短网址,方便传播。请设计一个短链服务,要求短网址尽可能短,且保证系统安全和并发能力。各位hao,我是南哥,相信对你通关面试、拿下Offer有所帮助。
162 14
面试的系统设计题,给我整懵了。。。
|
存储 网络安全 数据安全/隐私保护
docker 安装gitlab,配置邮件,备份全流程
docker 安装gitlab,配置邮件,备份全流程
433 0
|
10月前
|
缓存 负载均衡 网络协议
DNSSEC
【10月更文挑战第17天】
634 1
|
资源调度 前端开发 JavaScript
如何在Node.js环境中安装并使用Bower和LESS
【7月更文挑战第2天】在Node.js环境中,掌握Bower和LESS的使用对前端开发至关重要。安装Bower(全局`npm install -g bower`)用于管理前端资源,通过`bower init`和`bower install`管理依赖。LESS作为CSS预处理器,通过`npm install -g less`安装编译器,用`lessc`命令编译LESS到CSS。虽然Bower已进入维护模式,但理解其用法仍有价值。同时,学习使用Sass或Stylus等预处理器以适应现代前端趋势。
195 0
|
图形学
【unity实战】FPS实现拾取和丢弃枪
【unity实战】FPS实现拾取和丢弃枪
187 0
|
11月前
|
机器学习/深度学习 人工智能 JSON
微信小程序原生AI运动(动作)检测识别解决方案
近年来,疫情限制了人们的出行,却推动了“AI运动”概念的兴起。AI运动已在运动锻炼、体育教学、线上主题活动等多个场景中广泛应用,受到互联网用户的欢迎。通过AI技术,用户可以在家中进行有效锻炼,学校也能远程监督学生的体育活动,同时,云上健身活动形式多样,适合单位组织。该方案成本低、易于集成和扩展,已成功应用于微信小程序。
|
小程序 JavaScript
微信小程序实现一个简单的表格
微信小程序实现一个简单的表格
340 0
|
网络协议 安全 Python
我们将使用Python的内置库`http.server`来创建一个简单的Web服务器。虽然这个示例相对简单,但我们可以围绕它展开许多讨论,包括HTTP协议、网络编程、异常处理、多线程等。
我们将使用Python的内置库`http.server`来创建一个简单的Web服务器。虽然这个示例相对简单,但我们可以围绕它展开许多讨论,包括HTTP协议、网络编程、异常处理、多线程等。
|
关系型数据库 MySQL 中间件
【MySQL实战笔记】07 | 行锁功过:怎么减少行锁对性能的影响?-02 死锁和死锁检测
【4月更文挑战第19天】在高并发环境下,死锁发生在多个线程间循环等待资源时,导致无限期等待。MySQL中,死锁可通过`innodb_lock_wait_timeout`参数设置超时或`innodb_deadlock_detect`开启死锁检测来解决。默认的50s超时可能不适用于在线服务,而频繁检测会消耗大量CPU。应对热点行更新引发的性能问题,可以暂时关闭死锁检测(风险是产生大量超时),控制并发度,或通过分散记录减少锁冲突,例如将数据分拆到多行以降低死锁概率。
357 1
|
JSON fastjson Java
FastJSON操作各种格式的JSON数据
FastJSON处理各种格式的JSON数据