数码之家

 找回密码
 立即注册

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

搜索
查看: 456|回复: 3

[other] TM1652显示程序

[复制链接]
发表于 2025-5-23 13:14:53 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册 微信登录

x
因为TM1652是单数据线接口,对时序要求比较严,需要针对应用的硬件作精确延时,除此之外跟其他TM驱动芯片没有区别,


#include "stc8g.h"
#include <intrins.h>

sbit PIN_SDA    = P3^3;
sbit PIN_UP                = P5^4;
sbit PIN_DOWN        = P5^5;
sbit PIN_START        = P3^2;
sbit PIN_UVLED        = P3^1;

#define KEY_UP         0xA0
#define KEY_DOWN       0xA1
#define KEY_START      0xA2
#define KEY_ADJUST           0xA3

#define STATUS_IDLE           0 //空闲
#define STATUS_RUNNING 1 //运行
#define STATUS_ADJUST  2 //调节

const unsigned char DT[] = {
//[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [A], [-]
  0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x40
};

unsigned char status = 0; //状态
unsigned char worktime = 6; //工作时长1~99


unsigned short cnt250ms, cnt500ms, cnt1s;
bit flag1ms, flag250ms, flag500ms, flag1s;
void TM0_Isr() interrupt 1
{
        flag1ms = 1;
        if (++cnt250ms >= 250) { cnt250ms=0; flag250ms=1; }
        if (++cnt500ms >= 500) { cnt500ms=0; flag500ms=1; }
        if (++cnt1s   >= 1000) { cnt1s = 0;  flag1s = 1;  }
}

void delay_52us(void)
{
        unsigned i = 200;
        while(i--) {
                _nop_();
        }
}

void tm1652_start(void)
{
        PIN_SDA = 0;
        delay_52us();
}

void tm1652_stop(void)
{
        PIN_SDA = 1;
        delay_52us();
}

void tm1652_wr_8bits(unsigned char ch)
{
        char i, cnt=0;
        tm1652_start();
        for (i=0; i<8; i++)
        {
                if (ch & 0x01) {
                        PIN_SDA = 1;
                        cnt += 1;
                } else {
                        PIN_SDA = 0;
                }
                delay_52us();
                ch >>= 1;
        }
        PIN_SDA = (bit)(cnt%1);
        delay_52us();
        tm1652_stop();
}

void tm1652_wr_cmd(unsigned char cmd)        //0xFE
{
        tm1652_wr_8bits(0x18); //控制
        tm1652_wr_8bits(cmd);
}

void tm1652_wr_data(unsigned char h, unsigned char l)
{
        tm1652_wr_8bits(0x08); //地址GR1
        tm1652_wr_8bits(DT[h]);
        tm1652_wr_8bits(DT[l]);
}

void display_worktime(void)
{
        char h = worktime/10;
        char l = worktime%10;
        tm1652_wr_data(h, l);
        tm1652_wr_cmd(0xFE);
}

#define KEYDLY        3000
unsigned char keytmp=0, keybak=0;
unsigned short keycnt=0;
unsigned char keyget(void)
{
        //PIN_UP = 1;
        //PIN_DOWN = 1;
        //PIN_START = 1;
        //_nop_();

        if (PIN_START && PIN_UP && PIN_DOWN) {
                keytmp = 0;
                keybak = 0;
                keycnt = 0;
                return 0xFF;
        }

        if (!PIN_START) {
                keytmp = KEY_START;
        } else if (!PIN_UP) {
                keytmp = KEY_UP;
        } else if (!PIN_DOWN) {
                keytmp = KEY_DOWN;
        }

        if (keybak == keytmp)
        {
                if (keycnt < KEYDLY) {
                        if (keycnt == 10) { //short press
                                keycnt++;
                                return keytmp;
                        } else if (keycnt==(KEYDLY-1)) { //long press
                                keycnt = KEYDLY;
                                if (keytmp == KEY_UP)
                                        return KEY_ADJUST;
                        }
                        keycnt++;
                }
        } else {
                keybak = keytmp;
        }
        return 0xFF;
}

