STM32模拟I2C控制TM1650数码管显示电压电流

news2024/11/18 21:38:34

模拟I2C控制TM1650数码管显示电压电流

  • 数码管的逻辑
  • TM1650 原理
  • 模拟I2C的实现
  • TM1650驱动
  • 电压电流显示

数码管的逻辑

通过数码管来表示字符。
在这里插入图片描述
数码管的abcdefg和dp分别对应这发送过去的8位数据位比如0x3F -> 0011 1111 表示0字符。
如果要加上小数点则在最高位加一,变成了 1011 1111。
在这里插入图片描述

TM1650 原理

SCL:串行通信时钟线

SDA:串行通信数据线

做数码管驱动使用时

DIGx:数码管的位选引脚,灌电流驱动,最大可吸收150mA电流
A~DP:数码管的段驱动引脚,拉电流驱动,最大可输出25mA电流
在这里插入图片描述
这个指令用于设置数码管显示的相关参数。例如亮度,7段或者8段显示,显示的开关。模式命令固定为0x48,而显示命令则满足以下格式:
在这里插入图片描述

TM1650内部有4字节的显存,地址分别为0x68,0x6A,0x6C,0x6E,分别用于存放显示在DIG1,DIG2,DIG3,DIG4的段码数据。例如想要让DIG1对应的数码管位显示数字2,则要往0x68单元写入数字2的共阴段码0x5b。
在这里插入图片描述

模拟I2C的实现

这边主要参考了Leung_ManWah老哥

static void SDA_OUT_MODE(void);
static void SDA_IN_MODE(void);

void IIC2_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    __HAL_RCC_GPIOA_CLK_ENABLE();

    GPIO_InitStructure.Pin    = IIC_SCL_PIN;
    GPIO_InitStructure.Speed  = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Mode   = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStructure.Pull   = GPIO_PULLDOWN;
    HAL_GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);

    GPIO_InitStructure.Pin = IIC_SDA_PIN;
    HAL_GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);

    IIC_Stop();
}

void IIC_Start(void)
{
    SDA_OUT_MODE();

    IIC_SDA_1();
    IIC_SCL_1();
    HAL_Delay(1);
    IIC_SDA_0();
    HAL_Delay(1);
    IIC_SCL_0();
}

void IIC_Stop(void)
{
    SDA_OUT_MODE();

    IIC_SCL_0();
    IIC_SDA_0();
    IIC_SCL_1();
    HAL_Delay(1);
    IIC_SDA_1();
    HAL_Delay(1);
}

void IIC_SendByte(uint8_t ucByte)
{
    uint8_t i;

    SDA_OUT_MODE();

    IIC_SCL_0();

    for (i = 0; i < 8; i++)
    {
        if (ucByte & 0x80)
        {
            IIC_SDA_1();
        }
        else
        {
            IIC_SDA_0();
        }
        ucByte <<= 1;
        HAL_Delay(1);
        IIC_SCL_1();
        HAL_Delay(1);
        IIC_SCL_0();
        HAL_Delay(1);
    }
}

uint8_t IIC_ReadByte(void)
{
    uint8_t i = 0;
    uint8_t value = 0;

    SDA_IN_MODE();

    for (i = 0; i < 8; i++)
    {
        value <<= 1;
        IIC_SCL_1();
        HAL_Delay(1);
        if (IIC_SDA_READ())
        {
            value++;
        }
        IIC_SCL_0();
        HAL_Delay(1);
    }
    IIC_Ack();

    return value;
}

uint8_t IIC_WaitAck(void)
{
    uint8_t result = 0;

    SDA_IN_MODE();

    IIC_SDA_1();
    HAL_Delay(1);
    IIC_SCL_1();
    HAL_Delay(1);
    if (IIC_SDA_READ())
    {
        result = 1;
    }
    else
    {
        result = 0;
    }
    IIC_SCL_0();
    HAL_Delay(1);

    return result;
}

void IIC_Ack(void)
{
    SDA_OUT_MODE();

    IIC_SDA_0();
    HAL_Delay(1);
    IIC_SCL_1();
    HAL_Delay(1);
    IIC_SCL_0();
    HAL_Delay(1);
    IIC_SDA_1();
}

