使用STM32的硬件SPI及软件模拟SPI的方式驱动MAX7219点阵

使用STM32的硬件SPI及软件模拟SPI的方式驱动MAX7219点阵

  • 一、max7219.c。
  • 二、max7219.h。
  • 三、main.c
  • 开发板使用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);
    		} 
    	}
    }
    
    物联沃分享整理
    物联沃-IOTWORD物联网 » 使用STM32的硬件SPI及软件模拟SPI的方式驱动MAX7219点阵

    发表评论