本文介绍了我只能控制由Max7219供电的四个8x8 led矩阵中的第一个的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有4个8x8 LED矩阵,它们是串行连接的,我使用SPI协议与通信。
并且在重写几个库(python implementation、rust implementation、c implementation)之后,因为它不能在我的系统上工作,并且我的代码至少能工作一点,所以我只能控制四个连接的显示器中的第一个。以下是我的代码,用于在第一个显示器上显示类似目标的图像:
矩阵对象:
#![allow(dead_code)]
use spidev::Spidev;
use std::io::prelude::*;
// Maximum number of displays connected in series supported
const MAX_DISPLAYS: u8 = 8;
// Digits per addr
const MAX_DIGITS: u8 = 8;
// Possible command register values on the addr chip.
#[derive(Clone, Copy)]
pub enum Command {
Noop = 0x00,
Digit0 = 0x01,
Digit1 = 0x02,
Digit2 = 0x03,
Digit3 = 0x04,
Digit4 = 0x05,
Digit5 = 0x06,
Digit6 = 0x07,
Digit7 = 0x08,
DecodeMode = 0x09,
Intensity = 0x0A,
ScanLimit = 0x0B,
Power = 0x0C,
DisplayTest = 0x0F,
}
pub struct Matrix {
pub spi: Spidev,
pub devices: u8,
}
impl Matrix {
pub fn init(&mut self) -> std::io::Result<()> {
for device in 0..self.devices {
self.send_bytes([device, Command::ScanLimit as u8, 0x07])?; // to scan for 8 digits or in this case columns
self.send_bytes([device, Command::DecodeMode as u8, 0x00])?; // No Decode Mode for matrix
self.send_bytes([device, Command::DisplayTest as u8, 0x00])?; // no displaytest desired
self.send_bytes([device, Command::Power as u8, 0x01])?; // powers on the display
}
Ok(())
}
pub fn power_off(&mut self) -> std::io::Result<()> {
for addr in 0..self.devices {
self.send_bytes([addr, Command::Power as u8, 0x00])?;
}
Ok(())
}
pub fn send_command(&mut self, addr: u8, command: Command, value: u8) -> std::io::Result<()> {
self.send_bytes([addr, command as u8, value])?;
Ok(())
}
pub fn draw_raw(&mut self, addr: u8, data: [u8; 8]) -> std::io::Result<()> {
let mut digit: u8 = 1; // column
for b in data {
self.send_bytes([addr, digit, b])?;
digit += 1;
}
Ok(())
}
pub fn clear_display(&mut self, addr: u8) -> std::io::Result<()> {
for col in 1..=MAX_DIGITS {
self.send_bytes([addr, col, 0x00])?;
}
Ok(())
}
/// range 0 to 15
pub fn set_intensity(&mut self, addr: u8, intesity: u8) -> std::io::Result<()> {
self.send_bytes([addr, Command::Intensity as u8, intesity])?;
Ok(())
}
fn send_bytes(&mut self, bytes: [u8; 3]) -> std::io::Result<()> {
self.spi.write(&bytes)?;
Ok(())
}
}
main.rs
use spidev::{Spidev, SpidevOptions, SpiModeFlags};
use std::thread::sleep;
use std::time::Duration;
mod matrix;
use matrix::*;
fn create_spi() -> std::io::Result<Spidev> {
let mut spi = Spidev::open("/dev/spidev0.0")?;
let options = SpidevOptions::new()
.bits_per_word(8)
.max_speed_hz(20_000)
.mode(SpiModeFlags::SPI_MODE_0)
.build();
spi.configure(&options)?;
Ok(spi)
}
fn main() {
println!("running");
let spi = create_spi().unwrap();
let mut matrix = Matrix{
spi,
devices: 4,
};
matrix.init().unwrap();
matrix.draw_raw(0x01,
[
0b11111111,
0b10000001,
0b10000001,
0b10011001,
0b10011001,
0b10000001,
0b10000001,
0b11111111
])
.unwrap();
sleep(Duration::from_secs(3));
matrix.power_off().unwrap();
}
仅查看第一个显示,一切正常,但以下是问题:
- 在第二个显示屏上,每个像素都亮起
- 正如预期的那样,第三个显示屏完全没有亮起
- 位图&q;绘制在显示屏1和4上
我认为问题在于如何通过SPI发送数据,但我不确定。
我必须做些什么才能使其正常工作?
spi
我现在放弃了使用推荐答案的想法,并从此library
复制了方法矩阵对象现在如下所示:
use gpio_cdev::{LineHandle, Error};
// Maximum number of displays connected in series supported
const MAX_DISPLAYS: u8 = 8;
// Digits per addr
const MAX_DIGITS: u8 = 8;
// Possible command register values on the addr chip.
#[derive(Clone, Copy)]
pub enum Command {
Noop = 0x00,
Digit0 = 0x01,
Digit1 = 0x02,
Digit2 = 0x03,
Digit3 = 0x04,
Digit4 = 0x05,
Digit5 = 0x06,
Digit6 = 0x07,
Digit7 = 0x08,
DecodeMode = 0x09,
Intensity = 0x0A,
ScanLimit = 0x0B,
Power = 0x0C,
DisplayTest = 0x0F,
}
pub struct Matrix {
pub cs: LineHandle,
pub data: LineHandle,
pub clock: LineHandle,
pub devices: u8,
pub buffer: [u8; MAX_DISPLAYS as usize * 2]
}
impl Matrix {
pub fn new(
cs: LineHandle,
data: LineHandle,
clock: LineHandle,
devices: u8,
) -> Self {
Matrix { cs, data, clock, devices, buffer: [0; MAX_DISPLAYS as usize * 2] }
}
pub fn init(&mut self) -> Result<(), Error> {
for device in 0..self.devices {
self.write_raw(device, Command::ScanLimit as u8, 0x07)?; // to scan for 8 digits or in this case columns
self.write_raw(device, Command::DecodeMode as u8, 0x00)?; // No Decode Mode for matrix
self.write_raw(device, Command::DisplayTest as u8, 0x00)?;
self.write_raw(device, Command::Power as u8, 0x01)?; // powers on display
}
Ok(())
}
pub fn power_off(&mut self) -> Result<(), Error> {
for addr in 0..self.devices {
self.write_raw(addr, Command::Power as u8, 0x00)?;
}
Ok(())
}
pub fn send_command(&mut self, addr: u8, command: Command, value: u8) -> Result<(), Error> {
self.write_raw(addr, command as u8, value)?;
Ok(())
}
pub fn draw_raw(&mut self, addr: u8, data: [u8; 8]) -> Result<(), Error> {
let mut digit: u8 = 1; // column
for b in data {
self.write_raw(addr, digit, b)?;
digit += 1;
}
Ok(())
}
pub fn clear_display(&mut self, addr: u8) -> Result<(), Error> {
for col in 1..=MAX_DIGITS {
self.write_raw(addr, col, 0x00)?;
}
Ok(())
}
/// range 0 to 15
pub fn set_intensity(&mut self, addr: u8, intesity: u8) -> Result<(), Error> {
self.write_raw(addr, Command::Intensity as u8, intesity)?;
Ok(())
}
// new method that replaces SPI
fn write_raw(&mut self, addr: u8, header: u8, data: u8) -> Result<(), Error> {
let offset = addr as usize * 2;
let max_bytes = self.devices * 2;
self.buffer = [0; MAX_DISPLAYS as usize * 2];
self.buffer[offset] = header;
self.buffer[offset + 1] = data;
self.cs.set_value(0)?;
for b in 0..max_bytes as usize {
let value = self.buffer[b];
for i in 0..8 {
if value & (1 << (7 - i)) > 0 {
self.data.set_value(1)?;
} else {
self.data.set_value(0)?;
}
self.clock.set_value(1)?;
self.clock.set_value(0)?;
}
}
self.cs.set_value(1)?;
Ok(())
}
}
我使用gpio-cdev访问GPIO引脚,如下所示:
use gpio_cdev::{Chip, LineRequestFlags, LineHandle, Error};
fn get_pins(cs: u32, data: u32, clock: u32) -> Result<(LineHandle, LineHandle, LineHandle), Error> {
let mut chip = Chip::new("/dev/gpiochip0")?;
let cs = chip
.get_line(cs)? // 24 8
.request(LineRequestFlags::OUTPUT, 0, "chip-select")?;
let data = chip
.get_line(data)? // 19 10
.request(LineRequestFlags::OUTPUT, 0, "mosi")?;
let clock = chip
.get_line(clock)? // 23 11
.request(LineRequestFlags::OUTPUT, 0, "clock")?;
Ok( (cs, data, clock) )
}
这篇关于我只能控制由Max7219供电的四个8x8 led矩阵中的第一个的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!