Add a couple of examples of using the Max7219 LED driver chip (#209)

This commit is contained in:
James Hughes 2022-05-17 15:35:03 +01:00 committed by GitHub
parent 72e41ad66f
commit 705cd0fbea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 396 additions and 0 deletions

View File

@ -4,4 +4,6 @@ if (NOT PICO_NO_HARDWARE)
add_subdirectory(spi_dma)
add_subdirectory(spi_master_slave)
add_subdirectory(spi_flash)
add_subdirectory(max7219_32x8_spi)
add_subdirectory(max7219_8x7seg_spi)
endif ()

View File

@ -0,0 +1,12 @@
add_executable(max7219_32x8_spi
max7219_32x8_spi.c
)
# pull in common dependencies and additional spi hardware support
target_link_libraries(max7219_32x8_spi pico_stdlib hardware_spi)
# create map/bin/hex file etc.
pico_add_extra_outputs(max7219_32x8_spi)
# add url via pico_set_program_url
example_auto_set_url(max7219_32x8_spi)

View File

@ -0,0 +1,40 @@
= Attaching a Max7219 driving an 32x8 LED display via SPI
This example code shows how to interface the Raspberry Pi Pico to a Max7219 driving an 32x8 LED display. The particular device used is interfaced via SPI at 3.3v. This PCB uses 4 Max7219 devices, each driving an 8x8 LED matrix, giving the total of 32x8. These devices are designed to be cascaded together in this way, and SPI commands are passed down the line of devices as required.
The Max7219 datasheet can be found here https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf
== Wiring information
Wiring up the device requires 5 jumpers as follows:
* GPIO 17 (pin 22) Chip select -> CS on Max7219 board
* GPIO 18 (pin 24) SCK/spi0_sclk -> CLK on Max7219 board
* GPIO 19 (pin 25) MOSI/spi0_tx -> DIN on Max7219 board
* 5v (pin 40) -> VCC on Max7219 board
* GND (pin 38) -> GND on Max7219 board
The example here uses SPI port 0. Power is supplied from the 5V pin.
[NOTE]
======
There are many different manufacturers who sell boards with the Max7219. Whilst they all appear slightly different, they all have, at least, the same 5 pins required for power and communication. Please ensure you connect up as described in the previous paragraph.
======
== List of Files
CMakeLists.txt:: CMake file to incorporate the example in to the examples build tree.
max7219_32x8_spi.c:: The example code.
== Bill of Materials
.A list of materials required for the example
[[max7219-bom-table]]
[cols=3]
|===
| *Item* | *Quantity* | Details
| Breadboard | 1 | generic part
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
| max7219 board with 4 8x8 LED matrices| 1 | generic part
| M/M Jumper wires | 5 | generic part
|===

View File

@ -0,0 +1,141 @@
/**
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/spi.h"
/* Example code to talk to a Max7219 driving an 32x8 pixel LED display via SPI
NOTE: The device is driven at 5v, but SPI communications are at 3v3
Connections on Raspberry Pi Pico board and a generic Max7219 board, other
boards may vary.
* GPIO 17 (pin 22) Chip select -> CS on Max7219 board
* GPIO 18 (pin 24) SCK/spi0_sclk -> CLK on Max7219 board
* GPIO 19 (pin 25) MOSI/spi0_tx -> DIN on Max7219 board
* 5v (pin 40) -> VCC on Max7219 board
* GND (pin 38) -> GND on Max7219 board
Note: SPI devices can have a number of different naming schemes for pins. See
the Wikipedia page at https://en.wikipedia.org/wiki/Serial_Peripheral_Interface
for variations.
*/
// This defines how many Max7219 modules we have cascaded together, in this case, we have 4 x 8x8 matrices giving a total of 32x8
#define NUM_MODULES 4
const uint8_t CMD_NOOP = 0;
const uint8_t CMD_DIGIT0 = 1; // Goes up to 8, for each line
const uint8_t CMD_DECODEMODE = 9;
const uint8_t CMD_BRIGHTNESS = 10;
const uint8_t CMD_SCANLIMIT = 11;
const uint8_t CMD_SHUTDOWN = 12;
const uint8_t CMD_DISPLAYTEST = 15;
#ifdef PICO_DEFAULT_SPI_CSN_PIN
static inline void cs_select() {
asm volatile("nop \n nop \n nop");
gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 0); // Active low
asm volatile("nop \n nop \n nop");
}
static inline void cs_deselect() {
asm volatile("nop \n nop \n nop");
gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1);
asm volatile("nop \n nop \n nop");
}
#endif
#if defined(spi_default) && defined(PICO_DEFAULT_SPI_CSN_PIN)
static void write_register(uint8_t reg, uint8_t data) {
uint8_t buf[2];
buf[0] = reg;
buf[1] = data;
cs_select();
spi_write_blocking(spi_default, buf, 2);
cs_deselect();
sleep_ms(1);
}
static void write_register_all(uint8_t reg, uint8_t data) {
uint8_t buf[2];
buf[0] = reg;
buf[1] = data;
cs_select();
for (int i = 0; i< NUM_MODULES;i++) {
spi_write_blocking(spi_default, buf, 2);
}
cs_deselect();
}
#endif
int main() {
stdio_init_all();
#if !defined(spi_default) || !defined(PICO_DEFAULT_SPI_SCK_PIN) || !defined(PICO_DEFAULT_SPI_TX_PIN) || !defined(PICO_DEFAULT_SPI_CSN_PIN)
#warning spi/max7219_32x8_spi example requires a board with SPI pins
puts("Default SPI pins were not defined");
#else
printf("Hello, max7219! Drawing things on a LED matrix since 2022...\n");
// This example will use SPI0 at 10MHz.
spi_init(spi_default, 10 * 1000 * 1000);
gpio_set_function(PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI);
gpio_set_function(PICO_DEFAULT_SPI_TX_PIN, GPIO_FUNC_SPI);
// Make the SPI pins available to picotool
bi_decl(bi_2pins_with_func(PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI));
// Chip select is active-low, so we'll initialise it to a driven-high state
gpio_init(PICO_DEFAULT_SPI_CSN_PIN);
gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT);
gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1);
// Make the CS pin available to picotool
bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS"));
// Send init sequence to device
write_register_all(CMD_SHUTDOWN, 0);
write_register_all(CMD_DISPLAYTEST, 0);
write_register_all(CMD_SCANLIMIT, 7); // Use all lines
write_register_all(CMD_DECODEMODE, 0); // No BCD decode, just use bit pattern.
write_register_all(CMD_SHUTDOWN, 1);
write_register_all(CMD_BRIGHTNESS, 8);
for (int i=0; i<256; i++) {
for (int j=0; j<8; j++) {
write_register_all(CMD_DIGIT0+j, i);
}
sleep_ms(20);
}
int bright = 1;
while (true) {
for (int i=0; i<8; i++) {
if (bright & 1) {
write_register_all(CMD_DIGIT0 + i, 170 >> (i%2));
} else {
write_register_all(CMD_DIGIT0 + i, (170 >> 1) << (i%2));
}
write_register_all(CMD_BRIGHTNESS, bright % 16);
}
sleep_ms(250);
bright++;
}
return 0;
#endif
}

