全彩8*8点阵屏实现霓虹灯效果
全彩8*8点阵屏动态显示变换,实现霓虹灯效果。
一、简介 该款 RGB 点阵驱动板控制器我们采用的是 ATMEGA 328P,驱动使用的是 DM163,它是一款 8*3 通道的恒流 LED 驱动芯片,而且电流大小可以很方便的通过外接电阻调节, 另外它还可以实现 PWM 控制 LED,这样就能释放 MCU,方便用户设计其他的应用程序。 还有在模块中还加了缓冲器 M54564FP,这样增加了 RGB 点阵的显示效果。可以说这款 产品很方便用户在 Arduino IDE 环境下实现 RGB 点阵的控制。 二、产品特点 1)6 位颜色支持; 2)支持硬件 16MHZ PWM 3)没有任何外加的电路 4)专用 GPIO 和 ADC 接口 5)支持硬件 URAT 和 IIC 通信方式 6)24 路恒流通道每一通道电流可达 100mA 7)8 路源驱动恒流通道每一通道电流可达 500mA 三、使用说明 这个模块我们要结合 FT232 USB 适配器(我们也有对应的模块)来使用,需要用它来烧写我们的应用程序
原代码如下:
#include <Wire.h>
#define DEMO// enable demo
#define MATRIX_ROWS 8
#define MATRIX_COLS 8
#define MATRIX_CHANNELS 3
#define MATRIX_LEDS MATRIX_ROWS*MATRIX_COLS
#define MATRIX_ROW_CHANNELS MATRIX_COLS*MATRIX_CHANNELS
#define WIRE_DEVICE_ADDRESS 0x70
#define ROW_PORT1 PORTB
#define ROW_PORT2 PORTD
#define LED_PORTPORTC
#define I2C_PORTPORTD
#define LED_SELECT 0x01
#define LED_LATCH0x02
#define LED_RESET0x04
#define I2C_SCL 0x40
#define I2C_SDA 0x80
#define SET(_reg, _bits) (_reg) |=(_bits)
#define CLEAR(_reg, _bits) (_reg) &= ~(_bits)
// Two copies of the LED data, one being read from to drive the LEDs in an ISR, another being written to, via I2C
byte matrixDataA;
byte matrixDataB;
byte defaultCorrection[3] = {25, 63, 63};
bool matrixWriteA = true;// 'A' is the one being written to
intmatrixRow = 0;
bool processBalance = false;
bool balanceRecieved = false;// true when we've rx'd a white balance command
byte* wire_DataPtr = NULL;// the write pointer
int wire_DataCount = 0; // bytes received
bool processClear = false;
bytefastCommandBuffer[12];
byte* fastCommandPtr = NULL;
boolprocessFast = false;
// timer ISR
byte timerCounter2 = 0;
#ifdef DEMO
unsigned long demoTimeout = 5000UL; // wait 5s after startup with no balance command before running demo.
unsigned long demoTimestamp;
// rolling palette:
unsigned long demoR = 0xFF0000FFUL;
unsigned long demoG = 0xFF00FF00UL;
unsigned long demoB = 0xFFFF0000UL;
unsigned long demoStep = 0;
#endif
inline void i2c_Write(byte value, byte mask)
{
// I2C write to other chip on this board, msb first
while (mask)
{
if (value & mask)
SET(I2C_PORT, I2C_SDA);
else
CLEAR(I2C_PORT, I2C_SDA);
mask >>= 1;
CLEAR(I2C_PORT, I2C_SCL);
SET(I2C_PORT, I2C_SCL);
}
}
void wire_Request(void)
{
// ISR to process request for bytes over I2C from external master
byte response = wire_DataCount;
// write MUST be a byte buffer
Wire.write(&response, 1);
}
void wire_Receive(int numBytes)
{
// ISR to process receipt of bytes over I2C from external master
// Get out quickly!
if (numBytes == 1) // a command
{
byte command = Wire.read();
if (command == 0x00) // start frame
{
wire_DataPtr = (matrixWriteA)?matrixDataA:matrixDataB;
wire_DataCount = 0;
}
else if (command == 0x01) // show frame
{
matrixWriteA = !matrixWriteA; // atomic
}
else if (command == 0x02) // set colour balance
{
processBalance = true;
}
else if (command == 0x03) // set TCNT2
{
byte* ptr = (matrixWriteA)?matrixDataA:matrixDataB;
if (ptr[1] == 16 && ptr[2] == 128)
timerCounter2 = *ptr;
}
else if (command == 0x10) // clear to black
{
processClear = true;
}
else if (command == 0x11) // fast fill from bitmasks
{
fastCommandPtr = fastCommandBuffer;
wire_DataPtr = NULL;
wire_DataCount = 0;
}
return;
}
else if (wire_DataPtr && ((numBytes % MATRIX_CHANNELS) == 0))// read channel (RGB) data
{
while (Wire.available() && wire_DataCount < MATRIX_ROWS*MATRIX_ROW_CHANNELS)
{
*(wire_DataPtr++) = Wire.read();
wire_DataCount++;
}
}
else if (fastCommandPtr && ((numBytes % MATRIX_CHANNELS) == 0))// read triplets for fast cmd
{
while (Wire.available() && wire_DataCount < sizeof(fastCommandBuffer))
{
*(fastCommandPtr++) = Wire.read();
wire_DataCount++;
}
if (wire_DataCount == sizeof(fastCommandBuffer))
{
// process the cmd (outside the Wire handler)
processFast = true;
}
}
// discard extras
while (Wire.available())
Wire.read();
}
// white balance
void setCorrection(byte* pChannel, int dim)
{
if (*pChannel == 0x80) return;// Ignore (0x80, x, y)
cli();
CLEAR(LED_PORT, LED_SELECT);// bank 0, 6-bit
SET(LED_PORT, LED_LATCH);
for (int ctr = 0; ctr < MATRIX_COLS; ctr++)
for (int chan = MATRIX_CHANNELS - 1; chan >= 0; chan--)
i2c_Write(pChannel >> dim, 0x20); // 6- bit values
// latches BOTH banks
CLEAR(LED_PORT, LED_LATCH);
sei();
}
void doFastCommand()
{
// r,g,b, flags,row0,row1, row2,row3,row4, row5,row6,row7
int Idx = 0;
fastCommandPtr = NULL;
byte R = fastCommandBuffer;
byte G = fastCommandBuffer;
byte B = fastCommandBuffer;
byte F = fastCommandBuffer;
// F=flags, B000000xy, if x is set, use black as background (otherwise leave as-is), if y is set, show buffer at end
bool flagSetBackground = F & B00000010;
byte* ptr = (matrixWriteA)?matrixDataA:matrixDataB;
for (int row = 0; row < MATRIX_ROWS; row++)
{
byte mask = fastCommandBuffer;
for (int col = 0; col < MATRIX_COLS; col++)
{
if (mask & 0x01)// set the colour
{
(*ptr++) = R;
(*ptr++) = G;
(*ptr++) = B;
}
else if (flagSetBackground) // write black
{
(*ptr++) = 0x00;
(*ptr++) = 0x00;
(*ptr++) = 0x00;
}
else// leave colour as-is
{
ptr += 3;
}
mask >>= 1;
}
}
if (F & B00000001)// start displaying
{
matrixWriteA = !matrixWriteA;
}
}
ISR(TIMER2_OVF_vect)
{
TCNT2 = timerCounter2;
// all rows off
ROW_PORT1 = ROW_PORT2 = 0x00;
SET(LED_PORT, LED_SELECT);// bank 1, 8-bit
SET(LED_PORT, LED_LATCH);
byte* pChannel = (!matrixWriteA)?matrixDataA:matrixDataB;// (READING this time)
// clock in the channel data for the columns in the current row. REVERSE ORDER!
pChannel += matrixRow*MATRIX_ROW_CHANNELS + MATRIX_ROW_CHANNELS - 1;
for (int ctr = 0; ctr < MATRIX_ROW_CHANNELS; ctr++,pChannel--)
i2c_Write(*pChannel, 0x80);
// latches BOTH banks
CLEAR(LED_PORT, LED_LATCH);
// turn on this row
if (matrixRow < 6)
{
SET(ROW_PORT1, 0x01 << matrixRow++);
}
else if (matrixRow == 6)
{
SET(ROW_PORT2, 0x08);
matrixRow = 7;
}
else
{
SET(ROW_PORT2, 0x10);
matrixRow = 0;
}
}
void setup()
{
// clear to black
memset(matrixDataA, 0x00, sizeof(matrixDataA));
memset(matrixDataB, 0x00, sizeof(matrixDataB));
DDRB = DDRC = DDRD = 0xFF; // ALL ports to OUTPUT
ROW_PORT1 = ROW_PORT2 = 0x00;
// reset the DM163 driver
CLEAR(LED_PORT, LED_RESET);
SET(LED_PORT, LED_RESET);
// default white balance
setCorrection(defaultCorrection, 0);
// configure timer2 to service LED row updates at ~800Hz
ASSR = _BV(AS2); // Internal Calibrated clock source 16MHz
TCCR2A = 0x00; // Normal mode
TCCR2B = _BV(CS22) | _BV(CS20);// clk/128
TIMSK2 = _BV(TOIE2); // Overflow interrupt only
unsigned long timerFrequencyHz = 800UL; // sweet spot for brightness and steadyness, even when dimmed
unsigned long clockFrequencyHz = 16000000UL;
clockFrequencyHz /= 128UL;
// clock cycles to get the desired period:
unsigned long clockCyclesForTimerPeriod = clockFrequencyHz / timerFrequencyHz;
// overflow the 8-bit counter:
timerCounter2 = 255 - clockCyclesForTimerPeriod;
TCNT2 = timerCounter2;
sei();
Wire.begin(WIRE_DEVICE_ADDRESS);
Wire.onRequest(wire_Request);
Wire.onReceive(wire_Receive);
#ifdef DEMO
demoTimestamp = millis();
#endif
}
void loop()
{
if (processBalance)
{
setCorrection((matrixWriteA)?matrixDataA:matrixDataB, 0);
processBalance = false;
balanceRecieved = true;
}
else if (processFast)
{
doFastCommand();
processFast = false;
}
else if (processClear)
{
memset((matrixWriteA)?matrixDataA:matrixDataB, 0x00, MATRIX_ROWS*MATRIX_ROW_CHANNELS);
processClear = false;
}
#ifdef DEMO
else if (!balanceRecieved)
{
unsigned long now = millis();
if (now - demoTimestamp >= demoTimeout)
{
// kick demo animation
demoTimestamp = now;
byte* pChannel = (matrixWriteA)?matrixDataA:matrixDataB;
if (demoStep < 20)// first frames are solid/dimmed
setCorrection(defaultCorrection, 4-(demoStep%5));
for (int row = 0; row < MATRIX_ROWS; row++)
for (int col = 0; col < MATRIX_COLS; col++)
{
if (demoStep < 20)
{
int index = 8*(demoStep/5);
*(pChannel++) = demoR >> index;
*(pChannel++) = demoG >> index;
*(pChannel++) = demoB >> index;
}
else
{
int index = 8*min(min(MATRIX_ROWS - row - 1, row),
min(MATRIX_COLS - col - 1, col));
*(pChannel++) = demoR >> index;
*(pChannel++) = demoG >> index;
*(pChannel++) = demoB >> index;
}
}
demoStep++;
matrixWriteA = !matrixWriteA;
if (demoR == 0xFF0000FFUL)
demoTimeout = 500UL;// dwell on first frames
else
demoTimeout = 200UL;
if (demoStep > 20)
{
demoR = (demoR >> 8) | (random(0xFF) << 24);
demoG = (demoG >> 8) | (random(0xFF) << 24);
demoB = (demoB >> 8) | (random(0xFF) << 24);
}
}
}
#endif
}
有演示图或者视频吗 木子呢 发表于 2024-4-15 11:44
有演示图或者视频吗
【全彩8*8点阵屏动态霓虹灯】 https://www.bilibili.com/video/BV1Dw4m117rZ/?share_source=copy_web&vd_source=73065ad2a92df7535b0d65ddc215c2bd
页:
[1]