void IIC_NAck(void)
{
    SDA_OUT_MODE();

    IIC_SDA_1();
    HAL_Delay(1);
    IIC_SCL_1();
    HAL_Delay(1);
    IIC_SCL_0();
    HAL_Delay(1);
}

uint8_t IIC_CheckDevice(uint8_t address)
{
    uint8_t ucAck;

    IIC2_Init();
    IIC_Start();
    IIC_SendByte(address);
    ucAck = IIC_WaitAck();
    IIC_Stop();

    return ucAck;
}

static void SDA_OUT_MODE(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.Pin   = IIC_SDA_PIN;
    GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_HIGH;
    GPIO_InitStructure.Mode  = GPIO_MODE_OUTPUT_OD;
    HAL_GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}

static void SDA_IN_MODE(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.Pin  = IIC_SDA_PIN;
    GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
    HAL_GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);
}

TM1650驱动

这边在老哥的基础上增加了对字符 A P V的显示


static uint8_t s_7number[13] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F, 0x73, 0x3E, 0x77}; // 7display 0~9 %(P) V A
static uint8_t s_8number[13] = {0xBF, 0x86, 0xDB, 0xCF, 0xE6, 0xED, 0xFD, 0x87, 0xFF, 0xEF, 0xF3, 0xBE, 0xF7}; // 8display 0~9 %(P) V A

void TM1650_Write(uint8_t addr, uint8_t data)
{
    IIC_Start();
    IIC_SendByte(addr);
    IIC_WaitAck();
    IIC_SendByte(data);
    IIC_Ack();
    IIC_Stop();
}

void TM1650_SetDisplay(uint8_t brightness, uint8_t mode, uint8_t state)
{
    if(state)
    {
        if(mode == 7)                                                   // 7display
        {
            TM1650_Write(0x48, brightness*16 + 1*4 + 1);
        }
        else if(mode == 8)												// 8display
        {
            TM1650_Write(0x48, brightness*16 + 1);
        }
    }
    else
    {
        TM1650_Write(0x48, 0x00);                                       // close
    }
}

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)                                                   	// 7display
    {
        numValue = s_7number[num];
    }
    else if(mode == 8)													// 8display
    {
        numValue = s_8number[num];
    }

    TM1650_Write(indexAddr, numValue);
}

电压电流显示

这边应用层 对电压采用两位整数一位小数的显示方式,对电流采用一位整数两位小数的显示方式

int current_display(float current)
{
    int display_num;
    TM1650_SetDisplay(3, 8, 0);

    if (current <= 0)
    {
        return OPEN_ERR;
    }

    TM1650_SetDisplay(0, 8, 1);

    if (current > 10)
    {
        display_num = (int)(current * 0.1f);
        TM1650_SetNumber(1, 7, (display_num % 10));
    }
    else
    {
        TM1650_SetNumber(1, 7, 0);
    }

    if (current >= 1)
    {
        display_num = (int)current;
        TM1650_SetNumber(2, 8, (display_num % 10));
    }
    else
    {
        TM1650_SetNumber(2, 8, 0);
    }

    display_num = (int)(current*10.0f);
    TM1650_SetNumber(3, 7, (display_num % 10));

    TM1650_SetNumber(4, 7, A);

    return OK;
}

