MAX7219为例的spi通讯协议

一、代码

其中.h文件内容为

#ifndef __MAX7219_H__
#define __MAX7219_H__

#include <STC89C5xRC.H>
#include "typedef.h"

//user set define
#define MAX7219_NUMBER	4	//超过255需要更换函数中i和j的数据类型
#define MAX7219_LINE	2
#define MAX7219_COLUMN	16

#define MAX7219_DISNUM	MAX7219_NUMBER * 8

//接口定义
#define MAX7219_CS		P16
#define MAX7219_CLK		P15
#define MAX7219_DAT		P17

extern data u8 displayBuffer[MAX7219_DISNUM];

void MAX7219_init(void);

#endif

.c文件中的内容为

#include "max7219.h"

data u8 displayBuffer[MAX7219_DISNUM] = {0x00};


#define MAX7219_SHUTDOWN			0x0C	//停机模式,0x00关闭,0x01开启
#define MAX7219_DECODE				0x09	//译码方式,0x00不译码
#define MAX7219_INTENSITY			0x0A	//亮度设置,最低0x01,最高0x0F
#define MAX7219_SCAN				0x0B	//扫描界限,不扫描0x00,全扫描0x07
#define MAX7219_TEST				0x0F	//测试模式,0x00关闭测试,0x01开启测试

//数据显示地址
code u8 max7219_digit[8] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08};

/**
 * 开锁
 */
void MAX7219_unlock(void)
{
	//开启使能
	MAX7219_CS = 0;
}

/**
 * 关锁
 */
void MAX7219_lock(void)
{
	//关闭使能
	MAX7219_CS = 1;
}

/**
 * max7219发送数据
 * @param add 地址
 * @param dat 数据
 */
void MAX7219_sendData(u8 add, u8 dat)
{
	u8 i;
	
	//发送地址
	for (i = 0; i < 8; i++) {
		MAX7219_CLK = 0;
		MAX7219_DAT = add & 0x80;
		add <<= 1;
		MAX7219_CLK = 1;
	}
	//发送数据
	for(i = 0; i < 8; i++) {
		MAX7219_CLK = 0;
		MAX7219_DAT = (bit)(dat & 0x80);
		dat <<= 1;
		MAX7219_CLK = 1;
	}
}

二、解析

1. H文件

1. 首先是max7219.h文件中的内容#include "typedef.h"可以替换为typedef unsigned char u8;。这里主要是为了定义变量时少打字。

2. 这里的定义方法类似于oled点阵屏,方便后面写程序。如果是16行16列的话,后面处理8位数据太麻烦了。

 3. 以下是接口定义,用户可以自己更改。

 4. 函数引用

5. 其他部分暂时用不到,暂不介绍。

2. C文件

(1)基本理论

1. 宏定义部分是初始化时用到的,暂不介绍

2. spi协议共有三个接口,一个是使能(CS),一个是时钟信号(CLK),一个是数据信号(DATA)。

3. 使能信号:

        使能信号时主机(51单片机)控制从机(max7219)的。当使能信号为低电平(0)时,就是主机告诉从机,我发的信号你给我好好接收,要是有半点闪失,那我就重新发一次。

        当使能信号为高电平(1)时,主机就告诉从机,接下来的场景不是你可以承受的,把耳朵堵住,眼睛蒙起来,不管发生什么,你都装作没看见,你要是不小心看见了,那你就遭老罪咯。

4.时钟信号:

        时钟信号只在上升沿时把数据传入,什么是上升沿呢,就是低电平向高电平跳变的时候。在那一瞬间,从机心动了一下,血脉喷张,小脸一红,于是就把主机发来的数据记在了心里,当然从机脑子有限,一共只能记住16个1bit(1或者0)的数据。

5. 数据信号:

        数据信号的改变建议在时钟信号为低电平时进行,比如你要发送1,那就在时钟信号是低电平的时候将数据信号置为1,发送0同理。这样在数据信号调整好之后,只需要等待时钟信号心动(低电平向高电平跳变)就可以了。

        如果你比较倔强,非要在时钟信号为高电平时设置数据信号,当然,也是可以的,但是你需要先等时钟信号平复一下心情(设置为低电平),然后再让她砰然心动(时钟信号由低向高跳变),这种方式有个好处,写代码的时候时钟信号的处理都在一起,有错误能及时发现。

6. 时序图看看就行了,因为51单片机在12MHz晶振时是1us一条指令,速度太慢,所以不用关注max7219接收数据的极限速度(也就是tcsw,tldck这些数据),至于DOUT部分,后面再说。

 7. max7219数据格式

        从整体上看,就是一个经典的地址+数据的格式,地址是啥,不重要,数据是啥,也不重要。重要的是,知道了它一共发16个二进制数据,有两种类型,每种类型有8个二进制位。换句话来说,咱就发两次8位数据就OK了,其他的现在咱不用管。

        只要涉及到串行数据传输,就会有一个发送数据时是高位在前还是低位在前的问题,以上图为例,高位在前就是先发D15位的数据,然后D14位......直到D0位。低位在前就是先发D0位然后D1位......直到D15位。

        那怎么进行判断呢,绝大多数情况下看时序图的第一位就可以了,如下图红圈所标识

        第一位不是D0就是高位在前,是D0就是低位在前。

(2)代码实现

在代码实现中,因为是级联操作,所以将使能进行了分离,将其设置为开锁关锁操作。这里不用太纠结,后面实现的时候会慢慢讲解。

数据传输顺序为:使能置低->发送数据->使能置高

所以完整传输一帧数据的调用格式为

MAX7219_unlock();
MAX7219_sendData(MAX7219_SHUTDOWN, 0x00);//关闭显示屏
MAX7219_lock();

 对于发送数据的函数

采用这种发送数据的方式,可以对级联的芯片整体写入,如下图

posted @   一叁五  阅读(45)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!
点击右上角即可分享
微信分享提示