View File

@ -0,0 +1,12 @@
add_executable(max7219_8x7seg_spi
max7219_8x7seg_spi.c
)
# pull in common dependencies and additional spi hardware support
target_link_libraries(max7219_8x7seg_spi pico_stdlib hardware_spi)
# create map/bin/hex file etc.
pico_add_extra_outputs(max7219_8x7seg_spi)
# add url via pico_set_program_url
example_auto_set_url(max7219_8x7seg_spi)

View File

@ -0,0 +1,41 @@
= Attaching a Max7219 driving an 8 digit 7 segment display via SPI
This example code shows how to interface the Raspberry Pi Pico to a Max7219 driving an 8 digit 7 segment display. The particular device used is interfaced via SPI at 3.3v.
The Max7219 datasheet can be found here https://datasheets.maximintegrated.com/en/ds/MAX7219-MAX7221.pdf
== Wiring information
Wiring up the device requires 5 jumpers as follows:
* GPIO 17 (pin 22) Chip select -> CS on Max7219 board
* GPIO 18 (pin 24) SCK/spi0_sclk -> CLK on Max7219 board
* GPIO 19 (pin 25) MOSI/spi0_tx -> DIN on Max7219 board
* 5v (pin 40) -> VCC on Max7219 board
* GND (pin 38) -> GND on Max7219 board
The example here uses SPI port 0. Power is supplied from the 5V pin.
[NOTE]
======
There are many different manufacturers who sell boards with the Max7219. Whilst they all appear slightly different, they all have, at least, the same 5 pins required for power and communication. Please ensure you connect up as described in the previous paragraph.
======
== List of Files
CMakeLists.txt:: CMake file to incorporate the example in to the examples build tree.
max7219_8x7seg_spi.c:: The example code.
== Bill of Materials
.A list of materials required for the example
[[max7219-bom-table]]
[cols=3]
|===
| *Item* | *Quantity* | Details
| Breadboard | 1 | generic part
| Raspberry Pi Pico | 1 | https://www.raspberrypi.com/products/raspberry-pi-pico/
| max7219 board with 8x7segment LEDs| 1 | generic part
| M/M Jumper wires | 5 | generic part
|===

View File

