树莓派开发相关知识七 -串口数码管

1、概述

一个普通的数码管实际上为7+1个LED灯。

上图可知,A-G加上DP点8个LED,通过不同的亮暗来显示出所需的数字。

如果同时要控制多个数码管,则需要的GPIO未免太多。

我们选择控制4个数码管,通过串行转并行的方式实现控制。

所谓串行转并行,即与串口类似,在一根线上加上时间的维度,通过时序来转换为不同的并行输出。即,我们可以通过两根线控制4个数码管32个灯。 这种串行转并行,总线协议的前兆,这里的实现方式与I2C总线非常类似。

一般串行总线的实现,是协议+地址+寄存器+数据+……这种形式。

tm1637驱动方式:

CLK、DIO两个引脚加上VCC与GND。

  • CLK:时钟线,与串口不同,不是通过波特率同步,而是通过CLK这根线的脉冲同步
  • DIO:数据线,与CLK配合,实现串行数据的传输。

2、接口说明

微处理器的数据通过两线总线接口和 TM1637 通信,在输入数据时当 CLK 是高电平时,DIO 上的信号必须保持不变;只有 CLK 上的时钟信号为低电平时,DIO 上的信号才能改变。数据输入的开始条件是 CLK为高电平时,DIO 由高变低;结束条件是 CLK 为高时,DIO 由低电平变为高电平。TM1637 的数据传输带有应答信号 ACK,当传输数据正确时,会在第八个时钟的下降沿,芯片内部会产生一个应答信号 ACK 将 DIO 管脚拉低,在第九个时钟结束之后释放 DIO 口线。

Command:读按键指令;

S0、S1、S2、K1、K2 组成按键信息编码,S0、S1、S2为SGn 的编码,K1、K2 为 K1 和 K2 键的编码,

读按键时,时钟频率应小于 250K,先读低位,后读高位。

协议中的start(S)与stop(P)状态。

  • start:CLK高电平时,DIO由高变低,则为start状态
  • stop:CLK高电平时,DIO由低变高,则为stop状态

如uart串口协议可知,有开始于结束的状态,这里的状态即为start与stop两种。

切记CLK时钟线处于高电平,DIO不能随便发生变化,否则为start/stop状态中的任意一个,此时模块会“重新开始”数据传输。

CLK低电平时,DIO可以随意改变状态。数据的传输是发生在CLK的上升沿,每次数据传输8位,LSB低位在前。

协议中的ack(A)状态。 ack:模块的应答信号,自动将DIO拉低表示获取8位数据完毕。

计算设备与外设模块之间的通信,由CLK、DIO这两根线根据协议,以时间为轴线进行数据传输。

此类协议的详细步骤详细的解释如下:

  • 平时不传输协议,CLK,DIO都拉高
  • DIO变低,则start状态开启
  • CLK拉低,DIO切换状态,CLK拉高,注意拉高之后DIO不能随意改状态,否则触发start或者stop。
  • 此时一位数据的传输,发生在CLK变低后DIO确定状态后,拉高的上升沿触发,即CLK从低变高的一瞬间,外设模块迅速锁定DIO此时的状态,并 当做一位数据。
  • 以此类推,重复8次,传输8位数据,低位在前。
  • 第8个数据传输完毕后的CLK下降沿,触发外设芯片内部的ACK,强制拉低DIO,表示外设芯片告诉主设备收到了8个数据。主设备通过ACK获知传 输过程有没有错误,即手动拉高DIO后再读取DIO的电平,如果切换为低电平表示外设强制拉低了。
  • 第9个时钟后,外设芯片释放DIO。
  • 这种8位数据的传输根据需求连续发生多次,后stop状态切换一轮数据结束。

3、TM1637控制代码实现

