max7219共阴极数码管驱动 stm32 hal

因为做这个需要用到max7219,所以在网上找了一些前车之鉴。和以前找其他资料一样,我认为他们写的真的不好,甚至都辣眼睛,更有甚者上来就放两句话,最后一句是我实现了,倒不如发

目录

    • 目的
      • 步骤
        • max7219资料解读
          • 功能概述
        • stm32 参数配置
        • 驱动实现

目的

实现max7219驱动数码管显示

步骤

  • max7219资料解读
  • stm32 参数配置
  • 驱动实现

max7219资料解读

此部分只摘取官方文档部分内容。我认为足够使用了

  • max7219 与stm32通信方式
    max7219通信方式为SPI,16bit 数据格式,先发高位,最大10MHz (圈重点)
    max7219共阴极数码管驱动 stm32 hal_第1张图片
  • max7219 控制方式
    spi一次发送16bit,就是2字节 = 地址 + 数据 。地址代表着不同的功能,数据代表想设置的参数。按需要直接到地址的表查,然后按照地址的功能设置数据。初次上电时进入的是shutdown模式

下图寄存器表就是地址

max7219共阴极数码管驱动 stm32 hal_第2张图片
ditgit 代表要控制哪个数据管,max7219可以控制0 - 7个数码管,矩阵led这里不说了。实现步骤就是,想控制的 数码管地址 + 想要显示的数据(可以通过decode mode 设置BCD解码或者不解码)

功能概述
  • 解码模式 支持BCD解码,或者直接显示某个单独的线端
  • 亮度设置
  • 扫描限制 就是用几个数码管,数量小于等于三个时必须进行电流设置(请查手册)
  • 掉电模式 为了省电,掉电时候只是不显示而已,还是可以进行设置操作,初次上电也是处于这个模式
  • 显示测试 就是测试能不能都亮,或者正常的模式(自己设定的想让哪个亮的模式)

功能描述表
max7219共阴极数码管驱动 stm32 hal_第3张图片
max7219共阴极数码管驱动 stm32 hal_第4张图片
max7219共阴极数码管驱动 stm32 hal_第5张图片
max7219共阴极数码管驱动 stm32 hal_第6张图片

stm32 参数配置

max7219共阴极数码管驱动 stm32 hal_第7张图片
重点注意红框部分 硬件NSS不要使用,因为这个是你想的不是一个东西。速率不能超过10Mhz,差不多就行了,显示几个数字哪怕设置为最慢也是没问题的。

驱动实现

static int max7219_send(uint8_t address,uint8_t data)
{
    uint16_t Transmit_buf = (0x00ff&data)|(0xff00&(address<<8));
    
    HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port,SPI1_NSS_Pin,GPIO_PIN_RESET);
    HAL_SPI_Transmit(&MAX7219_SPI,(uint8_t*)&Transmit_buf,1,3000);
    HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port,SPI1_NSS_Pin,GPIO_PIN_SET);
    
    return 0;
}
char tem[2] = {0x01,0x02};

只需要进行发送即可,注意!16bit,先发高字节,假如使用数组tem 将先发送0x02,发送的字节1代表着sizeof(uint16_t)= 2字节
代码如下,使用面向对象的抽象思想

/**
  ******************************************************************************
  * File Name          : max7219.h
  * Description        : This file provides code for the configuration
  *                      of the max7219 instances.
  ******************************************************************************
  * @attention
  ******************************************************************************
  */

#ifndef __MAX7219_H
#define __MAX7219_H
#ifdef __cplusplus
 extern "C" {
#endif

/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* address define */
#define NO_OP              0x00
#define DIGIT0             0x01
#define DIGIT1             0x02
#define DIGIT2             0x03
#define DIGIT3             0x04
#define DIGIT4             0x05
#define DIGIT5             0x06
#define DIGIT6             0x07
#define DIGIT7             0x08
#define DECODE_MODE        0x09
#define INTENSITY          0x0A
#define SCAN_LIMIT         0x0B
#define SHUT_DOWN          0x0C
#define DISPLAY_TEST       0x0F
/* mode define */
#define NORMAL_MODE           0
#define NO_DECODE_D0_D7    0x00
#define DECODE_D0_ONLY     0x01
#define DECODE_D0_D3_ONLY  0x0F
#define DECODE_D0_D7       0xFF

/*
 *   AAAAAA\      
 *  FF  __BB\     
 *  FF /  BB |    
 *   GGGGGG  |    
 *  EE  __CC<     
 *  EE /  CC |    
 *  \DDDDDD  |  DP\ 
 *   \______/   \__|
 *  
 *    数码管
 */
#define Segment_Line_DP    (1<<7)
#define Segment_Line_A     (1<<6)
#define Segment_Line_B     (1<<5)
#define Segment_Line_C     (1<<4)
#define Segment_Line_D     (1<<3)
#define Segment_Line_E     (1<<2)
#define Segment_Line_F     (1<<1)
#define Segment_Line_G     (1<<0)

/*
 * flash_user_start_addr 数据开始的地址
 * Data                  数据
 * flash_user_size       数据长度
 */
typedef struct
{
    int (*max7219_api_find)(uint8_t* mode);
    int (*max7219_api)(uint8_t mode);
    int (*max7219_digit)(uint8_t digit,uint8_t data);
} max7219TypeDef;

extern max7219TypeDef max7219_api;

#ifdef __cplusplus
}
#endif
#endif /*__ max7219_H */

