涂鸦智能暖风机软件实现之利用TM1650实现显示功能

Posted 三明治开发社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了涂鸦智能暖风机软件实现之利用TM1650实现显示功能相关的知识,希望对你有一定的参考价值。


前言

前面我们已经实现了暖风机的外设驱动,本文主要内容是实现暖风机的面板显示功能,采用TM1650芯片作为数码管的驱动芯片。


一、智能暖风机的整体功能设定

  • 智能暖风机的设定功能如下表,我们将整个暖风机拆分成几个模块,逐个实现功能;本文实现暖风机的面板显示功能,暖风机在工作时要显示当前室温以及亮起相应的状态灯,在进行设备定时和设备设温时面板要显示定时的时间和设定的温度值。
功能说明
开关触摸按键:1个
按键控制,app控制
控制暖风机开关。
目前开发的开启有三种方式:
1.App面板控制
2:按键控制
3:定时控制
模式触摸按键:1个
按键控制,app控制
1:风扇功能:只吹风,不制热。
2:1档加热:风扇+加热1
3:2档加热:风扇+加热2(档位更高)
定时触摸按键:1个
按键控制,app控制
倒计时默认枚举值有cancel, 1h, 2h, 3h, 4h, 5h, 6h,7h, 8h。
倒计时功能针对暖风机开关。
app暖风机倒计时剩余时间。
灯光触摸按键:1个
按键控制,app控制
4种照明模式:
1 rgb1
2 rgb2
3 rgb3
4 rgb4
设温触摸按键:1个
按键控制,app控制
默认温度设置区间为15-40℃,客户可以自行调整温度设定区间。
温度显示硬件:断码显示
按键控制,app控制
只是在设定的时候显示
设备上和当前温度显示复用,app单独显示
设备:温度设定时,显示设定温度,误操作3秒后显示当前室温
摇头触摸按键:1个
按键可控制,app可控制。
开/关
待机记忆按键,app,主动操作开关键关机为待机状态。
再开启后恢复上一次设置:
温度设置:上一次设置
温度显示:当前环境温度
灯光模式:上一次设置
设备定时关:默认关闭
app定时关:默认关闭。
app定时开:上一次设置。
断电记忆断电后为断电状态,再上电恢复上一次设置:
开关状态:默认关
温度设置:上一次设置
温度显示:当前环境温度
灯光模式:上一次设置
设备定时关:默认关闭
app定时关:默认关闭。
app定时开:上一次设置。

二、面板显示的方案制定

1.面板显示原理

本案例中面板由两个数码管和7个LED状态灯组成,驱动芯片选择TM1650。

  • 显示电路如下:

在这里插入图片描述

  • TM1650驱动模块说明

    TM1650 是一种带键盘扫描接口的 LED(发光二极管显示器)驱动控制专用电路。

     两种显示模式:8段×4位和7段×4位

     段驱动电流大于25mA,位驱动电流大于150mA

     提供8级亮度控制

     IIC通信控制

寄存器名称寄存器地址
显示设置寄存器(亮度设置、开关显示设置、7段/8段显示)0x48
显存地址DIG10x68
显存地址DIG20x6A
显存地址DIG30x6C
显存地址DIG40x6E

其中显示设置寄存器的配置说明如下:

B7B6B5B4B3B2B1B0功能说明
X000XX亮度设置8级
X001XX亮度设置1级
X010XX亮度设置2级
X011XX亮度设置3级
X100XX亮度设置4级
X101XX亮度设置5级
X110XX亮度设置6级
X111XX亮度设置7级
X07/8段显示控制位8段显示方式
X17/8段显示控制位7段显示方式
X0开启/关闭显示位关显示
X1开启/关闭显示位开显示

打×的位可以为1,也可以为0,建议写0。

  • 对显存地址的写时序
    在这里插入图片描述

控制流程是以IIC时序发送要写的寄存器地址,再发送要写的数据,例:

address : 0x48 //控制寄存器地址
data:	  0x0a //8级亮度 开显示 7段显示方式

address : 0x68 //显存地址DIG1
data:	  0x7f //7段全亮

完整的写时序:
在这里插入图片描述

2.软件方案设定

  • 面板显示嵌入式方案设定
    前面已经实现了暖风机的温度采集功能,现在要将采集的温度显示到面板上,SOC按照IIC时序向TM1650发送显示命令控制数码管亮起相应的数字控制状态指示灯LED亮起,实现面板显示功能。
    通信引脚设定:

    SDA1	| P26	
    SCL1	| P24
    

三、功能实现

1.代码实现

  • 在之前开发的基础上增加程序,增加tm1650.c文件和其头文件,目前整个工程的文件结构如下:
├── src	
|    ├── tuya_drive
|    |  	└── b3950
|    |    		└── b3950.c           //温度传感器驱动相关
|    |  	└── tm1650
|    |    		└──  tm1650.c           
|    |  	└── gpio_control
|    |    		└── gpio_control.c    
|    |  	└── timer
|    |    		└── timer.c           //定时器相关
|    ├── tuya_device.c             //应用层入口文件
|    ├── tuya_thread.c             //主要线程处理文件
|    └── tuya_dp_process.c            //dp数据触发的主要应用文件
|
├── include				//头文件目录
|    ├── tuya_drive_h
|    |  	└── b3950_h
|    |    		└── b3950.h        
|    |  	└── tm1650_h
|    |    		└──  tm1650.h           
|    |  	└── gpio_control_h
|    |    		└── gpio_control.h        
|    |  	└── timer_h
|    |    		└── timer.h           
|    ├── tuya_device.h           
|    ├── tuya_thread.h       
|    └── tuya_dp_process.h       
|
└── output              //编译产物

其中tm1650.c文件中的内容主要是驱动tm1650芯片的代码。

tm1650.c代码及说明如下:

#include "tm1650.h"
typedef struct {
    tuya_i2c_t    *i2c;
} tm1650_dev_t;
/*============================ PROTOTYPES ====================================*/
void tm1650_led_init(void);
void tm1650_init(tm1650_dev_t *dev);
void tm1650_close(void);
void TM1650_Write(uint8_t addr, uint8_t data, tm1650_dev_t *dev);
void TM1650_SetDisplay(uint8_t brightness, uint8_t mode, uint8_t state);
void TM1650_SetNumber(uint8_t index, uint8_t mode,uint8_t num);
/*============================ IMPLEMENTATION ================================*/
static tm1650_dev_t tm1650_dev;
static uint8_t s_7number[10] = {0x5F,0x03,0x6E,0x6B,0x33,0x79,0x7D,0x0B,0x7F,0x7B};   // 7段显示方式0~9
static uint8_t s_8number[10] = {0xDF,0x83,0xEE,0xEB,0xB3,0xF9,0xFD,0x8B,0xFF,0xFB};   // 8段显示方式0~9
/*状态指示灯:cool hot1 hot2 cool+shake hot1+shake hot2+shake set_temperature set_time_hour close */
static uint8_t s_7status[10] = {0x23,0x32,0x2a,0x63,0x72,0x6a,0x02,0x04,0x00};   
/**
 * @Function: tm1650_led_init
 * @Description: tm1650_led display init
 * @Input: none
 * @Output: none
 * @Return: none
 * @Others: 
 */
void tm1650_led_init(void)
{
	/*SCL_PIN:PA24 SDA_PIN:PA26*/
    tuya_i2c_sw_cfg_t   sw_cfg;
    TUYA_I2C_SW_CFG_INIT(&sw_cfg, TUYA_PA24, TUYA_PA26, 1);
    tuya_sw_i2c_register(TUYA_I2C0, &sw_cfg);
    tm1650_init(&tm1650_dev);

}
/**
 * @Function: tm1650 init
 * @Description: Equip with IIC equipment and set the gray level of digital tube
 * @Input: none
 * @Output: none
 * @Return: none
 * @Others: 
 */
void tm1650_init(tm1650_dev_t *dev)
{
    uint8_t buffer[2];
	//! looking for IIC handle
    dev->i2c = tuya_driver_find(TUYA_DRV_I2C, TUYA_I2C0);
    //! no device addr
    TUYA_I2C_MASTER_CFG(dev->i2c, 0x00);
    tuya_i2c_init(dev->i2c);

    buffer[0] = 0x48;             //! register addr
    buffer[1] = 0x71;      //! power set

    tuya_i2c_master_send(dev->i2c, 0x00, TUYA_I2C_NO_START | TUYA_I2C_WR, buffer, 2);
}
/**
 * @Function: tm1650_close
 * @Description: Turn off the digital display
 * @Input: none
 * @Output: none
 * @Return: none
 * @Others: 
 */
void tm1650_close(void)
{
    TM1650_Write(0x68, 0x00, &tm1650_dev);
    TM1650_Write(0x6a, 0x00, &tm1650_dev);
    TM1650_Write(0x6e, 0x00, &tm1650_dev);
}

/**
 * @Function: TM1650_Write
 * @Description: Write data to TM1650
 * @Input: addr:register addr   data: 
 * @Output: none
 * @Return: none
 * @Others: 
 */
void TM1650_Write(uint8_t addr, uint8_t data, tm1650_dev_t *dev)
{          
    uint8_t     buffer[2];
    buffer[0] = addr;   //! register addr
    buffer[1] = data;      //! Transmitted data
    tuya_i2c_master_send(dev->i2c, 0x00, TUYA_I2C_NO_START | TUYA_I2C_WR, buffer, 2);
}