class TM1637:
    dio = 0
    clk = 0
    def __init__(self, dio, clk):
        self.dio = dio
        self.clk = clk
        GPIO.setup(clk, GPIO.OUT, initial = GPIO.HIGH)
        GPIO.setup(dio, GPIO.OUT, initial = GPIO.HIGH)
    def start(self):
        # 开始信号,clk为高时,dio由高变低
        GPIO.output(self.clk, GPIO.HIGH)
        GPIO.output(self.dio, GPIO.HIGH)
        GPIO.output(self.dio, GPIO.LOW)
        GPIO.output(self.clk, GPIO.LOW)
    def start(self):
        # 开始条件,默认clk高,dio高,clk高的时候,将dio从高拉低
        GPIO.output(self.clk, GPIO.HIGH)
        GPIO.output(self.dio, GPIO.HIGH)
        GPIO.output(self.dio, GPIO.LOW)
        GPIO.output(self.clk, GPIO.LOW)
    def end(self):
        # 结束条件,默认clk低,dio低,clk高的时候,将dio从低拉高
        GPIO.output(self.clk, GPIO.LOW)
        GPIO.output(self.dio, GPIO.LOW)
        GPIO.output(self.clk, GPIO.HIGH)
        GPIO.output(self.dio, GPIO.HIGH)
    def write(self, data):
        for i in range(0, 8):
            # 拉低clk
            GPIO.output(self.clk, GPIO.LOW)
            # 切换dio状态,低位在前 LSB
            if data & 0x01:
                GPIO.output(self.dio, GPIO.HIGH)
            else:
                GPIO.output(self.dio, GPIO.LOW)
            data >>= 1
            # 上升沿触发数据锁存
            GPIO.output(self.clk, GPIO.HIGH)
        # 下降沿触发ack,第八个下降沿
        GPIO.output(self.clk, GPIO.LOW)
        # 强制拉高dio,判断ack回应数据,必须在clk低电平时操作,否则可能触发stop
        GPIO.output(self.dio, GPIO.HIGH)
        # 第九个时钟
        GPIO.output(self.clk, GPIO.HIGH)
        GPIO.setup(self.dio, GPIO.IN)
        if GPIO.input(self.dio) == GPIO.HIGH:
            # 没有响应,出错
            GPIO.setup(self.dio, GPIO.OUT, initial = GPIO.HIGH)
            return None
        else:
            # 有响应,对了
            GPIO.setup(self.dio, GPIO.OUT, initial = GPIO.HIGH)
        return

4、两种控制方式

4.1 写 SRAM 数据地址自动加1模式

数据命令设置

4.2 写 SRAM 数据固定地址模式

地址命令设置

该指令用来设置显示寄存器的地址;如果地址设为0C6H 或更高,数据被忽略,直到有效地址被设定;上电时,地址默认设为00H。

显示控制

5、控制实现代码

# 地址自动加一模式,data使用列表
def send_auto_data(self, data):
    # command1:设置数据
    # 01000000
    self.start()
    self.write(0B01000000)
    self.end()
    # command2:设置地址
    # 11000000
    self.start()
    self.write(0B11000000)
    # data1-n
    self.write(num[data[0]])
    self.write(num[data[1]] | 0x80) # 中间的冒号
    self.write(num[data[2]])
    self.write(num[data[3]])
    self.end()
    # command3:控制显示
    # 10001111
    self.start()
    self.write(0B10001111)
    self.end()
    
 # 固定地址模式,0x0为第一个数码管,以此类推
def send_addr_data(self, addr, data):
    if addr < 0 or addr > 3:
        return None
    # 设置数据
    self.start()
    self.write(0B01000100)
    self.end()
    # 设置地址
    self.start()
    addr |= (0B11000000)
    self.write(addr)
    # 设置数据
    self.write(data)
    self.end()
     # 显示控制
    self.start()
     self.write(0B10001111)
     self.end()

6、调用代码

#!/usr/bin/env python
#coding:utf-8

import TM167
import RPi.GPIO as GPIO
import time
nums=[0B00111111,0B00000110,0B01011011,0B01001111,0B01100110,0B01101101,0B1111101,0B00000111,0B01111111,0B01101111]
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
obj=TM167.TM1637(12,16)

#初始化
for i in range(4):
	obj.send_addr_data(i,nums[0])
time.sleep(1)
for i in range(4):
	obj.send_addr_data(i,0)
time.sleep(0.5)
flag=False
#封装函数 小时 分钟
def showinfo(h,m):
	global flag
	ts=[h/10,h%10,m/10,m%10]
	for i in range(4):
		if i==1:
			if flag==False:
				obj.send_addr_data(i,nums[ts[i]]|0B10000000)
				flag=True
			else:
				obj.send_addr_data(i,nums[ts[i]])
				flag=False
		else:
			obj.send_addr_data(i,nums[ts[i]])

