当前位置: 首页 > news >正文

输入模块(TM1638函数的使用)

输入模块

文章目录

  • 输入模块
    • 1.矩阵键盘
      • 1.1结构图
    • 2.基于TM1638的按键数码管模块
      • 2.1实物图
      • 2.2TM1638简介
      • 2.3特性说明
      • 2.4输入输出时序
      • 2.5显示数码管(实操)

1.矩阵键盘

1.1结构图

4*4的矩阵键盘实验

矩阵键盘

  • 矩阵键盘检测方法:

  • 将高位(后4位)设置为输出;

  • 将其中一位设置为低电平,其余为高电平;

  • 将低位(前4位)设置为输入并上拉

  • 如果没有按键按下,其中的那一位值位0xEF

  • 若有按键按下,根据实际读取值判断按键(如图)

2.基于TM1638的按键数码管模块

2.1实物图

实物图

2.2TM1638简介

TM1638是带键盘扫描接口的LED(发光二极管显示器)驱动控制专用电路,内部集成有MCU 数字接口、数据锁存器、LED 高压驱动、键盘扫描等电路。主要应用于冰箱、空调、家庭影院等产品的高段位显示屏驱动。

2.3特性说明

  • 采用功率CMOS 工艺
  • 显示模式10 段x8位
  • ·键扫描(8x3bit)
  • 辉度调节电路(占空比8级可调)·
  • 串行接口(CLK,STB,DIO)
  • 振荡方式:RC振荡(450KHz+5%)·
  • 内置上电复位电路采用SOP28封装

引脚释义

2.4输入输出时序

读取和接收1个BIT都在时钟的上升沿操作。

输入输出时序

2.5显示数码管(实操)

main.c

#include "TM1638.h"
#include <msp430.h>  // 假设使用MSP430单片机
#include "SysCLK.h"

// TM1638段码表(0-9的显示编码)
//const unsigned char tab1[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
//const unsigned char tab_f[] = {0xBF, 0x86, 0xDB,0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF};
unsigned char num[8] = {2, 0, 2, 1, 1, 2, 1, 7}; // 数码管初始显示值
char i;
int sum = 2014;

// // 延时函数(需根据实际时钟频率调整)
// void delay_ms(unsigned int ms) {
//     while (ms--) {
//         __delay_cycles(1000); // 假设1ms延时
//     }
// }

int main(void) {
    WDTCTL = WDTPW | WDTHOLD;  // 关闭看门狗定时器
    P1DIR |= BIT2 | BIT3 | BIT4; // 设置P1.2(STB), P1.3(CLK), P1.4(DIO)为输出

    init_TM1638();  // 初始化TM1638模块

    // // 示例1:单个LED轮流点亮(需取消注释)
    // for(i = 0; i < 8; i++) {
    //     Write_oneLED(i, 1); // 点亮第i个LED
    //     delay_ms(500);
    //     Write_oneLED(i, 0); // 熄灭第i个LED
    // }

    // // 示例2:多个LED同时点亮(需取消注释)

    // Write_allLED(0x01);    // 仅第1个LED亮
    // delay_ms(1000);
    // Write_allLED(0x0F);    // 第1-4个LED亮

    // // 示例3:指定数码管显示数字(需取消注释)
    
    // Write_DATA(0, tab1[2]);  // 第1个数码管显示"2"
    // Write_DATA(2, tab1[0]);  // 第2个数码管显示"0"

    // // 示例4:按键扫描与显示(需取消注释)

    // while(1) {
    //     i = Read_key();
    //     if (i < 8) {  // 有效按键值为0-7
    //         while(Read_key() == i); // 等待按键释放
    //         Write_DATA(0, tab1[i]); // 在第一个数码管显示按键编号
    //     }
    // }

    // 示例5:数码管显示函数测试(需取消注释)
    
    // TM1638_Show_Left(3254);    // 左4位显示"3254"
    // TM1638_Show_Right(3521);   // 右4位显示"3521"
    // TM1638_ShowSEG4_Left_point(6012); // 显示"60.12"
    // TM1638_ShowSEG4_Left_xs(60.04);   // 显示"60.04"
    TM1638_ShowSEG4_Right_point(2024); //显示20.24
    delay_ms(5000);//5秒后切换
    TM1638_ShowSEG4_Right_xs(20.25); //显示20.25

    while(1); // 主循环
}

TM1638.c

#include "TM1638.h"
#include "SysCLK.h"  // 包含延时函数头文件
#include <msp430.h>



