【发布时间】:2021-12-26 20:30:46
【问题描述】:
我想使用 Raspberrypi 控制矩阵的每个单独像素,但我只是不知道我必须如何发送以及发送什么数据。
我已经查看了 SPI 接口,但是在阅读了这个 article 之后,他没有使用它并因此手动执行它,我不确定该怎么做。
调试也很困难,因为我无法检查发送的时间和数据
我还检查了各种 python 库,但我无法让它们运行,即使在安装了每个依赖项之后也是如此 但是没必要,因为我不想用python。
我从来没有做过这样的事情,所以我非常缺乏经验。
我像在guide 中那样将其连接起来,并在 rust 中编写了一些代码以通过 SPI 接口发送数据:
use std::io;
use std::io::prelude::*;
use spidev::{Spidev, SpidevOptions, SpiModeFlags};
fn create_spi() -> 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() {
let mut spi = create_spi().unwrap();
spi.write(&[0x01, 0x02, 0x03]).unwrap();
}
在 Pi 上运行它之后,它似乎成功地发送了数据而没有恐慌,但我无法检查它是否真的有效。
在矩阵上没有按预期显示。
有人可以向我解释如何配置 SPI 连接以及我必须发送哪些数据来初始化矩阵并在其上显示一些内容吗?
更新
在查看this driver 之后,我现在能够在第一行的第一个和第四个矩阵上显示从 0 到 255 的值。 这是代码:
use std::io;
use std::io::prelude::*;
use spidev::{Spidev, SpidevOptions, SpiModeFlags};
use std::thread::sleep;
use std::time::Duration;
// Possible command register values on the display 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,
}
// Decode modes for BCD encoded input.
#[derive(Copy, Clone)]
pub enum DecodeMode {
NoDecode = 0x00,
CodeBDigit0 = 0x01,
CodeBDigits3_0 = 0x0F,
CodeBDigits7_0 = 0xFF,
}
fn create_spi() -> 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() {
let mut spi = create_spi().unwrap();
// turns on 4 displays (address, command, on)
for display in 0..4_u8 {
spi.write(&[display, 0x0c, 0x01]).unwrap();
}
// sets decode mode (adress, mode) to 0x00
spi.write(&[0x00, 0x09, 0x00]).unwrap();
// writes data (address, digit, data)
for data in 0..255 {
spi.write(&[0x00, 0x01, data]).unwrap();
sleep(Duration::from_millis(50));
}
}
但我不知道如何访问其他行或单个矩阵。
更新 2
我现在清理了代码,发现将扫描限制设置为 7 可以让您将数据绘制到所有 8 行 这是代码:
#![allow(dead_code)]
use spidev::Spidev;
use std::io::prelude::*;
// Maximum number of addrs connected in series supported
const MAX_DISPLAYS: usize = 8;
// Digits per addr
const MAX_DIGITS: usize = 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,
}
// Decode modes for BCD encoded input.
#[derive(Copy, Clone)]
pub enum DecodeMode {
NoDecode = 0x00,
CodeBDigit0 = 0x01,
CodeBDigits3_0 = 0x0F,
CodeBDigits7_0 = 0xFF,
}
pub struct Matrix {
pub spi: Spidev,
pub devices: u8,
pub decode_mode: DecodeMode
}
impl Matrix {
pub fn power_on(&mut self) {
for addr in 0..self.devices {
self.spi.write(&[addr, Command::Power as u8, 0x01]).unwrap();
}
}
pub fn power_off(&mut self) {
for addr in 0..self.devices {
self.spi.write(&[addr, Command::Power as u8, 0x00]).unwrap();
}
}
pub fn set_decode_mode(&mut self, addr: u8, mode: DecodeMode) {
// sets decode mode (adress, command, mode)
self.spi.write(&[addr, Command::DecodeMode as u8, mode as u8]).unwrap();
}
pub fn send_command(&mut self, addr: u8, command: Command, value: u8) {
self.spi.write(&[addr, command as u8, value]).unwrap();
}
pub fn draw_raw(&mut self, addr: u8, data: &[u8; MAX_DIGITS]) {
let mut digit: u8 = 1;
for b in data {
// addr ..
self.spi.write(&[addr, digit, *b]).unwrap();
digit += 1;
}
}
pub fn clear_addr(&mut self, addr: u8) {
for i in 1..9 {
self.spi.write(&[addr, i, 0x00]).unwrap();
}
}
pub fn set_intensity(&mut self, addr: u8, intesity: u8) {
self.spi.write(&[addr, Command::Intensity as u8, intesity]).unwrap();
}
}
let spi = create_spi().unwrap();
let mut matrix = Matrix{
spi,
devices: 4, // 4 displays chained together, not working rn
decode_mode: DecodeMode::NoDecode
};
matrix.power_on();
matrix.send_command(0x00, Command::ScanLimit, 0x07);
matrix.draw_raw(0x00, &[
0b1001001,
0b0110110,
0b1001001,
0b0110110,
0b1001001,
0b0110110,
0b1001001,
0b0110110
]);
sleep(Duration::from_secs(1));
matrix.power_off();
但它显示在第一个和第四个显示器上,我仍然无法单独控制它们。
【问题讨论】:
标签: raspberry-pi microcontroller spi