`
iaiai
  • 浏览: 2147330 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

树莓派 - MAX7219

 
阅读更多
1.基础:认识MAX7219

拿到MAX7219驱动的LED矩阵,第一件事是先连接并尝试显示图案。使用MAX7219除了需要提供GND以及VCC外,只需要再提供三根引脚即可点亮矩阵。其中,DIN引脚输入数据,CS(LOAD)引脚控制数据输入,CLK引脚用于区分每个bit。

MAX的整个写入流程为,首先CS引脚置0,表示允许写入。而后从高位顺序写入16个bit。每个bit的写入方式为首先DIN置为要写入的bit值,而后CLK产生一个下降沿(图中为上升沿,不知道为何有差别)即被读入。最后CS引脚置1表示写入结束。

时序图如下:

在运行之前,需要进行一次初始化,其行为是向某几个特定的地址写入特定的值。至少需要写入两个地址,第一个是0x0b,写入0x07表示扫描显示所有行。第二个是0x0c,写入1表示进入工作模式。

而后点阵上每一行都有其地址,如第一行是0x01到第八行是0x08,每次向固定行的地址写入一个8位二进制数即可在指定行上显示图案。



2.      树莓派对GPIO的访问——虚拟文件系统访问

Linux可以通过访问sys/class/gpio下的一些文件,通过对这些文件的读写来实现对于GPIO的访问。

树莓派下面的可用的GPIO如右图所示,需要注意树莓派一代和二代的区别。

这里根据大大的博客攻略,我首先尝试用shell。代码直接参考了大大的。先试着玩一下。
!/bin/bash

# DIN, CS, CLK的GPIO口位置
DIN=4
CS=3
CLK=2

# 一些文件路径
GPIO_BASE=/sys/class/gpio
GPIO_EXPORT=${GPIO_BASE}/export
GPIO_UNEXPORT=${GPIO_BASE}/unexport

BIN=(00000001 00000010 00000011 00000100 00000101 00000110 00000111 00001000)

# 生成指定GPIO引脚的文件夹位置
function GPIO(){
    echo ${GPIO_BASE}/gpio$1
}

# 将某个引脚export到用户态
function GPIO_export(){
    if [ -d `GPIO $1` ]; then
        echo GPIO pin $1 found in folder.
    else
        echo $1 > ${GPIO_EXPORT}
    fi
}

# unexport某个引脚
function GPIO_unexport(){
    if [ -d `GPIO $1` ]; then
        echo $1 > ${GPIO_UNEXPORT}
    else
        echo GPIO pin $1 not found.
    fi
}

# 改变某个引脚的方向
function GPIO_direction(){
    echo $2 > `GPIO $1`/direction
}

# 改变某个引脚的值
function GPIO_set(){
    echo $2 > `GPIO $1`/value
}

# 改变DIN的值
function GPIO_DIN(){
    GPIO_set $DIN $1
}

# 改变CS的值
function GPIO_CS(){
    GPIO_set $CS $1
}

# 改变CLK的值
function GPIO_CLK(){
    GPIO_set $CLK $1
}

# 向MAX7219发送一个byte的值
function Matrix_send_char(){
    local i=1
    for ((i=1;i<=8;i++)); do
        chr=`expr substr $1 $i 1`
        GPIO_DIN $chr
        GPIO_CLK 1
        GPIO_CLK 0
    done
}

# 向MAX7219发送一次完整的信号
function Matrix_send_word(){
    GPIO_CS 1
    GPIO_CS 0
    GPIO_CLK 0
    Matrix_send_char $1
    Matrix_send_char $2
    GPIO_CS 1
}

# 初始化GPIO引脚
function GPIO_init(){
    GPIO_export $DIN
    GPIO_export $CS
    GPIO_export $CLK

    sleep 2

    GPIO_direction $DIN out
    GPIO_direction $CS out
    GPIO_direction $CLK out
}

# 清除GPIO引脚
function GPIO_clear(){
    GPIO_unexport $DIN
    GPIO_unexport $CS
    GPIO_unexport $CLK
}

# 在点阵上显示数据
function Matrix_render(){
    local i=1
    for ((i=0;i<8;i++)); do
        echo $i $1
        Matrix_send_word ${BIN[$i]} $1
        shift
    done
}

# 使用文件中的数据进行显示
function Matrix_render_file(){
    local tmp=(`cat $1`)
    Matrix_render "${tmp[@]}"
}

# 使用某个图案清屏
function Matrix_clear(){
    local STR=(
        00000000
        01100110
        11111111
        11111111
        11111111
        01111110
        00111100
        00011000
    )
    Matrix_render "${STR[@]}"
}

# 初始化点阵
function Matrix_init(){
    # 编码模式
    Matrix_send_word 00001001 00000000
    # 亮度
    Matrix_send_word 00001010 00000011
    # 扫描数码管个数
    Matrix_send_word 00001011 00000111
    # 工作模式
    Matrix_send_word 00001100 00000001

    # 初始化完毕后清屏显示默认图案
    Matrix_clear
}


在终端中:
source matrix.sh  
GPIO_init  
Matrix_init  

效果如图:

3.      树莓派对GPIO的访问——使用库

这里我使用了wiring库,非常容易上手。关键函数:digitalWrite()写GPIO;pinMode()设置GPIO方向;

需要注意的是它的管脚编号和树莓派不同。

上代码:
#include <wiringPi.h>
#include <stdio.h>

#define uchar unsigned char
#define uint unsigned int

#define DecodeMode      0x09  //译码模式寄存器
#define Intensity       0x0a  //亮度寄存器
#define ScanLimit       0x0b  //扫描位数寄存器
#define ShutDown        0x0c  //低功耗模式寄存器
#define DisplayTest     0x0f  //显示测试寄存器

#define ShutdownMode    0x00  //低功耗方式
#define NormalOperation 0x01  //正常操作方式
#define ScanDigit       0x07  //扫描位数设置,显示8位数码管
#define DecodeDigit     0x00  //译码设置,8位均为非译码
#define IntensityGrade  0x0a  //亮度级别设置
#define TestMode        0x01  //显示测试模式
#define TextEnd         0x00  //显示测试结束,恢复正常工作模式

#define DIN 8
#define CS 9
#define CLK 7

uchar buffer[8]={0x00,0x66,0xff,0xff,0xff,0xff,0x7e,0x3c,0x18};
void delay(uint t){
	uint i;
	while(t--)
		for (i = 0; i < 125; i++);
}

void sendChar(char ch){
	char i, tmp;
	for(i = 0; i < 8; i++){
		tmp = ch & 0x80;
		
		if(tmp) 
			digitalWrite(DIN, HIGH);
		else 
			digitalWrite(DIN, LOW);
		ch = ch << 1;
		digitalWrite(CLK, HIGH:);
		digitalWrite(CLK, LOW);
	}
}

void writeWord(char addr, char num){
	digitalWrite(CS, HIGH);
	digitalWrite(CS, LOW);
	digitalWrite(CLK, LOW);
	sendChar(addr);
	sendChar(num);
	digitalWrite(CS, HIGH);
}

void write(){
	char i;
	for(i = 0; i < 8; i++){
		printf("%d %d\n",i, buffer[i]);
		writeWord(i + 1, buffer[i]);
	}
}

void init(){
	writeWord(0x09, 0x00);
	writeWord(0x0a, 0x03);
	writeWord(0x0b, 0x07);
	writeWord(0x0c, 0x01);
}


int main(){
	wiringPiSetup();

	pinMode(DIN, OUTPUT);
	pinMode(CS, OUTPUT);
	pinMode(CLK, OUTPUT);

	init();
	wirte();


	return 0;

}

Makefile:
matrix:matrix.o    
      gcc matrix.c -o matrix -lwiringPi    
clean:    
      rm -f matrix matrix.o

结果和前面一样。LED矩阵上显示了爱心。

把上面代码改为python
#!/usr/bin/env python
# encoding: utf-8

import RPi.GPIO as GPIO
import time

DIN = 12
CS = 16
CLK = 18

GPIO.setmode(GPIO.BOARD)
GPIO.setup(DIN,GPIO.OUT)
GPIO.setup(CS,GPIO.OUT)
GPIO.setup(CLK,GPIO.OUT)

buffer = ['00000000','01100110','11111111','11111111','11111111','01111110','00111100','00011000']
#buffer = [0x00,0x66,0xff,0xff,0xff,0x7e,0x3c,0x18]

def send(byteData):
    for bit in range(0,8):
        if(byteData & 0x80):
            GPIO.output(DIN,True)
        else:
            GPIO.output(DIN,False)
        byteData = byteData<<1
        GPIO.output(CLK,True)
        GPIO.output(CLK,False)

def writeWord(addr,num):
    GPIO.output(CS,True)
    GPIO.output(CS,False)
    GPIO.output(CLK,False)
    send(addr)
    send(num)
    GPIO.output(CS,True)

def wt():
    for i in range(0,8):
        print("%d %d" %(i,int(buffer[i],2)))
        writeWord(i+1,int(buffer[i],2))

def initData():
    writeWord(0x09,0x00)
    writeWord(0x0a,0x03)
    writeWord(0x0b,0x07)
    writeWord(0x0c,0x01)
    writeWord(0xff,0x00)

try:
    initData()
    wt()
except KeyboardInterrupt:
    pass

time.sleep(2)
GPIO.cleanup()
  • 大小: 75.6 KB
  • 大小: 129.7 KB
  • 大小: 506.6 KB
  • 大小: 283.1 KB
分享到:
评论
1 楼 liangzai_cool 2019-04-01  
请教一下,文中,shell、C、Python三种方式控制led点阵,对应的树莓派版本分别是多少呢?

相关推荐

Global site tag (gtag.js) - Google Analytics