#include "max7219.h"
#include "spi.h"
#include "stdio.h"
#include "string.h"
#include "tos_k.h"

/* 配置主函数log功能*/
#define MAX7219_LOG_ENABLE

#ifdef MAX7219_LOG_ENABLE
#define MAX7219_LOG(...) \
do{\
	printf(__VA_ARGS__);\
    printf("\r\n");\
  } while (0)
#else
#define MAX7219_LOG(...)
#endif
  
#define MAX7219_SPI hspi1

static const uint8_t to_ascii_tab[][2] = {
    'A', 0x77,  '=',0x09,
    'B', 0x1F,  '-',0x01,
    'C', 0x4E,  '+',0x31,
    'D', 0x3D,  '(',0x4E,
    'E', 0x4f,  ')',0x78,
    'F', 0x47,  0,  0,
    'G', 0x5e,
    'H', 0x37,
    'I', 0x78,
    'J', 0x38,
    'K', 0x57,
    'L', 0x0e,
    'M', 0x76,
    'N', 0x15,
    'O', 0x1d,
    'P', 0x67,
    'Q', 0x73,
    'R', 0x46,
    'S', 0x49,
    'T', 0x0f,
    'U', 0x3e,
    'V', 0x1c,
    'W', 0x3f,
    'X', 0x13,
    'Y', 0x3b,
    'Z', 0x2d,
};
  
static int max7219_send(uint8_t address,uint8_t data)
{
    uint16_t Transmit_buf = (0x00ff&data)|(0xff00&(address<<8));
    
    HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port,SPI1_NSS_Pin,GPIO_PIN_RESET);
    HAL_SPI_Transmit(&MAX7219_SPI,(uint8_t*)&Transmit_buf,1,3000);
    HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port,SPI1_NSS_Pin,GPIO_PIN_SET);
    
    return 0;
}

/* 掉电模式 
 * mode:
 * NORMAL_MODE 0 -> 正常模式
 *             1 -> 掉电模式
 */
int max7219_shutdown(uint8_t mode)
{
    max7219_send(SHUT_DOWN,mode == NORMAL_MODE?1:0);
    return 0;
}

/* 译码器模式 
 * mode:
 *  NO_DECODE_D0_D7    0x00 -> 不译码模式
 *  DECODE_D0_ONLY     0x01 -> digits 0   译码 7-1 不译码
 *  DECODE_D0_D3_ONLY  0x0F -> digits 3-0 译码 7-4 不译码
 *  DECODE_D0_D7       0xFF -> digits 7-0 译码
 */
int max7219_decode_mode(uint8_t mode)
{
    max7219_send(DECODE_MODE,mode);
    return 0;
}

/* 亮度控制 
 * mode:0x00-0x0f
 */
int max7219_intensity(uint8_t mode)
{
    max7219_send(INTENSITY,mode&0x0f);
    return 0;
}

/* 扫描控制 
 * mode:0-7 digits 0 - 7
 */
int max7219_scan_limit(uint8_t mode)
{
    max7219_send(SCAN_LIMIT,mode&0x07);
    return 0;
}

/* digits显示 
 *  digit -> 显示位置'0'-'7'
 *  data  -> 显示的数据 
 * note :
 *          字符直接显示,不需要查手册 data|Segment_Line_DP
 *          带小数点时最高位为1 ->0x80 + x
 */