// TM1638段码表(0-9的显示编码)
const unsigned char tab1[] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};
const unsigned char tab_f[] = {0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF};

// TM1638初始化函数
void init_TM1638(void)
{
    unsigned char i;
    Write_COM(0x8b);  // 设置亮度为第4级(0x88-0x8f对应8级亮度,0x8b为中间亮度)
    Write_COM(0x40);  // 设置为地址自动递增模式(写入数据后地址自动+1)

    CLR_STB;          // 拉低STB,开始通信
    TM1638_Write(0xc0); // 设置起始地址为0xC0(对应数码管/LED的初始地址)

    for(i = 0; i < 16; i++) // 清除16个地址的数据(初始化数码管和LED为全灭)
    {
        TM1638_Write(0x00); // 写入0x00(关闭所有段)
    }

    SET_STB;          // 拉高STB,结束初始化
}

// 读数据函数
unsigned char TM1638_Read(void)
{
    unsigned char i;
    unsigned char temp = 0;

    DIO_DIR_IN;  // 设置DIO为输入模式

    for(i = 0; i < 8; i++)
    {
        temp >>= 1;       // 右移一位,准备接收新数据
        CLR_CLK;          // 拉低CLK,准备读取数据

        if(DIO_READ)      // 读取DIO引脚状态
        {
            temp |= 0x80; // 如果DIO为高电平,设置temp的最高位
        }

        SET_CLK;          // 拉高CLK,完成一位数据的读取
    }

    return temp;          // 返回读取的8位数据
}

// 写数据函数
void TM1638_Write(unsigned char S_DATA)
{
    unsigned char i;
    DIO_DIR_OUT;  // 设置DIO为输出模式

    for(i = 0; i < 8; i++)
    {
        CLR_CLK;  // 拉低CLK,准备发送数据

        if(S_DATA & 0x01)  // 检查最低位是否为1
        {
            SET_DIO;  // 如果最低位为1,设置DIO为高电平
        }
        else
        {
            CLR_DIO;  // 如果最低位为0,设置DIO为低电平
        }

        S_DATA >>= 1;  // 右移一位,准备发送下一位数据
        SET_CLK;       // 拉高CLK,完成当前位的发送
    }
}

// 写入命令字
void Write_COM(unsigned char cmd)
{
    CLR_STB;            // 拉低STB,开始通信
    TM1638_Write(cmd);  // 写入命令字(注意:原代码中函数名拼写错误,应为TM1638_Write)
    SET_STB;            // 拉高STB,结束通信
}

// 指定地址写入数据
void Write_DATA(unsigned char add, unsigned char DATA)
{
    Write_COM(0x44);    // 发送固定命令字0x44(表示写入数据模式)
    CLR_STB;            // 拉低STB,开始数据写入
    TM1638_Write(0xC0 | add);  // 发送地址(add为0~15,0xC0为地址命令前缀)
    TM1638_Write(DATA);        // 写入数据
    SET_STB;            // 拉高STB,结束写入
}

// 读取按键值
unsigned char Read_key(void)
{
    unsigned char c[4], i, key_value = 0;

    CLR_STB;                      // 拉低STB,开始通信
    TM1638_Write(0x42);           // 发送读键扫数据命令(0x42)

    for(i = 0; i < 4; i++)        // 读取4个字节的键扫数据
    {
        c[i] = TM1638_Read();     // 每次读取1字节
    }

    SET_STB;                      // 拉高STB,结束通信

    for(i = 0; i < 4; i++)        // 将4字节数据合并为1字节
    {
        key_value |= c[i] << i;   // 按位合并(c[0]在最低位,c[3]在最高位)
    }

    for(i = 0; i < 8; i++)        // 检测按键位置(0~7)
    {
        if((0x01 << i) == key_value)  // 检查哪一位为1
            break;                // 找到按键位置后退出循环
    }

    return i;                     // 返回按键编号(0~7)
}

// 单独控制一个LED函数
// 参数说明:
//   num  - 需要控制的LED序号(通常为0~7,对应8个LED)
//   flag - 控制标志:0表示熄灭LED,非0表示点亮LED
void Write_oneLED(unsigned char num, unsigned char flag)
{
    if(flag)  // 如果flag非0,点亮LED
    {
        Write_DATA(2 * num + 1, 1);  // 写入数据1到指定地址(奇数地址)
    }
    else      // 如果flag为0,熄灭LED
    {
        Write_DATA(2 * num + 1, 0);  // 写入数据0到指定地址(奇数地址)
    }
}

