第二个树莓派应用——LED点阵

1,655 阅读8分钟

前言

上篇文章已经学会应用了GPIO接口,后续树莓派应用就是分模块去学习,应用什么模块去看什么模块的文档。 这次我们来点亮8*8的LED点阵。

项目需求

共阴极8*8点阵(选用的驱动芯片是max7219) 这次是在某宝上面选用的现成的电路,当然你想要锻炼动手能力也是可以自己买led自己焊接的。 其他硬件需求跟第一篇文章 一样 软件方面跟之前相同

硬件连接

在某宝买的硬件主要有三个IO口控制,如图所示:

93a1deb4ab9b95de7f7e68173f9fb24.jpg

从实物来看左侧五个引脚是控制点阵的,右侧引脚是用来扩展的,本次项目就使用一个8*8点阵,所以就看左侧引脚就足够了。左侧五个引脚从上到下分别是VCC,GND,DIN,CS,CLK。其中VCC就是5V电源端,连接树莓派上面的5V电源端就行,GND就是接地端,与树莓派上面的接地端相连接,剩下三个就是串口控制端,CS DIN CLK,这就要研究下max7219芯片了,本文对其原理就不多做介绍了,主要介绍软件相关的: CS口主要是控制串口通讯的,低电平串行数据才被载入寄存器,高电平时会被锁存。DIN 通过高低电平传入数据 CLK 时钟序列,上升沿时DIN传入数据有效,即低电平变化成高电平时有效

软件方面

初始化接口

点钟模块总共三个io口,首先导入必要模块,初始化三个io口设置为输出模式。

import RPi.GPIO as GPIO    #先要导入模块

import time


GPIO.setmode(GPIO.BCM)      #选择 GPIO numbers 编号系统
GPIO.setwarnings(False)
DIN = 16
CS = 20
CLK = 21
GPIO.setup(DIN, GPIO.OUT)     
GPIO.setup(CS, GPIO.OUT)     
GPIO.setup(CLK, GPIO.OUT)   

写入数据方法

写入一直接数据

首先要写入数据通过上面芯片的描述可以看到DIN是数据的串行输入端,而且DIN的数据仅在CLK处于上升沿的时候有效,所以首先要给CLK创建一个上升沿,然后DIN输入数据。

def setBitData(data):
    GPIO.output(CLK, False) // 设置低电平
    GPIO.output(DIN, data)  // 输入数据,data为布尔类型 01
    GPIO.output(CLK, True)  // 设置高电平,产生上升沿,DIN输入数据生效

将十六进制数写入

由于芯片中的寄存器都是十六进制表示,所以我们要将十六进制逐位写入到寄存器中,传入的十六进制数字从高位到低位依次判断是否为1,若为1则设置高电平,否则设置低电平,判断的方法是先向左移位,把要判断的位移动到最高位然后跟0x80(1000 0000)相与,如果结果仍然是0x80(1000 0000)就表示最高位是1,否则最高位就是0

def Write_Max7219_byte(byteData):
    for bit in range(0, 8): // 从08位移
        if ((byteData << bit) & 0x80 == 0x80): // 位移后与0x80按位与,除最高位之外置零,再与0x80相比判断最高位是否为1
            setBitData(True) // 最高位为1写入高电平
        else:
            setBitData(False) // 最高位为0写入低电平

max7219写入数据方法

通过上述描述可以知道CS端控制着数据写入,写入数据时首先要将CS口置为低电平传入数据才有效,高电平则锁存。然后传入寄存器地址与数据。

def Write_Max7219(address,data):
    GPIO.output(CS, False) // 设置低电平 ,开始传入数据
    Write_Max7219_byte(address) // 传入寄存器地址
    Write_Max7219_byte(data) // 传入数据
    GPIO.output(CS, True) // 写入完毕,设置高电平,锁存

内置寄存器介绍

通过查阅max7219的datesheet可以发现,max7219芯片内不同的地址存储的值都有相应的作用。

0x01-0x08对应的是led 1到8行的显示通过8位二进制数来控制这一行led的显示状况,0 led熄灭,1 led点亮。 比如说 0x3C 转换成二进制就是 00111100 ,该行的led的显示模式就是 ○○●●●●●○○

  • 0x09 译码模式寄存器 00 0 关闭译码模式
  • 0x0b 扫描限制寄存器 07 设置扫描led的行数 1-8
  • 0x0a 亮度调节寄存器 07 16位调节亮度
  • 0x0c 关断模式寄存器 01 0 关断状态 1 正常操作状态
  • 0x0f 显示测试寄存器 00 0正常模式 1 测试模式 全部点亮

初始化程序

初始化内部寄存器,设置相应的值。

def Init_MAX7219():
    Write_Max7219(0x09, 0x00) // 关闭译码模式
    Write_Max7219(0x0a, 0x03) // 设置led亮度
    Write_Max7219(0x0b, 0x07) // 设置扫描行数
    Write_Max7219(0x0c, 0x01) // 设置正常模式
    Write_Max7219(0x0f, 0x00) // 设置正常模式

定义显示相应的数字

通过led点阵显示相应的图形,这里我已经设置的一些图形的显示相应的十六进制数。

// 仅做对应的提示
characters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9','A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J','K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T','U', 'V', 'W', 'X', 'Y', 'Z', ' ']
// 相应的十六进制数
disp1 = [
    [0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C],
    [0x10,0x30,0x50,0x10,0x10,0x10,0x10,0x7C],
    [0x3E,0x02,0x02,0x3E,0x20,0x20,0x3E,0x00],
    [0x00,0x7C,0x04,0x04,0x7C,0x04,0x04,0x7C],
    [0x08,0x18,0x28,0x48,0xFE,0x08,0x08,0x08],
    [0x3C,0x20,0x20,0x3C,0x04,0x04,0x3C,0x00],
    [0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x00],
    [0x3E,0x22,0x04,0x08,0x08,0x08,0x08,0x08],
    [0x00,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E],
    [0x3E,0x22,0x22,0x3E,0x02,0x02,0x02,0x3E],
    [0x08,0x14,0x22,0x3E,0x22,0x22,0x22,0x22],
    [0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x00],
    [0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x00],
    [0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x00],
    [0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C],
    [0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40],
    [0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C],
    [0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44],
    [0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C],
    [0x3C,0x08,0x08,0x08,0x08,0x08,0x48,0x30],
    [0x00,0x24,0x28,0x30,0x20,0x30,0x28,0x24],
    [0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C],
    [0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81],
    [0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x00],
    [0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C],
    [0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20],
    [0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D],
    [0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21],
    [0x00,0x1E,0x20,0x20,0x3E,0x02,0x02,0x3C],
    [0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08],
    [0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C],
    [0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18],
    [0x00,0x49,0x49,0x49,0x49,0x2A,0x1C,0x00],
    [0x00,0x41,0x22,0x14,0x08,0x14,0x22,0x41],
    [0x41,0x22,0x14,0x08,0x08,0x08,0x08,0x08],
    [0x00,0x7F,0x02,0x04,0x08,0x10,0x20,0x7F],
    [0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00],
]

通过循环显示相应的符号

def led_print(char1): // led逐行写入数据
    for i in range(0,8): // 8行的led显示数据,逐行写入
        Write_Max7219(i+1,disp1[char1][i])  
        
Init_MAX7219() // 初始化芯片

for i in range(0,30): // 循环显示所有的字符
    led_print(i) 
    time.sleep(.5) // 延迟显示后切换下一个符号显示

 
GPIO.cleanup()