/**
 * @Function: TM1650_SetDisplay
 * @Description: Setting display parameters
 * @Input: brightness:1-8   mode: Paragraph 7/Paragraph 8   state :display on/off
 * @Output: none
 * @Return: none
 * @Others: 
 */
void TM1650_SetDisplay(uint8_t brightness, uint8_t mode, uint8_t state)
{       
    if(state)
    {
        if(mode == 7)                                                   // 7段显示方式
        {
            TM1650_Write(0x48, brightness*16 + 1*4 + 1, &tm1650_dev);
        }
        else if(mode == 8)                                              // 8段显示方式
        {
            TM1650_Write(0x48, brightness*16 + 1, &tm1650_dev);                      
        }
    }
    else
    {
        TM1650_Write(0x48, 0x00,&tm1650_dev);                                       // 关闭显示
    }
}


/**
 * @Function: TM1650_SetNumber
 * @Description: display num
 * @Input: index:Which number  mode: Paragraph 7/Paragraph 8   num :Display number
 * @Output: none
 * @Return: none
 * @Others: 
 */
void TM1650_SetNumber(uint8_t index, uint8_t mode, uint8_t num)
{
    uint8_t indexAddr = 0;
    uint8_t numValue = 0;
    
    if(index == 1)
    {
        indexAddr = 0x68;
    }
    else if(index == 2)
    {
        indexAddr = 0x6A;
    }
    else if(index == 3)
    {
        indexAddr = 0x6C;
    }
    else if(index == 4)
    {
        indexAddr = 0x6E;
    }
    
    if(mode == 7)                                                       // 7段显示方式
    {
        numValue = s_7number[num];
    }
    else if(mode == 8)                                                  // 8段显示方式
    {
        numValue = s_8number[num];                      
    }
    
    TM1650_Write(indexAddr, numValue, &tm1650_dev);
}
/**
 * @Function: display_num
 * @Description: display num
 * @Input: num :Display number
 * @Output: none
 * @Return: none
 * @Others: 
 */
void display_num(uint8_t num)
{
    uint8_t num_1 = 0;
    uint8_t num_10 = 0;
    num_1 = num%10;
    num_10 = (num%100)/10;
    TM1650_SetNumber(1, 7, num_10);
    TM1650_SetNumber(2, 7, num_1);
}
/**
 * @Function: display_status
 * @Description: led_display_work_status
 * @Input: status :work_status
 * @Output: none
 * @Return: none
 * @Others: 
 */
void display_status(uint8_t status)
{
    TM1650_Write(0x6E, status, &tm1650_dev);
}
  • TM1650的驱动工作已经完成,tm1650_init()函数调用后就已经进行了数码管的亮度设置,后面在定时采集温度的线程中调用display_num(temperature)即可显示温度。
    tuya_thread.c增加的代码及说明如下:上报温度信息的线程中每10秒采集一次温度信息并在显示面板进行显示
void update_temperature_thread(void)
{
    static int last_temper = 0;
    while(1)
    {
        tuya_hal_semaphore_wait(g_temper_binsemap);
        last_temper = cur_temper_get();
        if(last_temper > 50)
        {
            last_temper = 50;
        }
        else if(last_temper < -20)
        {
            last_temper = -20;
        }
        temper_s.value = last_temper;
        dp_memory_s.temperature_value = last_temper;

        PR_DEBUG("CURRENT TIME : %d",timercount);
        PR_DEBUG("last_time : %d",dev_key_s.last_time_count);
        //开关开启才会显示,dev_key_s.display_lock初始值为0,后面逻辑控制会用到
        if((switch_s.power == 1) && (dev_key_s.display_lock == 0)){
            display_num(dp_memory_s.temperature_value);
            //根据暖风机的工作状态,开启状态灯
            display_status(dp_memory_s.status);
            report_one_dp_status(DP_TEMPER);
            //如果开启倒计时关闭,将会上传所剩的倒计时时间
            report_one_dp_status(DP_SHUTDOWN_TIME);
        }

    }

}
  • 此时一个暖风机的显示功能就已经实现了,其他功能实现请见后续文章。

技术支持

您可以通过以下方法获得涂鸦的支持:

-涂鸦IoT智能平台
Demo中心

以上是关于涂鸦智能暖风机软件实现之利用TM1650实现显示功能的主要内容,如果未能解决你的问题,请参考以下文章

涂鸦智能暖风机软件实现之利用B3950实现温度采集功能

涂鸦智能暖风机软件实现之暖风机外设驱动实现

涂鸦智能暖风机软件实现之LED驱动和断电记忆功能

涂鸦智能暖风机软件实现之云端控制(完结)

显示面板硬件案例分析(基于TM1650)

涂鸦智能暖风机-FAQ