MAX7219/MAX7221 dirver + example
This commit is contained in:
parent
c21f70366f
commit
87b4befd87
6 changed files with 383 additions and 0 deletions
3
examples/max7219_7seg/Makefile
Normal file
3
examples/max7219_7seg/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
PROGRAM = max7219_7seg
|
||||||
|
EXTRA_COMPONENTS = extras/max7219
|
||||||
|
include ../../common.mk
|
52
examples/max7219_7seg/main.c
Normal file
52
examples/max7219_7seg/main.c
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* Example of using MAX7219 driver with 7 segment displays
|
||||||
|
*
|
||||||
|
* Part of esp-open-rtos
|
||||||
|
* Copyright (C) 2017 Ruslan V. Uss <unclerus@gmail.com>
|
||||||
|
* BSD Licensed as described in the file LICENSE
|
||||||
|
*/
|
||||||
|
#include <esp/uart.h>
|
||||||
|
#include <espressif/esp_common.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <max7219/max7219.h>
|
||||||
|
#include <FreeRTOS.h>
|
||||||
|
#include <task.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <esp/hwrand.h>
|
||||||
|
|
||||||
|
#define CS_PIN 5
|
||||||
|
#define DELAY 2000
|
||||||
|
|
||||||
|
static max7219_display_t disp = {
|
||||||
|
.cs_pin = CS_PIN,
|
||||||
|
.digits = 8,
|
||||||
|
.cascade_size = 1,
|
||||||
|
.mirrored = true
|
||||||
|
};
|
||||||
|
|
||||||
|
void user_init(void)
|
||||||
|
{
|
||||||
|
uart_set_baud(0, 115200);
|
||||||
|
printf("SDK version:%s\n", sdk_system_get_sdk_version());
|
||||||
|
|
||||||
|
max7219_init(&disp);
|
||||||
|
//max7219_set_decode_mode(&disp, true);
|
||||||
|
|
||||||
|
char buf[9];
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
max7219_clear(&disp);
|
||||||
|
max7219_draw_text(&disp, 0, "7219LEDS");
|
||||||
|
vTaskDelay(DELAY / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
max7219_clear(&disp);
|
||||||
|
sprintf(buf, "%2.4f A", 34.6782);
|
||||||
|
max7219_draw_text(&disp, 0, buf);
|
||||||
|
vTaskDelay(DELAY / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
max7219_clear(&disp);
|
||||||
|
sprintf(buf, "%08x", hwrand());
|
||||||
|
max7219_draw_text(&disp, 0, buf);
|
||||||
|
vTaskDelay(DELAY / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
7
extras/max7219/component.mk
Normal file
7
extras/max7219/component.mk
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
# include it as 'max7219/max7219.h'
|
||||||
|
INC_DIRS += $(max7219_ROOT)..
|
||||||
|
|
||||||
|
# args for passing into compile rule generation
|
||||||
|
max7219_SRC_DIR = $(max7219_ROOT)
|
||||||
|
|
||||||
|
$(eval $(call component_compile_rules,max7219))
|
189
extras/max7219/max7219.c
Normal file
189
extras/max7219/max7219.c
Normal file
|
@ -0,0 +1,189 @@
|
||||||
|
/*
|
||||||
|
* Driver for MAX7219/MAX7221
|
||||||
|
* Serially Interfaced, 8-Digit LED Display Drivers
|
||||||
|
*
|
||||||
|
* Part of esp-open-rtos
|
||||||
|
* Copyright (C) 2017 Ruslan V. Uss <unclerus@gmail.com>
|
||||||
|
* BSD Licensed as described in the file LICENSE
|
||||||
|
*/
|
||||||
|
#include "max7219.h"
|
||||||
|
#include <esp/spi.h>
|
||||||
|
#include <esp/gpio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "max7219_priv.h"
|
||||||
|
|
||||||
|
#define SPI_BUS 1
|
||||||
|
|
||||||
|
//#define MAX7219_DEBUG
|
||||||
|
|
||||||
|
#ifdef MAX7219_DEBUG
|
||||||
|
#include <stdio.h>
|
||||||
|
#define debug(fmt, ...) printf("%s: " fmt "\n", "MAX7219", ## __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define debug(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ALL_CHIPS 0xff
|
||||||
|
#define ALL_DIGITS 8
|
||||||
|
|
||||||
|
#define REG_DIGIT_0 (1 << 8)
|
||||||
|
#define REG_DECODE_MODE (9 << 8)
|
||||||
|
#define REG_INTENSITY (10 << 8)
|
||||||
|
#define REG_SCAN_LIMIT (11 << 8)
|
||||||
|
#define REG_SHUTDOWN (12 << 8)
|
||||||
|
#define REG_DISPLAY_TEST (15 << 8)
|
||||||
|
|
||||||
|
#define VAL_CLEAR_BCD 0x0f
|
||||||
|
#define VAL_CLEAR_NORMAL 0x00
|
||||||
|
|
||||||
|
static const spi_settings_t bus_settings = {
|
||||||
|
.mode = SPI_MODE0,
|
||||||
|
.freq_divider = SPI_FREQ_DIV_10M,
|
||||||
|
.msb = true,
|
||||||
|
.minimal_pins = true,
|
||||||
|
.endianness = SPI_BIG_ENDIAN
|
||||||
|
};
|
||||||
|
|
||||||
|
static void send(const max7219_display_t *disp, uint8_t chip, uint16_t value)
|
||||||
|
{
|
||||||
|
uint16_t buf[MAX7219_MAX_CASCADE_SIZE] = { 0 };
|
||||||
|
if (chip == ALL_CHIPS)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0; i < disp->cascade_size; i++)
|
||||||
|
buf[i] = value;
|
||||||
|
}
|
||||||
|
else buf[chip] = value;
|
||||||
|
|
||||||
|
spi_settings_t old_settings;
|
||||||
|
spi_get_settings(SPI_BUS, &old_settings);
|
||||||
|
spi_set_settings(SPI_BUS, &bus_settings);
|
||||||
|
gpio_write(disp->cs_pin, false);
|
||||||
|
|
||||||
|
spi_transfer(SPI_BUS, buf, NULL, disp->cascade_size, SPI_16BIT);
|
||||||
|
|
||||||
|
gpio_write(disp->cs_pin, true);
|
||||||
|
spi_set_settings(SPI_BUS, &old_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool max7219_init(max7219_display_t *disp)
|
||||||
|
{
|
||||||
|
if (!disp->cascade_size || disp->cascade_size > MAX7219_MAX_CASCADE_SIZE)
|
||||||
|
{
|
||||||
|
debug("Invalid cascade size %d", disp->cascade_size);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t max_digits = disp->cascade_size * ALL_DIGITS;
|
||||||
|
if (!disp->digits || disp->digits > max_digits)
|
||||||
|
{
|
||||||
|
debug("Invalid digits count %d, max %d", disp->cascade_size, max_digits);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_enable(disp->cs_pin, GPIO_OUTPUT);
|
||||||
|
gpio_write(disp->cs_pin, true);
|
||||||
|
|
||||||
|
// Shutdown all chips
|
||||||
|
max7219_set_shutdown_mode(disp, true);
|
||||||
|
// Disable test
|
||||||
|
send(disp, ALL_CHIPS, REG_DISPLAY_TEST);
|
||||||
|
// Set max scan limit
|
||||||
|
send(disp, ALL_CHIPS, REG_SCAN_LIMIT | (ALL_DIGITS - 1));
|
||||||
|
// Set normal decode mode & clear display
|
||||||
|
max7219_set_decode_mode(disp, false);
|
||||||
|
// Set minimal brightness
|
||||||
|
max7219_set_brightness(disp, 0);
|
||||||
|
// Wake up
|
||||||
|
max7219_set_shutdown_mode(disp, false);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void max7219_set_decode_mode(max7219_display_t *disp, bool bcd)
|
||||||
|
{
|
||||||
|
disp->bcd = bcd;
|
||||||
|
send(disp, ALL_CHIPS, REG_DECODE_MODE | (bcd ? 0xff : 0));
|
||||||
|
max7219_clear(disp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void max7219_set_brightness(const max7219_display_t *disp, uint8_t value)
|
||||||
|
{
|
||||||
|
send(disp, ALL_CHIPS, REG_INTENSITY | (value > MAX7219_MAX_BRIGHTNESS ? MAX7219_MAX_BRIGHTNESS : value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void max7219_set_shutdown_mode(const max7219_display_t *disp, bool shutdown)
|
||||||
|
{
|
||||||
|
send(disp, ALL_CHIPS, REG_SHUTDOWN | !shutdown);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool max7219_set_digit(const max7219_display_t *disp, uint8_t digit, uint8_t val)
|
||||||
|
{
|
||||||
|
if (digit >= disp->digits)
|
||||||
|
{
|
||||||
|
debug("Invalid digit: %d", digit);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (disp->mirrored)
|
||||||
|
digit = disp->digits - digit - 1;
|
||||||
|
|
||||||
|
uint8_t c = digit / ALL_DIGITS;
|
||||||
|
uint8_t d = digit % ALL_DIGITS;
|
||||||
|
|
||||||
|
send(disp, c, (REG_DIGIT_0 + ((uint16_t)d << 8)) | val);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void max7219_clear(const max7219_display_t *disp)
|
||||||
|
{
|
||||||
|
uint8_t val = disp->bcd ? VAL_CLEAR_BCD : VAL_CLEAR_NORMAL;
|
||||||
|
for (uint8_t i = 0; i < ALL_DIGITS; i++)
|
||||||
|
send(disp, ALL_CHIPS, (REG_DIGIT_0 + ((uint16_t)i << 8)) | val);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline static uint8_t get_char(const max7219_display_t *disp, char c)
|
||||||
|
{
|
||||||
|
if (disp->bcd)
|
||||||
|
{
|
||||||
|
if (c >= '0' && c <= '9')
|
||||||
|
return c - '0';
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case '-':
|
||||||
|
return 0x0a;
|
||||||
|
case 'E':
|
||||||
|
case 'e':
|
||||||
|
return 0x0b;
|
||||||
|
case 'H':
|
||||||
|
case 'h':
|
||||||
|
return 0x0c;
|
||||||
|
case 'L':
|
||||||
|
case 'l':
|
||||||
|
return 0x0d;
|
||||||
|
case 'P':
|
||||||
|
case 'p':
|
||||||
|
return 0x0e;
|
||||||
|
}
|
||||||
|
return VAL_CLEAR_BCD;
|
||||||
|
}
|
||||||
|
|
||||||
|
return font_7seg[(c - 0x20) & 0x7f];
|
||||||
|
}
|
||||||
|
|
||||||
|
void max7219_draw_text(const max7219_display_t *disp, uint8_t pos, const char *s)
|
||||||
|
{
|
||||||
|
while (s && pos < disp->digits)
|
||||||
|
{
|
||||||
|
uint8_t c = get_char(disp, *s);
|
||||||
|
if (*(s + 1) == '.')
|
||||||
|
{
|
||||||
|
c |= 0x80;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
max7219_set_digit(disp, pos, c);
|
||||||
|
pos++;
|
||||||
|
s++;
|
||||||
|
}
|
||||||
|
}
|
96
extras/max7219/max7219.h
Normal file
96
extras/max7219/max7219.h
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
/*
|
||||||
|
* Driver for MAX7219/MAX7221
|
||||||
|
* Serially Interfaced, 8-Digit LED Display Drivers
|
||||||
|
*
|
||||||
|
* Part of esp-open-rtos
|
||||||
|
* Copyright (C) 2017 Ruslan V. Uss <unclerus@gmail.com>
|
||||||
|
* BSD Licensed as described in the file LICENSE
|
||||||
|
*/
|
||||||
|
#ifndef EXTRAS_MAX7219_H_
|
||||||
|
#define EXTRAS_MAX7219_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX7219_MAX_CASCADE_SIZE 8
|
||||||
|
#define MAX7219_MAX_BRIGHTNESS 31
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display descriptor
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
uint8_t cs_pin; //!< GPIO connected to CS/LOAD pin
|
||||||
|
|
||||||
|
uint8_t digits; //!< Accessible digits in 7seg. Up to cascade_size * 8
|
||||||
|
|
||||||
|
uint8_t cascade_size; //!< Up to 8 MAX721xx cascaded
|
||||||
|
bool mirrored; //!< true for horizontally mirrored displays
|
||||||
|
|
||||||
|
bool bcd;
|
||||||
|
} max7219_display_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize display: switch it to normal operation from shutdown mode,
|
||||||
|
* set scan limit to the max and clear
|
||||||
|
* @param disp Pointer to display descriptor
|
||||||
|
* @return false if error occured
|
||||||
|
*/
|
||||||
|
bool max7219_init(max7219_display_t *disp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set decode mode and clear display
|
||||||
|
* @param disp Pointer to display descriptor
|
||||||
|
* @param bcd true to set BCD decode mode, false to normal
|
||||||
|
*/
|
||||||
|
void max7219_set_decode_mode(max7219_display_t *disp, bool bcd);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set display brightness
|
||||||
|
* @param disp Pointer to display descriptor
|
||||||
|
* @param value Brightness value, 0..MAX7219_MAX_BRIGHTNESS
|
||||||
|
*/
|
||||||
|
void max7219_set_brightness(const max7219_display_t *disp, uint8_t value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shutdown display or set it to normal mode
|
||||||
|
* @param disp Pointer to display descriptor
|
||||||
|
* @param shutdown Shutdown display if true
|
||||||
|
*/
|
||||||
|
void max7219_set_shutdown_mode(const max7219_display_t *disp, bool shutdown);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write data to display digit
|
||||||
|
* @param disp Pointer to display descriptor
|
||||||
|
* @param digit Digit index, 0..disp->digits - 1
|
||||||
|
* @param val Data
|
||||||
|
* @return false if error occured
|
||||||
|
*/
|
||||||
|
bool max7219_set_digit(const max7219_display_t *disp, uint8_t digit, uint8_t val);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear display
|
||||||
|
* @param disp Pointer to display descriptor
|
||||||
|
*/
|
||||||
|
void max7219_clear(const max7219_display_t *disp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draw text.
|
||||||
|
* Currently only 7-segment displays supported
|
||||||
|
* @param disp Pointer to display descriptor
|
||||||
|
* @param pos Start digit
|
||||||
|
* @param s Text
|
||||||
|
*/
|
||||||
|
void max7219_draw_text(const max7219_display_t *disp, uint8_t pos, const char *s);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C"
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* EXTRAS_MAX7219_H_ */
|
36
extras/max7219/max7219_priv.h
Normal file
36
extras/max7219/max7219_priv.h
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Driver for MAX7219/MAX7221
|
||||||
|
* Serially Interfaced, 8-Digit LED Display Drivers
|
||||||
|
*
|
||||||
|
* Part of esp-open-rtos
|
||||||
|
* Copyright (C) 2017 Ruslan V. Uss <unclerus@gmail.com>
|
||||||
|
* BSD Licensed as described in the file LICENSE
|
||||||
|
*/
|
||||||
|
#ifndef EXTRAS_MAX7219_PRIV_H_
|
||||||
|
#define EXTRAS_MAX7219_PRIV_H_
|
||||||
|
|
||||||
|
static const uint8_t font_7seg[] = {
|
||||||
|
/* ' ' ! " # $ % & ' ( ) */
|
||||||
|
0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4e, 0x78,
|
||||||
|
/* * + , - . / 0 1 2 3 */
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x30, 0x6d, 0x79,
|
||||||
|
/* 4 5 6 7 8 9 : ; < = */
|
||||||
|
0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x00, 0x00, 0x0d, 0x09,
|
||||||
|
/* > ? @ A B C D E F G */
|
||||||
|
0x19, 0x65, 0x00, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47, 0x5e,
|
||||||
|
/* H I J K L M N O P Q */
|
||||||
|
0x37, 0x06, 0x38, 0x57, 0x0e, 0x76, 0x15, 0x1d, 0x67, 0x73,
|
||||||
|
/* R S T U V W X Y Z [ */
|
||||||
|
0x05, 0x5b, 0x0f, 0x1c, 0x3e, 0x2a, 0x49, 0x3b, 0x6d, 0x4e,
|
||||||
|
/* \ ] ^ _ ` a b c d e */
|
||||||
|
0x00, 0x78, 0x00, 0x08, 0x02, 0x77, 0x1f, 0x4e, 0x3d, 0x4f,
|
||||||
|
/* f g h i j k l m n o */
|
||||||
|
0x47, 0x5e, 0x37, 0x06, 0x38, 0x57, 0x0e, 0x76, 0x15, 0x1d,
|
||||||
|
/* p q r s t u v w x y */
|
||||||
|
0x67, 0x73, 0x05, 0x5b, 0x0f, 0x1c, 0x3e, 0x2a, 0x49, 0x3b,
|
||||||
|
/* z { | } ~ */
|
||||||
|
0x6d, 0x4e, 0x06, 0x78, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* EXTRAS_MAX7219_PRIV_H_ */
|
Loading…
Reference in a new issue