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();
对于发送数据的函数
采用这种发送数据的方式,可以对级联的芯片整体写入,如下图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!