@ -0,0 +1,148 @@
/**
* Copyright (c) 2022 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <string.h>
#include "pico/stdlib.h"
#include "pico/binary_info.h"
#include "hardware/spi.h"
/* Example code to talk to a Max7219 driving an 8 digit 7 segment display via SPI
NOTE: The device is driven at 5v, but SPI communications are at 3v3
Connections on Raspberry Pi Pico board and a generic Max7219 board, other
boards may vary.
* GPIO 17 (pin 22) Chip select -> CS on Max7219 board
* GPIO 18 (pin 24) SCK/spi0_sclk -> CLK on Max7219 board
* GPIO 19 (pin 25) MOSI/spi0_tx -> DIN on Max7219 board
* 5v (pin 40) -> VCC on Max7219 board
* GND (pin 38) -> GND on Max7219 board
Note: SPI devices can have a number of different naming schemes for pins. See
the Wikipedia page at https://en.wikipedia.org/wiki/Serial_Peripheral_Interface
for variations.
*/
// This defines how many Max7219 modules we have cascaded together, in this case, just the one.
#define NUM_MODULES 1
const uint8_t CMD_NOOP = 0;
const uint8_t CMD_DIGIT0 = 1; // Goes up to 8, for each line
const uint8_t CMD_DECODEMODE = 9;
const uint8_t CMD_BRIGHTNESS = 10;
const uint8_t CMD_SCANLIMIT = 11;
const uint8_t CMD_SHUTDOWN = 12;
const uint8_t CMD_DISPLAYTEST = 15;
#ifdef PICO_DEFAULT_SPI_CSN_PIN
static inline void cs_select() {
asm volatile("nop \n nop \n nop");
gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 0); // Active low
asm volatile("nop \n nop \n nop");
}
static inline void cs_deselect() {
asm volatile("nop \n nop \n nop");
gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1);
asm volatile("nop \n nop \n nop");
}
#endif
#if defined(spi_default) && defined(PICO_DEFAULT_SPI_CSN_PIN)
static void write_register(uint8_t reg, uint8_t data) {
uint8_t buf[2];
buf[0] = reg;
buf[1] = data;
cs_select();
spi_write_blocking(spi_default, buf, 2);
cs_deselect();
sleep_ms(1);
}
static void write_register_all(uint8_t reg, uint8_t data) {
uint8_t buf[2];
buf[0] = reg;
buf[1] = data;
cs_select();
for (int i = 0; i< NUM_MODULES;i++) {
spi_write_blocking(spi_default, buf, 2);
}
cs_deselect();
}
#endif
void display_num(int32_t num)
{
int digit = 0;
while (num && digit < 8) {
write_register_all(CMD_DIGIT0 + digit, num % 10);
num /= 10;
digit++;
}
}
void clear()
{
for (int i=0;i<8;i++) {
write_register_all(CMD_DIGIT0 + i, 0);
}
}
int main() {
stdio_init_all();
#if !defined(spi_default) || !defined(PICO_DEFAULT_SPI_SCK_PIN) || !defined(PICO_DEFAULT_SPI_TX_PIN) || !defined(PICO_DEFAULT_SPI_CSN_PIN)
#warning spi/max7219_8x7seg_spi example requires a board with SPI pins
puts("Default SPI pins were not defined");
#else
printf("Hello, max7219! Drawing things on a 8 x 7 segment display since 2022...\n");
// This example will use SPI0 at 10MHz.
spi_init(spi_default, 10 * 1000 * 1000);
gpio_set_function(PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI);
gpio_set_function(PICO_DEFAULT_SPI_TX_PIN, GPIO_FUNC_SPI);
// Make the SPI pins available to picotool
bi_decl(bi_2pins_with_func(PICO_DEFAULT_SPI_TX_PIN, PICO_DEFAULT_SPI_SCK_PIN, GPIO_FUNC_SPI));
// Chip select is active-low, so we'll initialise it to a driven-high state
gpio_init(PICO_DEFAULT_SPI_CSN_PIN);
gpio_set_dir(PICO_DEFAULT_SPI_CSN_PIN, GPIO_OUT);
gpio_put(PICO_DEFAULT_SPI_CSN_PIN, 1);
// Make the CS pin available to picotool
bi_decl(bi_1pin_with_name(PICO_DEFAULT_SPI_CSN_PIN, "SPI CS"));
// Send init sequence to device
write_register_all(CMD_SHUTDOWN, 0);
write_register_all(CMD_DISPLAYTEST, 0);
write_register_all(CMD_SCANLIMIT, 7);
write_register_all(CMD_DECODEMODE, 255);
write_register_all(CMD_SHUTDOWN, 1);
write_register_all(CMD_BRIGHTNESS, 8);
clear();
int j = 0;
while (true) {
display_num(j++);
sleep_ms(1);
if (j > 99999999) {
j = 0;
}
}
return 0;
#endif
}