while(1):
	t=time.localtime(time.time())
	#showinfo(t.tm_hour,t.tm_min)
	h=t.tm_hour
	m=t.tm_min
	obj.send_auto_data((h/10,h%10,m/10,m%10),flag)
	if flag ==False:
		flag=True
	else:
		flag=False
	#ts=t.tm_sec
	time.sleep(0.5)
obj.send_addr_data(0,nums[0])

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于IMX6ULL的电子产品量产工具

参考博客&#xff1a; https://blog.csdn.net/m0_63168877/article/details/138545059一、设计思路 软件框架及目录 二、显示系统 2.1显示管理器框架 2.2DispOpr 结构体 在disp_manager.h这一层抽象出显示结构体 在底层显示模块分配、设置这个结构体&#xff0c;并且向本层…

React 中使用 Redux Toolkit 状态管理

在现代 React 应用程序中&#xff0c;状态管理是一个至关重要的部分。使用 Redux Toolkit 可以简化 Redux 的配置和管理。本文将通过三个文件的示例&#xff0c;详细讲解如何使用 Redux Toolkit 创建和管理一个简单的计数器状态&#xff0c;并通过类比源 store 和根 store 的概…

3、liunx系统网络配置

一、liunx网络配置 Linux服务器网卡默认配置文件在/etc/sysconfig/network-scripts/下&#xff0c;命名的名称一般为:ifcfg-eth0 ifcfg-eth1 &#xff0c;eth0表示第一块网卡&#xff0c;eth1表示第二块网卡&#xff0c;依次类推&#xff0c;例如DELL R720标配有4块千兆网卡&am…

【零售和消费品&存货】快递包裹条形码与二维码识别系统源码&数据集全套:改进yolo11-RFCBAMConv

改进yolo11-RVB等200全套创新点大全&#xff1a;快递包裹条形码与二维码识别系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.11.01 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系统…

牛客网最新Java高频面试题汇总(2024最新含答案)

作为一名优秀的程序员&#xff0c;技术面试都是不可避免的一个环节&#xff0c;一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识。 如果你参加过一些大厂面试&#xff0c;肯定会遇到一些这样的问题&#xff1a; 1、看你项目都用的框架&#xff0c;熟悉…

电科金仓(人大金仓)更新授权文件(致命错误: XX000: License file expired.)

问题:电科金仓(人大金仓)数据库链接异常,重启失败,查看日志如下: 致命错误: XX000: License file expired. 位置: PostmasterMain, postmaster.c:725 解决方法: 一、下载授权文件 根据安装版本在官网下载授权文件(电科金仓-成为世界卓越的数据库产品与服务提供商)…

Hadoop期末复习(完整版)

前言&#xff08;全部为语雀导出&#xff0c;个人所写&#xff0c;仅用于学习&#xff01;&#xff01;&#xff01;&#xff01;&#xff09; 复习之前我们要有目的性&#xff0c;明确考什么&#xff0c;不考什么。 对于hadoop来说&#xff0c;首先理论方面是跑不掉的&#x…

河北冠益荣信科技公司洞庭变电站工程低压备自投装置的应用

摘 要&#xff1a;随着电力需求增长&#xff0c;供电可靠性变得至关重要&#xff0c;许多系统已有多回路供电。备用电源自动投入装置能提升供电可靠性&#xff0c;它能在主电源故障时迅速切换到备用电源。本文介绍的AM5-DB低压备自投装置&#xff0c;为洞庭变电站提供多种供电方…

Spring Boot:打造动态定时任务,开启灵活调度之旅

一、描述 在 Spring Boot 中设置动态定时任务是一种非常实用的功能&#xff0c;可以根据实际需求在运行时动态地调整定时任务的执行时间、频率等参数。以下是对 Spring Boot 设置动态定时任务的简单介绍&#xff1a; 1、传统定时任务的局限性 在传统的 Spring Boot 定时任务…

Lua 从基础入门到精通(非常详细)

