使用STM32的硬件SPI及软件模拟SPI的方式驱动MAX7219点阵
目录
使用STM32的硬件SPI及软件模拟SPI的方式驱动MAX7219点阵
使用STM32的硬件SPI及软件模拟SPI的方式驱动MAX7219点阵
开发板使用STM32F103ZET6主控,可使用其自带的硬件SPI或者使用软件模拟SPI的方式驱动MAX7219点阵,显示其他字符可在
code_disp1
中修改字节定义。
一、max7219.c。
在模拟SPI时,函数
Write_Max7219_byte()
中,对
Max7219_pinDIN
的定义不可写成
Max7219_pinDIN = data & 0x80;
实测无效(暂时不知道原因,时钟太快数据处理不过来?在51单片机中可以正常使用),上电点阵无显示或者为全亮状态。使用逻辑分析仪抓取分析,
Max7219_pinDIN
一直是低电平状态,导致MAX7219无数据写入。
#include "max7219.h"
#include "delay.h"
u8 code_disp1[38][8]={
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//0
{0x08,0x18,0x28,0x08,0x08,0x08,0x08,0x3E},//1
{0x7E,0x02,0x02,0x7E,0x40,0x40,0x40,0x7E},//2
{0x3E,0x02,0x02,0x3E,0x02,0x02,0x3E,0x00},//3
{0x08,0x18,0x28,0x48,0xFE,0x08,0x08,0x08},//4
{0x3C,0x20,0x20,0x3C,0x04,0x04,0x3C,0x00},//5
{0x3C,0x20,0x20,0x3C,0x24,0x24,0x3C,0x00},//6
{0x3E,0x22,0x04,0x08,0x08,0x08,0x08,0x08},//7
{0x00,0x3E,0x22,0x22,0x3E,0x22,0x22,0x3E},//8
{0x3E,0x22,0x22,0x3E,0x02,0x02,0x02,0x3E},//9
{0x08,0x14,0x22,0x3E,0x22,0x22,0x22,0x22},//A
{0x3C,0x22,0x22,0x3E,0x22,0x22,0x3C,0x00},//B
{0x3C,0x40,0x40,0x40,0x40,0x40,0x3C,0x00},//C
{0x7C,0x42,0x42,0x42,0x42,0x42,0x7C,0x00},//D
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x7C},//E
{0x7C,0x40,0x40,0x7C,0x40,0x40,0x40,0x40},//F
{0x3C,0x40,0x40,0x40,0x40,0x44,0x44,0x3C},//G
{0x44,0x44,0x44,0x7C,0x44,0x44,0x44,0x44},//H
{0x7C,0x10,0x10,0x10,0x10,0x10,0x10,0x7C},//I
{0x3C,0x08,0x08,0x08,0x08,0x08,0x48,0x30},//J
{0x00,0x24,0x28,0x30,0x20,0x30,0x28,0x24},//K
{0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7C},//L
{0x81,0xC3,0xA5,0x99,0x81,0x81,0x81,0x81},//M
{0x00,0x42,0x62,0x52,0x4A,0x46,0x42,0x00},//N
{0x3C,0x42,0x42,0x42,0x42,0x42,0x42,0x3C},//O
{0x3C,0x22,0x22,0x22,0x3C,0x20,0x20,0x20},//P
{0x1C,0x22,0x22,0x22,0x22,0x26,0x22,0x1D},//Q
{0x3C,0x22,0x22,0x22,0x3C,0x24,0x22,0x21},//R
{0x00,0x1E,0x20,0x20,0x3E,0x02,0x02,0x3C},//S
{0x00,0x3E,0x08,0x08,0x08,0x08,0x08,0x08},//T
{0x42,0x42,0x42,0x42,0x42,0x42,0x22,0x1C},//U
{0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18},//V
{0x00,0x49,0x49,0x49,0x49,0x2A,0x1C,0x00},//W
{0x81,0x42,0x24,0x18,0x18,0x24,0x42,0x81},//X
{0x41,0x22,0x14,0x08,0x08,0x08,0x08,0x08},//Y
{0x00,0x7F,0x02,0x04,0x08,0x10,0x20,0x7F},//Z
{0x08,0x7F,0x49,0x49,0x7F,0x08,0x08,0x08},//中
{0xFE,0xBA,0x92,0xBA,0x92,0x9A,0xBA,0xFE},//国
};
#if SPI_IS_HARDWARE //判断 SPI 方式
void Max7219_GPIO_Init(void) //硬件 SPI
{
SPI_InitTypeDef SPI1_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
//配置 SPI1 管脚
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1,ENABLE);
GPIO_InitStructure.GPIO_Pin=Max7219_pinCS_GPIO;//CS/LOAD
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin=Max7219_pinCLK_GPIO|SPI_MISO_GPIO|Max7219_pinDIN_GPIO;//CLK MISO MOSI
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;
GPIO_Init(GPIOA,&GPIO_InitStructure);
SPI1_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
SPI1_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_64;
SPI1_InitStructure.SPI_DataSize=SPI_DataSize_8b;
SPI1_InitStructure.SPI_Mode=SPI_Mode_Master;
SPI1_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB; //高位在先
SPI1_InitStructure.SPI_CPOL = SPI_CPOL_High;
SPI1_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
SPI1_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI1_InitStructure.SPI_CRCPolynomial = 7;
SPI_I2S_DeInit(SPI1);
SPI_Init(SPI1, &SPI1_InitStructure);
SPI_Cmd(SPI1, ENABLE);
}
//功能:向 MAX7219 内部寄存器写入数据
//参数:addr、dat
void Write_Max7219(u8 addr,u8 dat)
{
Max7219_pinCS = 0;
SPI_I2S_SendData(SPI1, addr); //写入地址
delay_us(10);//必须,点阵不显示时可以延长此延时调试
SPI_I2S_SendData(SPI1, dat); //写入数据
delay_us(10);//必须,点阵不显示时可以延长此延时调试
Max7219_pinCS = 1;
}
#else
void Max7219_GPIO_Init(void)//软件模拟 SPI
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Pin = Max7219_pinCS_GPIO | Max7219_pinDIN_GPIO | Max7219_pinCLK_GPIO;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
}
//功能:向 MAX7219 写入字节
//入口参数:data
void Write_Max7219_byte(u8 data)
{
u8 i;
Max7219_pinCS = 0;
for(i = 0;i<8;i++)
{
Max7219_pinCLK = 0;
if((data & 0x80) == 0)//写成 Max7219_pinDIN = data & 0x80;实测无效,Max7219_pinDIN 一直是低电平
{
Max7219_pinDIN = 0;
}
else
{
Max7219_pinDIN = 1;
}
data = data<<1;
Max7219_pinCLK = 1;
}
}
//功能:向 MAX7219 内部寄存器写入数据
//参数:addr、dat
void Write_Max7219(u8 addr,u8 dat)
{
Max7219_pinCS = 0;
Write_Max7219_byte(addr); //写入地址
//delay_us(10);//模拟 SPI 时可以去除
Write_Max7219_byte(dat); //写入数据
//delay_us(10);
Max7219_pinCS = 1;
}
#endif
void Init_MAX7219(void)
{
Write_Max7219(0x09, 0x00); //译码方式:无
Write_Max7219(0x0a, 0x03); //亮度
Write_Max7219(0x0b, 0x07); //扫描界限;8 个数码管显示
Write_Max7219(0x0c, 0x01); //掉电模式:0,普通模式:1
Write_Max7219(0x0f, 0x00); //显示测试:1;测试结束,正常显示:0
}
二、max7219.h。
根据实际需求修改函数,修改定义
SPI_IS_HARDWARE
,确定使用硬件 SPI 或者软件模拟 SPI。本 max7219 库文件中,使用的软、硬件 SPI 引脚为同一引脚,所以在不改变引脚的情况下,可定义
SPI_IS_HARDWARE
自主选择 SPI 方式。
#ifndef **MAX7219_H
#define **MAX7219_H
#include "stm32f10x.h"
#include "sys.h"
#define SPI_IS_HARDWARE 1 //1:硬件 SPI;0:软件模拟 SPI
#define Max7219_pinDIN_GPIO GPIO_Pin_7
#define Max7219_pinCS_GPIO GPIO_Pin_3
#define Max7219_pinCLK_GPIO GPIO_Pin_5
#define SPI_MISO_GPIO GPIO_Pin_6//未使用到
#define Max7219_pinDIN PAout(7)
#define Max7219_pinCS PAout(3)
#define Max7219_pinCLK PAout(5)
void Max7219_GPIO_Init(void);
void Write_Max7219_byte(u8 data);
void Write_Max7219(u8 addr,u8 dat);
void Init_MAX7219(void);
#endif
三、main.c
主函数是对
code_disp1
数组中的字符循环显示,在实际使用当中,如果显示字符变动不频繁可将显示函数写在 while(1)之前,特别是有多个点阵级联情况下。否则会在 while 里循环刷新,级联状况下点阵会有重影(上一级的残影)。
另外在电源突然断开再重新上电情况下,点阵屏不显示,需要手动按下单片机复位按键方可正常显示,测试后在 max7219 初始化和 SPI 初始化之前增加延时可解决,具体延时时长可自行调试。本人使用的是国产 GC7219 驱动芯片(购买时图片上标的是 MAX7219。。。),也有可能是芯片原因,MAX7219 没有试验过,后续有机会验证。
#include "stm32f10x.h"
#include "sys.h"
#include "delay.h"
#include "max7219.h"
extern u8 code_disp1[38][8];
int main(void)
{
u8 i,j;
delay_init();
delay_ms(500);//只能解决短暂掉电后上电点阵不显示问题,否则需要手动按复位
Max7219_GPIO_Init();
delay_ms(500);
Init_MAX7219();
while(1)
{
Max7219_pinCS = 1;
delay_ms(1);
for(j=0;j<38;j++)
{
for(i=1;i<9;i++)
Write_Max7219(i,code_disp1[j][i-1]);
delay_ms(1000);
}
}
}