// 控制全部LED函数
// 参数说明:
//   LED_flag - 8位无符号字符,每位对应一个LED的状态(1点亮,0熄灭)
void Write_allLED(unsigned char LED_flag)
{
    unsigned char i;
    for(i = 0; i < 8; i++)  // 遍历8个LED(0~7)
    {
        if(LED_flag & (1 << i))  // 检查第i位是否为1
        {
            Write_DATA(2 * i + 1, 1);  // 点亮第i个LED(写入1到对应奇数地址)
        }
        else
        {
            Write_DATA(2 * i + 1, 0);  // 熄灭第i个LED(写入0到对应奇数地址)
        }
    }
}

// 显示4位数字(左4位数码管)
void TM1638_Show_Left(unsigned int data)
{
    unsigned int d[4], i;
    d[0] = data / 1000;          // 提取千位数字
    d[1] = data / 100 % 10;      // 提取百位数字
    d[2] = data / 10 % 10;       // 提取十位数字
    d[3] = data % 10;            // 提取个位数字

    for (i = 0; i < 4; i++)
    {
        Write_DATA(i * 2, tab1[d[i]]);  // 写入数字到左4位数码管(地址0,2,4,6)
    }
}

// 显示4位数字(右4位数码管)
void TM1638_Show_Right(unsigned int data)
{
    unsigned int d[4], i;
    d[3] = data / 1000;          // 提取千位数字
    d[2] = data / 100 % 10;      // 提取百位数字
    d[1] = data / 10 % 10;       // 提取十位数字
    d[0] = data % 10;            // 提取个位数字

    for (i = 0; i < 4; i++)      // 从右4位数码管地址开始(地址14,12,10,8)
    {
        Write_DATA((7 - i) * 2, tab1[d[i]]);  // 写入数字到右4位数码管
    }
}

// 显示4位整数(左4位数码管,第2位后有小数点)
void TM1638_ShowSEG4_Left_point(unsigned int data)
{
    unsigned int gw, sw, bw, qw;
    gw = data % 10;            // 提取个位
    sw = (data % 100) / 10;    // 提取十位
    bw = (data % 1000) / 100;  // 提取百位
    qw = (data % 10000) / 1000; // 提取千位

    Write_DATA(0, tab1[qw]);     // 千位数(地址0)
    Write_DATA(2, tab_f[bw]);   // 百位数带小数点(地址2)
    Write_DATA(4, tab1[sw]);     // 十位数(地址4)
    Write_DATA(6, tab1[gw]);     // 个位数(地址6)
}

// 显示4位小数(左4位数码管,第2位后有小数点)
void TM1638_ShowSEG4_Left_xs(float data1)
{
    unsigned int gw, sw, bw, qw, data;
    data = (int)(data1 * 100); // 将小数转为整数(保留2位小数)
    gw = data % 10;            // 提取小数第2位(原个位)
    sw = (data % 100) / 10;    // 提取小数第1位(原十位)
    bw = (data % 1000) / 100;  // 提取整数部分个位(原百位)
    qw = (data % 10000) / 1000; // 提取整数部分十位及以上(原千位)

    Write_DATA(0, tab1[qw]);     // 整数高位(地址0)
    Write_DATA(2, tab_f[bw]);   // 整数低位带小数点(地址2)
    Write_DATA(4, tab1[sw]);     // 小数第1位(地址4)
    Write_DATA(6, tab1[gw]);     // 小数第2位(地址6)
}

// 显示4位整数(右4位数码管,第2位后有小数点)
void TM1638_ShowSEG4_Right_point(unsigned int data)
{
    unsigned int gw, sw, bw, qw;
    gw = data % 10;            // 提取个位
    sw = (data % 100) / 10;    // 提取十位
    bw = (data % 1000) / 100;  // 提取百位
    qw = (data % 10000) / 1000; // 提取千位

    Write_DATA(8, tab1[qw]);     // 千位数(地址8)
    Write_DATA(10, tab_f[bw]);   // 百位数带小数点(地址10)
    Write_DATA(12, tab1[sw]);     // 十位数(地址12)
    Write_DATA(14, tab1[gw]);     // 个位数(地址14)
}