int max7219_digit(uint8_t digit,uint8_t data)
{
    uint8_t tem = data&0x7f;
    if ((tem >= '0' && tem <= '9'))
    {
        tem = data - '0';
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(DECODE_D0_D7);
    }
    else if(tem == '-')
    {
        tem = 0x0A;
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(DECODE_D0_D7);
    }
    else if(tem == 'E')
    {
        tem = 0x0B;
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(DECODE_D0_D7);
    }
    else if(tem == 'H')
    {
        tem = 0x0C;
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(DECODE_D0_D7);
    }
    else if(tem == 'L')
    {
        tem = 0x0D;
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(DECODE_D0_D7);
    }
    else if(tem == 'P')
    {
        tem = 0x0E;
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(DECODE_D0_D7);
    }
    else if(tem == ' ')
    {
        tem = 0x0F;
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(DECODE_D0_D7);
    }
    else
    {
//        tem = data&0x7f;
        for(int i = 0;i < sizeof(to_ascii_tab)/2;i++)
        {
            if (tem == to_ascii_tab[i][0])
            {
                tem = to_ascii_tab[i][1];
                break;
            }
        }
//        tem |= data&(Segment_Line_DP);
        
        max7219_api.max7219_api_find((uint8_t*)"decode");
        max7219_api.max7219_api(NO_DECODE_D0_D7);
    }
    tos_task_delay(50);
    max7219_send(digit-'0' + 1,tem|(data&(Segment_Line_DP)));//这里加 1 因为1对应digit0
    tos_task_delay(10);
    return 0;
}

/* 显示检测 
 * mode:
 *  0 -> 正常模式
 *  1 -> 测试全部显示
 */
int max7219_test(uint8_t mode)
{
    max7219_send(DISPLAY_TEST,mode == NORMAL_MODE?0:1);
    return 0;
}

/* 设置api */
int max7219_api_find(uint8_t* mode)
{
    max7219_api.max7219_api = NULL;
    if (!strcmp((char*)mode,"shutdown"))
    {
        max7219_api.max7219_api = max7219_shutdown;
    }
    else if(!strcmp((char*)mode,"scan"))
    {
        max7219_api.max7219_api = max7219_scan_limit;
    }
    else if(!strcmp((char*)mode,"test"))
    {
        max7219_api.max7219_api = max7219_test;
    }
    else if(!strcmp((char*)mode,"decode"))
    {
        max7219_api.max7219_api = max7219_decode_mode;
    }
    else if(!strcmp((char*)mode,"intensity"))
    {
        max7219_api.max7219_api = max7219_intensity;
    }
    else
    {
        MAX7219_LOG("max7219_api_find error :%s",mode);
    }
    
    if(!max7219_api.max7219_api)
        return -1;
    return 0;
}

max7219TypeDef max7219_api = {
.max7219_api_find = max7219_api_find,
.max7219_digit = max7219_digit,
};

max7219_digit 函数直接输入字符,注释写的很清楚
使用例子

void led_display_task  (void*arg)
{
    delay(100);
    
    max7219_api.max7219_api_find((uint8_t*)"shutdown");
    max7219_api.max7219_api(NORMAL_MODE);
    
    max7219_api.max7219_api_find((uint8_t*)"intensity");
    max7219_api.max7219_api(0x8);
    
    max7219_api.max7219_api_find((uint8_t*)"test");
    max7219_api.max7219_api(1);
    
    delay(500);
    
    max7219_api.max7219_api(NORMAL_MODE);

    max7219_api.max7219_api_find((uint8_t*)"decode");
    max7219_api.max7219_api(NO_DECODE_D0_D7);
    
    max7219_api.max7219_api_find((uint8_t*)"scan");
    max7219_api.max7219_api(3);
    
    while (1)
    {
        max7219_api.max7219_digit('0','0'|Segment_Line_DP);// |Segment_Line_DP 是带小数点
        max7219_api.max7219_digit('1','1');
        max7219_api.max7219_digit('2','2');
        max7219_api.max7219_digit('3','3');

        max7219_api.max7219_digit('2','='|Segment_Line_DP);
        max7219_api.max7219_digit('3','-'|Segment_Line_DP);
        max7219_api.max7219_digit('3','+'|Segment_Line_DP);
        max7219_api.max7219_digit('3','('|Segment_Line_DP);
        max7219_api.max7219_digit('3',')'|Segment_Line_DP);
    }
}

注意: 改变编码方式时,原有的显示会有影响,比如 1 位置显示 bcd编码,2位置想要更新为 无编码模式,那1 位置也将变为无编码模式。

你可能感兴趣的:(STM32,数码管)