void main(void)
{
        unsigned char key=0xFF;

        P3M0 = 0x0;     //设置P3.0~P3.7为双向模式
    P3M1 = 0x0;
        P5M0 = 0x0;     //设置P5.0~P5.7为双向模式
    P5M1 = 0x0;

        TMOD = 0x00;
        TL0  = 0x66;  //65535-11.0592M/12/1000 (1ms)
        TH0  = 0xFC;
        TR0  = 1;     //启动定时器
        ET0  = 1;     //使能定时器中断
        EA   = 1;

        status = STATUS_IDLE;
        worktime = 6;
        PIN_UVLED = 0;
        display_worktime();

        while(1)
        {
                if (flag1ms) {
                        flag1ms = 0;
                        key = keyget();
                        if (key == 0xFF) continue;
                        if (status == STATUS_IDLE) {
                                if (key == KEY_START) {
                                        status = STATUS_RUNNING;
                                        PIN_UVLED = 1;
                                } else if (key == KEY_ADJUST) {
                                        status = STATUS_ADJUST;
                                }
                        } else if (status == STATUS_RUNNING) {
                                if (flag1s) {
                                        flag1s = 0;
                                        if (worktime > 0) {
                                                worktime -= 1;
                                                //display update
                                                display_worktime();
                                        }
                                        if (worktime == 0) {
                                                status = STATUS_IDLE;
                                                PIN_UVLED = 0;
                                        }
                                }
                        } else if (status == STATUS_ADJUST) {
                                if (key == KEY_UP) {
                                        if (worktime < 99) worktime++;
                                        display_worktime();
                                } else if (key == KEY_DOWN) {
                                        if (worktime > 0) worktime--;
                                        display_worktime();
                                } else if (key == KEY_START) { //退出调节
                                        status = STATUS_IDLE;
                                }
                        }
                }
        }
}


 楼主| 发表于 2025-5-25 11:03:54 | 显示全部楼层
//TM1651, 类I2C接口, 其实跟I2C区别很大,
  1. sbit DIO    = P1^0;
  2. sbit CLK    = P1^1;

  3. const unsigned char DT[] = {
  4.   //[0], [1], [2], [3], [4], [5], [6], [7], [8], [9], [A], [-]
  5.         0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x40
  6. };


  7. void i2c_start()
  8. {
  9.         CLK = 1;
  10.         DIO = 1;
  11.         delay_us(2);
  12.         DIO = 0;
  13. }

  14. void i2c_stop()
  15. {
  16.         CLK = 1;
  17.         DIO = 0;
  18.         delay_us(2);
  19.         DIO = 1;
  20. }

  21. void i2c_ack(void)
  22. {
  23.         CLK = 0;
  24.         delay_us(5);
  25.         while(DIO);
  26.         CLK = 1;
  27.         delay_us(2);
  28.         CLK = 0;
  29. }

  30. void i2c_write(uint8_t ch)
  31. {
  32.         char i;
  33.         for (i=0; i<8; i++)
  34.         {
  35.                 CLK = 0;
  36.                 if (ch & 0x01) {
  37.                         DIO = 1;
  38.                 } else {
  39.                         DIO = 0;
  40.                 }
  41.                 delay_us(3);
  42.                 ch >>= 1;
  43.                 CLK = 1;
  44.                 delay_us(3);
  45.         }
  46.        
  47.         i2c_ack();
  48. }

  49. //设定LED数码管的显示亮度
  50. //level: 0~7 //亮度取值范围
  51. void tm1651_light(uint8_t level)
  52. {
  53.         if (level > 7)
  54.                 level = 7;
  55.         i2c_start();
  56.         i2c_write(0x88 + level);
  57.         i2c_stop();
  58. }

  59. //在指定的数码管上写入数据, 4个数码管映射为0~3
  60. //addr: 0~3
  61. void tm1651_display(uint8_t addr, uint8_t dat)
  62. {
  63.         i2c_start();
  64.         i2c_write(0x44); //固定地址
  65.         i2c_stop();
  66.        
  67.         i2c_start();
  68.         i2c_write(0xC0 | addr);
  69.         i2c_write(DT[dat]);
  70.         i2c_stop();
  71. }

  72. void tm1651_display2(uint8_t addr, uint8_t *dat)
  73. {
  74.     i2c_start();
  75.     i2c_write(0x44); //地址自增
  76.     i2c_stop();

  77.     i2c_start();
  78.     i2c_write(0xC0 | addr); //写入的首地址
  79.     i2c_write(DT[*dat++]);
  80.     i2c_write(DT[*dat++]);
  81.     i2c_write(DT[*dat++]);
  82.     i2c_write(DT[*dat]);
  83.     i2c_stop();

  84.     tm1651_light(7); //也可注释掉,仅在开机初始化代码中调用
  85. }
复制代码
回复 支持 反对

使用道具 举报

发表于 2025-5-25 15:51:07 来自手机浏览器 | 显示全部楼层
TM1652就是uart口吧
回复 支持 反对

使用道具 举报

 楼主| 发表于 2025-5-26 22:45:20 | 显示全部楼层
o535913 发表于 2025-5-25 15:51
TM1652就是uart口吧

是的,1652可用串口TX脚驱动,但有时需要用串口,模拟串口才有了用武之地
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册 微信登录

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2025-7-24 13:18 , Processed in 0.156001 second(s), 12 queries , Redis On.

Powered by Discuz!

© 2006-2025 MyDigit.Net

快速回复 返回顶部 返回列表