目录 什么是 Lua&#xff1f; Lua 环境安装 Lua基本语法 注释 数据类型 nil&#xff08;空&#xff09; Boolean number&#xff08;数字&#xff09; string&#xff08;字符串&#xff09; function&#xff08;函数&#xff09; userdata thread table&#xff…

PostgreSQL 到 PostgreSQL 数据迁移同步

简述 PostgreSQL 是一个历史悠久且广泛使用的数据库&#xff0c;不仅具备标准的关系型数据库能力&#xff0c;还具有相当不错的复杂 SQL 执行能力。用户常常会将 PostgreSQL 应用于在线事务型业务&#xff0c;以及部分数据分析工作&#xff0c;所以 PostgreSQL 到 PostgreSQL …

GESP4级考试语法知识(捕捉异常)

参考程序代码&#xff1a; #include <iostream> using namespace std;double divide(double a, double b) {if (b 0) {throw "Division by zero error"; // 抛出异常}return a / b; }int main() {double num1, num2;cout << "Enter two numbers:…

新老项目不同node版本,使用nvm控制node版本切换(mac、window)

window系统电脑的链接&#xff1a;https://blog.csdn.net/qq_40269801/article/details/136450961 以下是mac版本的操作方式&#xff1a; 1、打开终端 克隆 NVM 仓库&#xff1a; git clone https://github.com/nvm-sh/nvm.git ~/.nvm 2、运行安装脚本&#xff1a; cd ~/.n…

HTTP与HTTPS协议

HTTP协议&#xff0c;即超文本传输协议&#xff08;HyperText Transfer Protocol&#xff09;&#xff0c;是互联网中一种用于在Web浏览器与Web服务器之间传输数据的应用层协议。它的核心理念是提供一种简单、灵活的方式来请求和响应信息&#xff0c;是现代万维网的基础。 1. 什…

R语言机器学习与临床预测模型79--机器学习总览

R小盐准备介绍R语言机器学习与预测模型的学习笔记 你想要的R语言学习资料都在这里&#xff0c; 快来收藏关注【科研私家菜】 01 机器学习分类 机器学习模型主要分为有监督、无监督和强化学习方法。 监督学习 监督学习是教师向学生提供关于他们在考试中是否表现良好的反馈。其中…

Diving into the STM32 HAL-----HAL_GPIO

1、怎么看待外设&#xff1a; 从总线连接的角度看&#xff0c;外设和Core、DMA通过总线交换数据&#xff0c;正所谓要想富先修路。要注意&#xff0c;这些总线中的每一个都连接到不同的时钟源&#xff0c;这些时钟源决定了连接到该总线的外设操作的最大速度。 从内存分配的角度…

FlinkCDC-MYSQL批量写入

一、运行环境 &#xff08;1&#xff09;Flink&#xff1a;1.17.2 &#xff08;2&#xff09;Scala&#xff1a;2.12.20 &#xff08;3&#xff09;Mysql&#xff1a;5.7.43 ##开启binlog 二、代码示例 思路&#xff1a;通过滚动窗口收集一批数据推给sink消费。binlog日志对…

集合(数组、链表、map)

目录 Collection包结构 和collections区别 List 数组和arrayList 区别 数组下标为什么从0开始&#xff1f; ArrayList 动态数组 LinkedList双向链表增删快 增删快 链表 单链表和双链表区别 Arraylist VS LinkedList 区别 数组和List之间转换 ArrayList 、LinkedList…

多线程和线程同步基础篇学习笔记(Linux)

大丙老师教学视频&#xff1a;10-线程死锁_哔哩哔哩_bilibili 目录 大丙老师教学视频&#xff1a;10-线程死锁_哔哩哔哩_bilibili 线程概念 为什么要有线程 线程和进程的区别 在处理多任务的时候为什么线程数量不是越多越好? Linux提供的线程API 主要接口 线程创建 pth…

希望十一月对我好一点:C++之多态(2)--多态的原理(部分)

多态的原理 虚函数表指针 下⾯编译为32位程序的运⾏结果是什么&#xff08;&#xff09; A. 编译报错 B.运⾏报错C.8 D.12 class Base{public:virtual void Func1(){cout << "Func1()" << endl;}protected:int _b 1;char _ch x;};int main(){Base b…