因为做这个需要用到max7219,所以在网上找了一些前车之鉴。和以前找其他资料一样,我认为他们写的真的不好,甚至都辣眼睛,更有甚者上来就放两句话,最后一句是我实现了,倒不如发
实现max7219驱动数码管显示
此部分只摘取官方文档部分内容。我认为足够使用了
下图寄存器表就是地址
ditgit 代表要控制哪个数据管,max7219可以控制0 - 7个数码管,矩阵led这里不说了。实现步骤就是,想控制的 数码管地址 + 想要显示的数据(可以通过decode mode 设置BCD解码或者不解码)
重点注意红框部分 硬件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 位置也将变为无编码模式。