// 显示4位小数(右4位数码管,第2位后有小数点)
void TM1638_ShowSEG4_Right_xs(float data1)
{
    unsigned int gw, sw, bw, qw, data;
    data = (int)(data1 * 100); // 将小数转为整数(保留2位小数)
    gw = data % 10;            // 提取小数第2位(原个位)
    sw = (data % 100) / 10;    // 提取小数第1位(原十位)
    bw = (data % 1000) / 100;  // 提取整数部分个位(原百位)
    qw = (data % 10000) / 1000; // 提取整数部分十位及以上(原千位)

    Write_DATA(8, tab1[qw]);     // 整数高位(地址8)
    Write_DATA(10, tab_f[bw]);   // 整数低位带小数点(地址10)
    Write_DATA(12, tab1[sw]);     // 小数第1位(地址12)
    Write_DATA(14, tab1[gw]);     // 小数第2位(地址14)
}



TM1638.h

#ifndef __TM1638_H
#define __TM1638_H
#include "TM1638.h"
#include "msp430.h"
// TM1638模块引脚定义
#define CLR_STB    P1OUT &= ~BIT2  // 将STB引脚置低
#define SET_STB    P1OUT |= BIT2   // 将STB引脚置高

#define CLR_CLK    P1OUT &= ~BIT3  // 将CLK引脚置低
#define SET_CLK    P1OUT |= BIT3   // 将CLK引脚置高

#define DIO_DIR_IN   P1DIR &= ~BIT4  // 设置DIO引脚为输入模式
#define DIO_DIR_OUT  P1DIR |= BIT4   // 设置DIO引脚为输出模式
#define CLR_DIO    P1OUT &= ~BIT4    // 将DIO引脚置低
#define SET_DIO    P1OUT |= BIT4     // 将DIO引脚置高
#define DIO_READ    P1IN & BIT4      // 读取DIO引脚状态

// 外部定义的段码表(需在.c文件中实现)
extern const unsigned char tab1[];
extern const unsigned char tab_f1[];

// 函数声明
void init_TM1638(void);
unsigned char TM1638_Read(void);
void TM1638_Write(unsigned char S_DATA);
void Write_COM(unsigned char cmd);
void Write_DATA(unsigned char add, unsigned char DATA);
unsigned char Read_key(void);
void Write_oneLED(unsigned char num, unsigned char flag);
void Write_allLED(unsigned char LED_flag);
void TM1638_Show_Left(unsigned int data);
void TM1638_Show_Right(unsigned int data);
void TM1638_ShowSEG4_Left_point(unsigned int data);
void TM1638_ShowSEG4_Left_xs(float data1);
void TM1638_ShowSEG4_Right_point(unsigned int data);
void TM1638_ShowSEG4_Right_xs(float data1);

#endif

时钟部分代码,主要是个延时,有需要留言即可.

http://www.dtcms.com/a/99372.html

相关文章:

  • 驱动开发系列49 - 搭建 Vulkan 驱动调试环境(编译 mesa 3D)- Ubuntu24.04
  • postman测试文件上传接口详解
  • 鸿蒙原生开发之状态管理V2
  • 白盒测试/接口测试/自动化测试
  • python 如何打包成exe文件
  • 嵌入式系统安全架构白皮书
  • PH热榜 | 2025-03-29
  • 【C语言】一文掌握 C 语言用法(C 备忘清单)
  • 数据湖的数据存储与管理策略:构建高效的数据管理框架
  • Web自动化测试:Unittest单元测试框架
  • 如果从一个系统向另一个系统推送2000条数据,java中使用什么技术合理
  • 【AI速读】CNN图像处理单元的形式化验证方法
  • 简单程序语言理论与编译技术·18 语法制导翻译SDT
  • 【文本张量表示】
  • docker部署mongodb数据库
  • 【Python NetworkX】图结构 图绘制
  • 如何下载主流网站的视频和音频?(支持100+网站视频下载)
  • CAN 介绍
  • C语言 - 变量修饰关键字
  • 软件测试之接口测试
  • 【Git “reflog“ 命令详解】
  • Vue2 项目将网页内容转换为图片并保存到本地
  • 基于74LS192的十进制两位数正向计时器(proteus仿真)
  • pycharm找不到conda可执行文件解决办法
  • 【数据结构】并查集
  • 数据湖的崛起:从大数据到智能未来的钥匙
  • 嵌入式开发技术总结报告
  • 从呼叫中心到大模型赋能:客户服务的智能化跃迁与人机协同新范式
  • 第二章 机器学习概述(续)
  • Linux上位机开发实践(MPP平台的核心构成)