int voltage_display(float voltage)
{
    int display_num;
    TM1650_SetDisplay(3, 8, 0);

    if (voltage <= 0)
    {
        return OPEN_ERR;
    }

    TM1650_SetDisplay(0, 8, 1);

    if (voltage > 10)
    {
        display_num = (int) (voltage *0.1f);
        TM1650_SetNumber(1, 7, display_num % 10);
    }
    else
    {
        TM1650_SetNumber(1, 7, 0);
    }

    if (voltage >= 1)
    {
        display_num = (int) voltage;
        TM1650_SetNumber(2, 8, (display_num % 10));
    }
    else
    {
        TM1650_SetNumber(2, 8, 0);
    }

    display_num = (int) (voltage * 10.0f);
    TM1650_SetNumber(3, 7, (display_num % 10));

    TM1650_SetNumber(4, 7, V);

    return OK;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1514783.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

同步整流芯片 支持12V降5V 24V降5V 24V降12V 降压芯片 H4122

惠海H4122降压恒压芯片的工作原理&#xff1a; 主要是通过内部电路和算法来控制和调节输出电压&#xff0c;使其保持恒定。 输入电压&#xff1a;芯片接收一个较高的输入电压&#xff0c;如12V、24V或36V。 开关电源转换器&#xff1a;芯片内部通常包含一个或多个开关电源转…

【python pyinstaller库】pyinstaller介绍、安装、以及相关重点知识

PyInstaller是一个在Windows、GNU/Linux、macOS等平台下将Python程序冻结&#xff08;打包&#xff09;为独立可执行文件的工具, 用于在未安装Python的平台上执行Python编写的应用程序。 相比类似工具&#xff0c;它的主要优点是 PyInstaller 与 Python 3.7-3.10 一起工作&…

StarRocks实战——云览科技存算分离实践

目录 背景 一、平台现状&痛点 1.1 使用组件多&#xff0c;维护成本高 1.2 链路冗长&#xff0c;数据时效性难以保证 1.3 服务稳定性不足 二、StarRocks 存算分离调研 2.1 性能对比 2.2 易用性 2.3 存储成本 三、StarRocks 存算分离实践 3.1 查询优化 3.1.1 物化…

SyntaxError: Unexpected end of JsON input J50N.parse....报错

const userInfoJSON.parse(uni.getStorageSync(userInfo))改成 const userInfouni.getStorageSync(userInfo)&& JSON.parse(uni.getStorageSync(userInfo)) //不报错

ChatGPT国内能用吗?中国用户怎么才能使用ChatGPT?

与ChatGPT类似的国内网站&#xff0c;他们都能提供和ChatGPT相似的能力&#xff0c;而且可以在国内直接使用。 点击直达方式 百科GPT官网&#xff1a;baikegpt.cn ChatGPT是基于GPT-3.5架构的语言模型的一个实例&#xff0c;由OpenAI开发。以下是ChatGPT的发展历史&#xff1…

深入理解Python中的面向对象编程(OOP)【第129篇—Scikit-learn的入门】

深入理解Python中的面向对象编程&#xff08;OOP&#xff09; 在Python编程领域中&#xff0c;面向对象编程&#xff08;Object-Oriented Programming&#xff0c;简称OOP&#xff09;是一种强大而灵活的编程范式&#xff0c;它允许开发者以对象为中心组织代码&#xff0c;使得…

Redis7.2.4分片集群搭建

Redis分片集群搭建 1.集群结构 分片集群需要的节点数量较多&#xff0c;这里我们搭建一个最小的分片集群&#xff0c;包含3个master节点&#xff0c;每个master包含一个slave节点&#xff0c;结构如下&#xff1a; 信息如下&#xff1a; IPPORT角色glnode036379slaveglnode0…

JavaEE:文件IO

硬盘 文件指的是硬盘/磁盘上的文件 ⚠硬盘 ≠ 磁盘 磁盘属于外存的一种&#xff1b;而软盘&#xff0c;硬盘&#xff08;机械硬盘&#xff09;这种属于用磁性介质来存储二进制数据 ssd硬盘&#xff08;固态硬盘&#xff09;&#xff0c;内部完全是集成电路&#xff0c;和磁…

手写简易操作系统(七)--加载操作系统内核

前情提要 上一节中&#xff0c;我们开启了内存分页&#xff0c;这一节中&#xff0c;我们将加载内核&#xff0c;内核是用C语言写的&#xff0c;C语言编译完了是一段ELF可加载程序&#xff0c;所以我们需要学会解析ELF格式文件&#xff0c;并将内核加载到内存 一、ELF格式 程…

(黑马出品_高级篇_04)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式

&#xff08;黑马出品_高级篇_04&#xff09;SpringCloudRabbitMQDockerRedis搜索分布式 微服务技术——可靠性消息服务 今日目标服务异步通信-高级篇1.消息可靠性1.1.生产者消息确认1.1.1.修改配置1.1.2.定义Return回调1.1.3.定义ConfirmCallbac…

【LeetCode热题100】2. 两数相加(链表)

一.题目要求 给你两个 非空 的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的&#xff0c;并且每个节点只能存储 一位 数字。 请你将两个数相加&#xff0c;并以相同形式返回一个表示和的链表。 你可以假设除了数字 0 之外&#xff0c;这两个数…

论文阅读——RemoteCLIP

RemoteCLIP: A Vision Language Foundation Model for Remote Sensing 摘要——通用基础模型在人工智能领域变得越来越重要。虽然自监督学习&#xff08;SSL&#xff09;和掩蔽图像建模&#xff08;MIM&#xff09;在构建此类遥感基础模型方面取得了有希望的结果&#xff0c;但…

深度学习系列62:Agent入门

1 anget介绍和openai标准接口 agent的核心是其代理协同工作的能力。每个代理都有其特定的能力和角色&#xff0c;你需要定义代理之间的互动行为&#xff0c;即当一个代理从另一个代理收到消息时该如何回复。 agent目前大多使用openai标准接口调用LLM服务&#xff0c;说明如下。…

Java集合基础知识总结(绝对经典)

List接口继承了Collection接口&#xff0c;定义一个允许重复项的有序集合。该接口不但能够对列表的一部分进行处理&#xff0c;还添加了面向位置的操作。 实际上有两种list&#xff1a;一种是基本的ArrayList&#xff0c;其优点在于随机访问元素&#xff0c;另一种是更强大的L…

PYTHON 自动化办公:更改图片后缀

1、前言 在之前的文章中&#xff0c;介绍了图片的压缩技术&#xff0c;这里讲解如何利用python批量将图片改为指定后缀的格式。当然&#xff0c;也可以为深度学习批量更改文件后缀&#xff0c;例如在分割中&#xff0c;可能需要img和mask的图片名称完全一致等等 PYTHON 自动化…

掌握FilterOutputStream类!

咦咦咦&#xff0c;各位小可爱&#xff0c;我是你们的好伙伴——bug菌&#xff0c;今天又来给大家普及Java IO相关知识点了&#xff0c;别躲起来啊&#xff0c;听我讲干货还不快点赞&#xff0c;赞多了我就有动力讲得更嗨啦&#xff01;所以呀&#xff0c;养成先点赞后阅读的好…

谈谈Darknet53为啥这么难训练

在我使用Imagenet2012对Darknet53进行预训练的时候&#xff0c;往往训练到一半&#xff0c;就会出现过拟合&#xff0c;导致无法继续向下训练&#xff0c;尝试了很多方法&#xff0c;最后发现问题出现在下图红框的部分。 得出这个结论是因为当我使用Resnet中&#xff0c;包含有…

力扣654 最大二叉树 Java版本

文章目录 题目描述解题思路代码 题目描述 给定一个不重复的整数数组 nums 。 最大二叉树 可以用下面的算法从 nums 递归地构建: 创建一个根节点&#xff0c;其值为 nums 中的最大值。 递归地在最大值 左边 的 子数组前缀上 构建左子树。 递归地在最大值 右边 的 子数组后缀上…

【DVWA】19. Insecure CAPTCHA 不安全的验证码(全等级)

文章目录 1. Low1) 源码分析2&#xff09;实操 2. Medium1) 源码分析2&#xff09;实操 3. High1) 源码分析2&#xff09;实操 4. Impossible1) 源码分析 1. Low 1) 源码分析 <?phpif( isset( $_POST[ Change ] ) && ( $_POST[ step ] 1 ) ) {// Hide the CAPTC…

WPF图表库LiveCharts的使用

这个LiveCharts非常考究版本&#xff0c;它有非常多个版本&#xff0c;.net6对应的是LiveChart2 我这里的wpf项目是.net6&#xff0c;所以安装的是这三个&#xff0c;搜索的时候要将按钮“包括愈发行版”打勾 git&#xff1a;https://github.com/beto-rodriguez/LiveCharts2?…