项目开发中遇到的问题:
1、上电瞬间点阵屏显示乱码问题:
猜测:由于BK3431Q芯片加电时所有I/O为高电平,加电时可能595上电比BK3431Q快,所以上电被认为是一个正脉冲跳变,结果595内部的寄存器初始值被输出,网上看论坛别人给出的解决方案如下:
1.试试RCK反相后再进595,这样BK3431Q上电时的脉冲反相后成为负的,使595不输出.
2.OE用单片机I/O控制,由于上电时BK3431Q
为高电平,所以无输出,然后程序控制595输出.
3.加大C26的值,让595的OE输出比51复位慢.
加粗的是本人采用的解决办法
硬件电路图:
点阵屏是在网上购置的现成的32*32的点阵改的24*24,行低电平灯亮,列高电平灯亮(由于列用到了MOS管反向,实际控制中单片机的相应位送低电平)
由于硬件上的限制,此点阵屏只能列扫描,mos管才能发挥作用,如若用行扫描,led灯显示亮度会很弱
字模取模方式如下图所示:
74hc595Led.c源代码:
#include "gpio.h"
#include "74hc595Led.h"
#include "BK3435_reg.h"
#include "uart.h"
#include "app_task.h"
#define HC595_SH_CLK 0X13 //74HC595的时钟
#define HC595_DS_DATA 0X33 //74HC595的数据
#define HC595_ST_LATCH 0x12 //74HC595的锁存
#define SCL_HIGH() gpio_set(HC595_SH_CLK,1)
#define SCL_LOW() gpio_set(HC595_SH_CLK,0)
#define SDA_HIGH() gpio_set(HC595_DS_DATA,1)
#define SDA_LOW() gpio_set(HC595_DS_DATA,0)
#define LATCH_HIGH() gpio_set(HC595_ST_LATCH,1)
#define LATCH_LOW() gpio_set(HC595_ST_LATCH,0)
#define SDA_SetInput() gpio_config(HC595_DS_DATA,INPUT,PULL_NONE)
#define SDA_SetOutput() gpio_config(HC595_DS_DATA,OUTPUT,PULL_NONE)
#define SDA_READ() gpio_get_input(HC595_DS_DATA)
bool StartDelayFlag = 0; // 1表示延时 0 表示不延时
DisplayTag DisplayTagFlag = NoFlag;
//uint8_t TempBuf[48] = {0};
bool DisplayModeChangeFlag = 0;
DisplayContent DisplayBuf[ARRAY_RANK_NUM] =
{
{
RIGHT2LEFT_COLUMN_SCAN_DISPLAY_MODE,
5,
0x01,
#if 1
{0x00,0x00,0x00,0x00,0x00,0x08,0x00,0xE1,0x8C,0x01,0x23,0x88,0x06,0x25,0x18,0x38,
0x59,0x10,0x10,0x61,0x10,0x01,0xC2,0x20,0x01,0x82,0x20,0x01,0x00,0x20,0x03,0xFF,
0xFE,0x01,0xFF,0xFE,0x01,0x00,0x40,0x01,0x01,0x80,0x01,0x06,0x00,0x3F,0xFC,0x00,
0x3E,0x08,0x00,0x01,0x0C,0x00,0x01,0x07,0x04,0x01,0x03,0x06,0x03,0xFF,0xFE,0x03,
0xFF,0xFC,0x00,0x00,0x00,0x00,0x00,0x00}/*"纳",0*/
/* (24 X 24 , 宋体 ) */
#else
{0x40,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/*"未命名文件",0*/
/* (24 X 24 ) */
#endif
},
{
DOWN2UP_LINE_SCAN_DISPLAY_MODE,
5,
0x1,
{0x00,0x00,0x00,0x00,0x00,0x80,0x01,0x01,0x00,0x01,0x06,0x00,0x21,0x08,0x00,0x1D,
0x3F,0xFE,0x09,0xF0,0x00,0x03,0x98,0x00,0x01,0x0E,0x00,0x01,0x00,0x80,0x01,0x10,
0x80,0x21,0x10,0x80,0x19,0x10,0x80,0x1D,0x10,0x80,0x01,0xFF,0xFE,0x01,0xFF,0xFE,
0x06,0x10,0x80,0x19,0x10,0x80,0x31,0x10,0x80,0x21,0x30,0x80,0x02,0x11,0x00,0x00,
0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00}/*"祥",0*/
/* (24 X 24 , 宋体 ) */
},
{
UP2DOWN_LINE_SCAN_DISPLAY_MODE,
5,
0x01,
{0x00,0x00,0x00,0x00,0x00,0x20,0x08,0x40,0x40,0x08,0x41,0x80,0x08,0x46,0x00,0x08,
0x5C,0x00,0x1F,0xFF,0xFE,0x1F,0xFF,0xFE,0x10,0x48,0x00,0x30,0x8C,0x00,0x10,0x86,
0x80,0x00,0x00,0x80,0x00,0x20,0x80,0x04,0x10,0x80,0x03,0x1C,0x80,0x03,0x01,0x00,
0x00,0x01,0x00,0x00,0x01,0x00,0x3F,0xFF,0xFE,0x20,0x01,0x00,0x00,0x02,0x00,0x00,
0x06,0x00,0x00,0x02,0x00,0x00,0x00,0x00}/*"科",0*/
/* (24 X 24 , 宋体 ) */
},
{
LEFT2RIGHT_COLUMN_SCAN_DISPLAY_MODE,
5,
0x01,
{0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x06,0x00,0x01,0x04,0x04,0x01,0x04,0x06,0x7F,
0xFF,0xFE,0x3F,0xFF,0xFC,0x21,0x08,0x00,0x02,0x10,0x02,0x02,0x10,0x02,0x01,0x10,
0x02,0x01,0x10,0x04,0x01,0x1C,0x08,0x01,0x13,0x08,0x01,0x10,0xD0,0x3F,0xF0,0x30,
0x21,0x10,0x70,0x01,0x11,0xC8,0x01,0x17,0x0C,0x01,0x1C,0x04,0x02,0x10,0x06,0x02,
0x00,0x06,0x00,0x00,0x04,0x00,0x00,0x00}/*"技",0*/
/* (24 X 24 , 宋体 ) */
}
};
uint8_t Mould[3]; //控制该列的取模值,低电平亮灯,每个模组16行,占2字节 //行
uint8_t upright[3]; //控制某一列,高电平亮灯,每个模组16列,占2字节 //列
uint8_t LED2X64[LED2X64LEN] = {0}; //开辟缓存空间,被定时器随时调用。每列两个字节,多加2个用于移位操作。
uint8_t DisplayTotal =0; //根据APP 发过来的数据随时改变
uint8_t CharDisplayInd1 = 0; //记录汉字索引
uint8_t CharDisplayInd2 = 0; //记录汉字点阵索引
ScanDisplay StartDisplayFlag = NoScan;
uint8_t DelayDisplayNextNUM = 0;
uint8_t DelayDisplayNextNumLimit = 0;
//======================================================================================
//发送数据到595芯片
//======================================================================================
void HC595WriteLineScan(void) //74HC595发送数据。行用来扫描
{
uint8_t i,j=1;
static uint8_t DisplayInd_1 = 0;
static uint32_t kkk_1=0x1; //用于16行轮流控制 这个初始值决定从哪一行开始扫描
//Mould[3]=~LED2X64[DisplayInd_1+3]; //i=0,把缓存的第01号字节发送到第一个模组的最右边的8位。
Mould[2]=~LED2X64[DisplayInd_1+2];
Mould[1]=~LED2X64[DisplayInd_1+1]; //i=0,把缓存的第01号字节发送到第一个模组的最右边的8位。
Mould[0]=~LED2X64[DisplayInd_1+0]; //i=0,把缓存的第00号字节发送到第一个模组的最左边的8位。
//upright[3]=~((kkk_1>>24)&0xff);
upright[2]=~((kkk_1>>16)&0xff);
upright[1]=~((kkk_1>>8)&0xff); //16位变量KKK,取高8位。控制第一个模组的0~7行。
upright[0]=~(kkk_1&0xff); //16位变量KKK,取低8位。控制第一个模组的8~15行。
//循环控制0~16行
if(kkk_1&0x800000)
kkk_1 = (kkk_1<<1)|0x01;
else
kkk_1 = (kkk_1<<1);
DisplayInd_1+=3;
DisplayInd_1=DisplayInd_1%72;
SDA_HIGH();
SCL_HIGH();
LATCH_LOW();
for(i=0;i<8;i++) //发送给每个模组的 U4 ,低电平整行可以亮,高电平整行全灭。
{
SCL_LOW();
//if (Mould[j*3-3]&0x80)
if (Mould[j*3-3]&0x01)
SDA_HIGH();
else
SDA_LOW();
//Mould[j*3-3]<<=1;
Mould[j*3-3]>>=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U3 ,低电平整行可以亮,高电平整行全灭。
{
SCL_LOW();
//if (Mould[j*3-2]&0x80)
if (Mould[j*3-2]&0x01)
SDA_HIGH();
else
SDA_LOW();
//Mould[j*3-2]<<=1;
Mould[j*3-2]>>=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U4 ,低电平整行可以亮,高电平整行全灭。
{
SCL_LOW();
//if (Mould[j*3-1]&0x80)
if (Mould[j*3-1]&0x01)
SDA_HIGH();
else
SDA_LOW();
//Mould[j*3-1]<<=1;
Mould[j*3-1]>>=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U2 ,高电平整列可以亮,低电平整列灭。
{
SCL_LOW(); //时钟拉低
//if(upright[j*3-1]&0x1) //从最后一个字节开始,先高位后低位。
if(upright[j*3-1]&0x80)
SDA_HIGH();
else
SDA_LOW();
//upright[j*3-1]>>=1; //字节左移
upright[j*3-1]<<=1;
SCL_HIGH(); //时钟上升沿拷贝
}
for(i=0;i<8;i++) //发送给每个模组的 U1 ,高电平整列可以亮,低电平整列灭。
{
SCL_LOW();
//if (upright[j*3-2]&0x1) //先送低位
if (upright[j*3-2]&0x80)
SDA_HIGH();
else
SDA_LOW();
//upright[j*3-2]>>=1;
upright[j*3-2]<<=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U2 ,高电平整列可以亮,低电平整列灭。
{
SCL_LOW(); //时钟拉低
//if(upright[j*3-3]&0x1) //从最后一个字节开始,先高位后低位。
if(upright[j*3-3]&0x80)
SDA_HIGH();
else
SDA_LOW();
//upright[j*3-3]>>=1; //字节左移
upright[j*3-3]<<=1;
SCL_HIGH(); //时钟上升沿拷贝
}
LATCH_HIGH(); //锁存脉冲信号,上升沿。
SDA_HIGH(); //延时
LATCH_LOW(); //锁存脉冲信号复位。
}
void HC595WriteColumnScan(void) //74HC595发送数据。列用来扫描
{
uint8_t i,j=1;
static uint8_t DisplayInd = 0;
static uint32_t kkk=0x800000; //用于16列轮流控制
//Mould[3]=~LED2X64[DisplayInd+3]; //DisplayInd=0,把缓存的第03号字节发送到最左边的上8位。
Mould[2]=~LED2X64[DisplayInd+2];
Mould[1]=~LED2X64[DisplayInd+1];
Mould[0]=~LED2X64[DisplayInd+0]; //DisplayInd=0,把缓存的第00号字节发送到最左边的上8位。
//每个都取反是因为硬件有MOS管反向
// upright[3]=~((kkk>>24)&0xff); //取高8位。控制的0~7列。
upright[2]=~((kkk>>16)&0xff);
upright[1]=~((kkk>>8)&0xff);
upright[0]=~(kkk&0xff); //取低8位。控制24~31列。
//循环控制0~31列
if(kkk&0x1)
kkk = (kkk>>1)|0x800000;
else
kkk = (kkk>>1);
DisplayInd+=3;
DisplayInd=DisplayInd%72;
SDA_HIGH();
SCL_HIGH();
LATCH_LOW();
for(i=0;i<8;i++) //发送给每个模组的 U7 ,高电平整列可以亮,低电平整列灭。
{
SCL_LOW(); //时钟拉低
if(upright[j*3-1]&0x80) //先高位后低位。
SDA_HIGH();
else
SDA_LOW();
upright[j*3-1]<<=1; //字节左移
SCL_HIGH(); //时钟上升沿拷贝
}
for(i=0;i<8;i++) //发送给每个模组的 U6 ,高电平整列可以亮,低电平整列灭。
{
SCL_LOW();
if (upright[j*3-2]&0x80)
SDA_HIGH();
else
SDA_LOW();
upright[j*3-2]<<=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U5,高电平整列可以亮,低电平整列灭。
{
SCL_LOW();
if (upright[j*3-3]&0x80)
SDA_HIGH();
else
SDA_LOW();
upright[j*3-3]<<=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U3 ,低电平整行可以亮,高电平整行全灭。
{
SCL_LOW();
//if (Mould[j*3-1]&0x80)
if (Mould[j*3-1]&0x1)
SDA_HIGH();
else
SDA_LOW();
//Mould[j*3-1]<<=1;
Mould[j*3-1]>>=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U2 ,低电平整行可以亮,高电平整行全灭。
{
SCL_LOW();
//if (Mould[j*3-2]&0x80)
if (Mould[j*3-2]&0x1)
SDA_HIGH();
else
SDA_LOW();
//Mould[j*3-2]<<=1;
Mould[j*3-2]>>=1;
SCL_HIGH();
}
for(i=0;i<8;i++) //发送给每个模组的 U1 ,低电平整行可以亮,高电平整行全灭。
{
SCL_LOW();
//if (Mould[j*3-3]&0x80)
if (Mould[j*3-3]&0x1)
SDA_HIGH();
else
SDA_LOW();
//Mould[j*3-3]<<=1;
Mould[j*3-3]>>=1;
SCL_HIGH();
}
LATCH_HIGH(); //锁存脉冲信号,上升沿。
SDA_HIGH(); //延时
LATCH_LOW();
}
/*************************************
* 闪烁模式:有小变大,有大变小 右移、右移 、下飘、上移
*时间
*************************************/
void WjInitDisplayContent(void)
{
uint8_t i;
}
void WjClearDisplay(void)
{
uint8_t i;
//清理显示缓冲区
for(i=0;i= DelayDisplayNextNumLimit)
{
DelayDisplayNextNUM = 0;
StartDelayFlag = 0;
if (CharDisplayInd1 == 0) //说明是最后一个 中间延时一会重新开始显示
{
DisplayTagFlag = EndFlag;
}
DisplayBuf[3] = DisplayBuf[0];
}
}
//检测下一帧数据,由于连续向左、向右、向上、向下函数调用
static void WjSeriesDisplayDetectNextFrame(void)
{
uint8_t i;
switch(DisplayBuf[3].Mode)
{
case SERIES_RIGHT_SHIFT_DISPLAY_MODE:
for(i=LED2X64LEN-1;i>2;i--) //每次调用函数时让TransformObjBuf数组里面的数据循环右移一列赋值给LED2X64数组
{
LED2X64[i] = LED2X64[i-3];
}
//UART_PRINTF("#####wj -->>StartDelayFlag = %d
",StartDelayFlag);
if (!StartDelayFlag)
{
LED2X64[i-2] = DisplayBuf[3].DisplayBuf[ARRAY_ROW_NUM-1-CharDisplayInd2-2]; //i = 1 -->>1
LED2X64[i-1] = DisplayBuf[3].DisplayBuf[ARRAY_ROW_NUM-1-CharDisplayInd2-1]; //i = 1; -->>0
LED2X64[i] = DisplayBuf[3].DisplayBuf[ARRAY_ROW_NUM-1-CharDisplayInd2]; //i = 1 -->>1
CharDisplayInd2 += 3;
}
else
{
LED2X64[i-2] = 0x0;
LED2X64[i-1] = 0x0;
LED2X64[i] = 0x0;
}
break;
case SERIES_LEFT_SHIFT_DISPLAY_MODE:
for(i=0;i>StartDelayFlag = %d
",StartDelayFlag);
if(!StartDelayFlag)
{
LED2X64[i] = DisplayBuf[3].DisplayBuf[CharDisplayInd2];
LED2X64[i+1] = DisplayBuf[3].DisplayBuf[CharDisplayInd2+1];
LED2X64[i+2] = DisplayBuf[3].DisplayBuf[CharDisplayInd2+2];
CharDisplayInd2 += 3;
}
else
{
LED2X64[i+2] = 0x0;
LED2X64[i+1] = 0x0;
LED2X64[i] = 0x0;
}
break;
default:
break;
}
if (CharDisplayInd2 >=ARRAY_ROW_NUM) //一个汉字显示完毕,进入下一个汉字赋值
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
}
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
if ((DisplayBuf[3].Mode == DisplayBuf[0].Mode)&&(CharDisplayInd1 != 0))
{
DelayDisplayNextNumLimit = SERIES_DISPLAY_DELAY_NEXT_CHAR_NUM;
}
else
{
DelayDisplayNextNumLimit = DISORDER_DISPLAY_DELAY_NEXT_CHAR_NUM;
}
//开启调用延时函数
StartDelayFlag = 1;
DelayDisplayNextNUM = 0;
}
}
void WjNoDisplay(void)
{
memset(LED2X64,0,ARRAY_ROW_NUM);
CharDisplayInd1++;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //闪到最后一个汉字接着闪第一个
{
//开启调用延时函数,最后一个到第一个的显示时间拉长一点
CharDisplayInd1 = 0;
}
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//uart_send(DisplayBuf[0].DisplayBuf,128);
if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1;
DisplayBuf[3] = DisplayBuf[0];
}
}
void WjStaticDisplay(void)
{
static bool flag = 0;
//if (!flag)
{
DisplayBuf[3] = DisplayBuf[0];
memcpy(LED2X64,DisplayBuf[3].DisplayBuf,ARRAY_ROW_NUM);
CharDisplayInd1++;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //闪到最后一个汉字接着闪第一个
{
//开启调用延时函数,最后一个到第一个的显示时间拉长一点
CharDisplayInd1 = 0;
}
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//uart_send(DisplayBuf[0].DisplayBuf,128);
if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1;
DisplayBuf[3] = DisplayBuf[0];
}
}
/*
else //解决相同两个字连着显示看不出闪烁效果
{
memset(LED2X64,0,LED2X64LEN);
}
flag = !flag;
*/
}
//Elem:需要移位的数组
// sum: 数组的大小
// k : 需要移位的位数
//uint8_t Tempbuf[3] = {0x00,0xE1,0x8C};
static uint8_t WjBitLeftShiftElem(uint8_t * Elem,uint8_t Sum,uint8_t k) //循环上移中调用
{
uint8_t i;
//exceedB: 本元素溢出值
//exceedA: 上一元素溢出值
uint8_t exceedA=0,exceedB=0;
char Msk=0; //用于计算溢出位的掩码,如k=6时,其掩码值为00000011(二进制)
for (i=0;i<8-k;i++)
{
Msk=Msk|(1<0;i--)
{
exceedB=(Elem[i-1]&(~Msk))>>(8-k);//计算溢出数据
Elem[i-1]=(Elem[i-1]<>k)|exceedA;
//UART_PRINTF("Elem[%d] = 0X%x
",i-1,Elem[i]);
exceedA=(exceedB<<(8-k));
}
return exceedA;
}
//连续向左向右平移
void WjSeriesLeftRightShiftDisplay(void)
{
//UART_PRINTF("#####wj CharDisplayInd2 = %d StartDelayFlag = %d
",CharDisplayInd2 ,StartDelayFlag);
if((CharDisplayInd2 == 0)&&(!StartDelayFlag))
{
DisplayBuf[3] = DisplayBuf[0];
//UART_PRINTF("------------->>FUZHI_1");
}
WjSeriesDisplayDetectNextFrame();
}
//连续向上平移
void WjSeriesUpShiftDisplay(void)
{
uint8_t i;
for (i = 0;i < 24; i++)
{
WjBitLeftShiftElem(&LED2X64[3*i],3,1);
}
if (!StartDelayFlag)
{
for(i = 0;i< 24;i++)
{
LED2X64[3*i+2] = LED2X64[3*i+2]|(WjBitLeftShiftElem (&DisplayBuf[3].DisplayBuf[3*i],3,1));
}
CharDisplayInd2 += 3;
}
if (CharDisplayInd2 >= ARRAY_ROW_NUM/*+2*/)
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
//DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
}
//UART_PRINTF("######wj CharDisplayInd1 = %d
",CharDisplayInd1);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
if ((DisplayBuf[3].Mode == DisplayBuf[0].Mode)&&(CharDisplayInd1 != 0))
{
DelayDisplayNextNumLimit = SERIES_DISPLAY_DELAY_NEXT_CHAR_NUM;
}
else
{
DelayDisplayNextNumLimit = DISORDER_DISPLAY_DELAY_NEXT_CHAR_NUM;
}
//开启调用延时函数
StartDelayFlag = 1;
DelayDisplayNextNUM = 0;
}
}
//连续向下平移
void WjSeriesDownShiftDisplay()
{
uint8_t i;
for (i = 0;i < 24; i++)
{
WjBitRightShiftElem(&LED2X64[3*i],3,1);
}
if (!StartDelayFlag)
{
for(i = 0;i< 24;i++)
{
LED2X64[3*i] = LED2X64[3*i]|(WjBitRightShiftElem (&DisplayBuf[3].DisplayBuf[3*i],3,1));
}
CharDisplayInd2 += 3;
}
if (CharDisplayInd2 >= ARRAY_ROW_NUM/*+2*/)
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
//DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
}
//UART_PRINTF("######wj CharDisplayInd1 = %d
",CharDisplayInd1);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
if ((DisplayBuf[3].Mode == DisplayBuf[0].Mode)&&(CharDisplayInd1 != 0))
{
DelayDisplayNextNumLimit = SERIES_DISPLAY_DELAY_NEXT_CHAR_NUM;
}
else
{
DelayDisplayNextNumLimit = DISORDER_DISPLAY_DELAY_NEXT_CHAR_NUM;
}
//开启调用延时函数
StartDelayFlag = 1;
DelayDisplayNextNUM = 0;
}
}
//向左平移
void WjLeftShiftDisplay(void)
{
uint8_t i;
for(i=0;i>StartDelayFlag = %d
",StartDelayFlag);
if (CharDisplayInd2 < ARRAY_ROW_NUM) //
{
LED2X64[i] = DisplayBuf[3].DisplayBuf[CharDisplayInd2];
LED2X64[i+1] = DisplayBuf[3].DisplayBuf[CharDisplayInd2+1];
LED2X64[i+2] = DisplayBuf[3].DisplayBuf[CharDisplayInd2+2];
}
else
{
LED2X64[i] = 0;
LED2X64[i+1] = 0;
LED2X64[i+2] = 0;
}
CharDisplayInd2 += 3;
//UART_PRINTF("###### --->> CharDisplayInd2 = %d
",CharDisplayInd2);
if (CharDisplayInd2 >=ARRAY_ROW_NUM/*+2*/) //一个汉字显示完毕,进入下一个汉字赋值
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//向右平移
void WjRightShiftDisplay(void)
{
uint8_t i;
for(i=LED2X64LEN-1;i>2/*1*/;i--) //每次调用函数时让TransformObjBuf数组里面的数据循环右移一列赋值给LED2X64数组
{
LED2X64[i]= LED2X64[i-3];
}
LED2X64[i-2] = DisplayBuf[3].DisplayBuf[/*31*/71-CharDisplayInd2-2]; //i = 1; -->>0
LED2X64[i-1] = DisplayBuf[3].DisplayBuf[/*31*/71-CharDisplayInd2-1]; //i = 1; -->>0
LED2X64[i] = DisplayBuf[3].DisplayBuf[/*31*/71-CharDisplayInd2]; //i = 1 -->>1
CharDisplayInd2 += 3;
if (CharDisplayInd2 >=ARRAY_ROW_NUM) //一个汉字显示完毕,进入下一个汉字赋值
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//向上平移
void WjUpShiftDisplay(void)
{
uint8_t i;
for (i = 0;i < 24; i++)
{
WjBitLeftShiftElem(&LED2X64[3*i],3,1);
}
for(i = 0;i< 24;i++)
{
LED2X64[3*i+2] = LED2X64[3*i+2]|(WjBitLeftShiftElem (&DisplayBuf[3].DisplayBuf[3*i],3,1));
}
CharDisplayInd2 += 3;
if (CharDisplayInd2 >= ARRAY_ROW_NUM/*+2*/)
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
}
//UART_PRINTF("######wj CharDisplayInd1 = %d
",CharDisplayInd1);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//向下平移
void WjDownShiftDisplay(void)
{
uint8_t i;
for (i = 0;i < 24; i++)
{
WjBitRightShiftElem(&LED2X64[3*i],3,1);
}
for(i = 0;i< 24;i++)
{
LED2X64[3*i] = LED2X64[3*i]|(WjBitRightShiftElem (&DisplayBuf[3].DisplayBuf[3*i],3,1));
}
CharDisplayInd2 += 3;
if (CharDisplayInd2 >= ARRAY_ROW_NUM/*+2*/)
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
}
//UART_PRINTF("######wj CharDisplayInd1 = %d
",CharDisplayInd1);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//左右对开
void WjLeftRightOpenDisplay(void)
{
uint8_t i;
static uint8_t LeftInd = ARRAY_ROW_NUM/2-1/*15*//*35*/;
static uint8_t RightInd = ARRAY_ROW_NUM/2/*16*//*36*/;
LED2X64[LeftInd] = DisplayBuf[3].DisplayBuf[LeftInd];
LED2X64[RightInd]= DisplayBuf[3].DisplayBuf[RightInd];
if(LeftInd > 0)
LeftInd--;
RightInd++;
for(i=LeftInd;i>0;i--)
{
LED2X64[i]= 0;
}
for(i = RightInd;i ARRAY_ROW_NUM) //一个汉字显示结束
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
LeftInd = ARRAY_ROW_NUM/2-1/*15*//*35*/;
RightInd = ARRAY_ROW_NUM/2/*16*//*36*/;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//左右闭合
void WjLeftRightCloseDisplay(void)
{
uint8_t i;
static uint8_t LeftInd = 0;
static uint8_t RightInd = ARRAY_ROW_NUM-1;
LED2X64[LeftInd] = DisplayBuf[3].DisplayBuf[LeftInd];
LED2X64[RightInd]= DisplayBuf[3].DisplayBuf[RightInd];
LeftInd++;
RightInd--;
//UART_PRINTF("###### wj LeftInd = %d RightInd = %d
",LeftInd,RightInd);
CharDisplayInd2 = 1; //在这里没有任何意思,只是表示正在给一个汉字描点
if (LeftInd >= (ARRAY_ROW_NUM/2)) //一个汉字显示结束
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
LeftInd = 0;
RightInd = ARRAY_ROW_NUM-1;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
else
{
for(i=LeftInd;i>(ARRAY_ROW_NUM/2);i++)
{
LED2X64[i]= 0;
}
for(i = RightInd;i<(ARRAY_ROW_NUM/2);i--)
{
LED2X64[i]= 0;
}
}
}
//上下对开
void WjUpDownOpenDisplay(void)
{
uint8_t i;
static uint32_t LineMask= 0x001800;
uint32_t TempValue = 0;
for (i = 0;i < 24; i++)
{
TempValue = ((uint32_t)(DisplayBuf[3].DisplayBuf[3*i])<<16)|
((uint32_t)(DisplayBuf[3].DisplayBuf[3*i+1])<<8)|
(uint32_t)(DisplayBuf[3].DisplayBuf[3*i+2]);
TempValue = LineMask&TempValue;
LED2X64[3*i] = (uint8_t)(TempValue>>16);
LED2X64[3*i+1] = (uint8_t)(TempValue>>8);
LED2X64[3*i+2] = (uint8_t)(TempValue);
}
LineMask = (LineMask<<1)|(LineMask>>1);
if (LineMask > 0xffffff)
{
LineMask = 0x001800;
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
void WjUpDownCloseDisplay(void)
{
uint8_t i;
static uint32_t LineMask= 0x800001;
uint32_t TempValue = 0;
for (i = 0;i < 24; i++)
{
TempValue = ((uint32_t)(DisplayBuf[3].DisplayBuf[3*i])<<16)|
((uint32_t)(DisplayBuf[3].DisplayBuf[3*i+1])<<8)|
(uint32_t)(DisplayBuf[3].DisplayBuf[3*i+2]);
TempValue = LineMask&TempValue;
LED2X64[3*i] = (uint8_t)(TempValue>>16);
LED2X64[3*i+1] = (uint8_t)(TempValue>>8);
LED2X64[3*i+2] = (uint8_t)(TempValue);
}
LineMask = LineMask|(0xffffff&(LineMask<<1))|(LineMask>>1);
CharDisplayInd2+=6;
//UART_PRINTF("LineMask = 0x%x CharDisplayInd2 = %d
",LineMask,CharDisplayInd2);
if (CharDisplayInd2 > ARRAY_ROW_NUM)
{
LineMask = 0x800001;
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//从左到右扫描显示
void WjLeft2RightScanDisplay(void)
{
uint8_t i;
LED2X64[CharDisplayInd2] = DisplayBuf[3].DisplayBuf[CharDisplayInd2];
LED2X64[CharDisplayInd2+1]= DisplayBuf[3].DisplayBuf[CharDisplayInd2+1];
LED2X64[CharDisplayInd2+2]= DisplayBuf[3].DisplayBuf[CharDisplayInd2+2];
CharDisplayInd2 += 3;
if ((CharDisplayInd2 > ARRAY_ROW_NUM)) //一个汉字显示结束
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//从右到左扫描显示
void WjRight2LeftScanDisplay(void)
{
uint8_t i;
LED2X64[ARRAY_ROW_NUM - 1-CharDisplayInd2]= DisplayBuf[3].DisplayBuf[ARRAY_ROW_NUM - 1-CharDisplayInd2];
LED2X64[ARRAY_ROW_NUM - 2-CharDisplayInd2]= DisplayBuf[3].DisplayBuf[ARRAY_ROW_NUM - 2-CharDisplayInd2];
LED2X64[ARRAY_ROW_NUM - 3-CharDisplayInd2]= DisplayBuf[3].DisplayBuf[ARRAY_ROW_NUM - 3-CharDisplayInd2];
CharDisplayInd2 += 3;
if ((CharDisplayInd2 >= ARRAY_ROW_NUM)) //一个汉字显示结束
{
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
//从上到下扫描显示
void WjUp2DownScanDisplay(void)
{
uint8_t i;
static uint32_t LineMask= 0x800000;
uint32_t TempValue = 0;
for (i = 0;i < 24; i++)
{
TempValue = ((uint32_t)(DisplayBuf[3].DisplayBuf[3*i])<<16)|
((uint32_t)(DisplayBuf[3].DisplayBuf[3*i+1])<<8)|
(uint32_t)(DisplayBuf[3].DisplayBuf[3*i+2]);
TempValue = LineMask&TempValue;
LED2X64[3*i] = (uint8_t)(TempValue>>16);
LED2X64[3*i+1] = (uint8_t)(TempValue>>8);
LED2X64[3*i+2] = (uint8_t)(TempValue);
}
CharDisplayInd2+=3;
LineMask = LineMask|(LineMask>>1);
if (CharDisplayInd2 > ARRAY_ROW_NUM)
{
LineMask = 0x800000;
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
void WjDown2UpScanDisplay(void)
{
uint8_t i;
static uint32_t LineMask= 0x1;
uint32_t TempValue = 0;
for (i = 0;i < 24; i++)
{
TempValue = ((uint32_t)(DisplayBuf[3].DisplayBuf[3*i])<<16)|
((uint32_t)(DisplayBuf[3].DisplayBuf[3*i+1])<<8)|
(uint32_t)(DisplayBuf[3].DisplayBuf[3*i+2]);
TempValue = LineMask&TempValue;
LED2X64[3*i] = (uint8_t)(TempValue>>16);
LED2X64[3*i+1] = (uint8_t)(TempValue>>8);
LED2X64[3*i+2] = (uint8_t)(TempValue);
}
CharDisplayInd2+=3;
LineMask = LineMask|(LineMask<<1);
if (CharDisplayInd2 > ARRAY_ROW_NUM)
{
LineMask = 0x1;
CharDisplayInd1++;
CharDisplayInd2 = 0;
DisplayTagFlag = MidFlag;
if (CharDisplayInd1 >= DisplayTotal) //已经是最后一个汉字了
{
CharDisplayInd1 = 0; //在这里等于0 说明是最后一个汉字
//DisplayTagFlag = EndFlag;
}
//UART_PRINTF("###### --->>CharDisplayInd1 = %d CharDisplayInd2 = %d
",CharDisplayInd1,CharDisplayInd2);
flash_read_data((uint8_t *)DisplayBuf,
FLASH_STORE_LED_ADDR+CharDisplayInd1*FLASH_STORE_LED_ADDR_UNIT, FLASH_STORE_LED_ADDR_UNIT);
//if(DisplayBuf[3].Mode!= DisplayBuf[0].Mode) //在这里判断如果显示模式变化。在进入下次调用模式切换时清除显示缓冲
{
DisplayModeChangeFlag = 1; //该种不管模式切不切,每次都需要这个变量等于1去清屏
DisplayBuf[3] = DisplayBuf[0]; //20180716
}
}
}
void WjLedDisplayModeSelectFun(void)
{
if (StartDelayFlag)
{
WjDelayDisplayNextCharFun();
}
if (DisplayModeChangeFlag)
{
memset(LED2X64,0,LED2X64LEN);
CharDisplayInd2 = 0;
DisplayModeChangeFlag = 0;
}
UART_PRINTF("DisplayBuf[3].Mode = %d
",DisplayBuf[3].Mode);
switch (DisplayBuf[3].Mode)
{
case SERIES_LEFT_SHIFT_DISPLAY_MODE:
case SERIES_RIGHT_SHIFT_DISPLAY_MODE:
WjSeriesLeftRightShiftDisplay();
//StartDisplayFlag = ColumnScan;
break;
case SERIES_UP_SHIFT_DISPLAY_MODE:
WjSeriesUpShiftDisplay();
//StartDisplayFlag = ColumnScan;
break;
case SERIES_DOWN_SHIFT_DISPLAY_MODE:
WjSeriesDownShiftDisplay();
//StartDisplayFlag = ColumnScan;
break;
case STATIC_DISPLAY_MODE:
WjStaticDisplay();
//StartDisplayFlag = ColumnScan;
break;
case LEFT_SHIFT_DISPLAY_MODE: //向左平移
WjLeftShiftDisplay();
//StartDisplayFlag = ColumnScan;
break;
case RIGHT_SHIFT_DISPLAY_MODE: //向右平移
WjRightShiftDisplay();
//StartDisplayFlag = ColumnScan;
break;
case UP_SHIFT_DISPLAY_MODE: //向上平移
WjUpShiftDisplay();
//StartDisplayFlag = ColumnScan;
break;
case DOWN_SHIFT_DISPLAY_MODE: //向下平移
WjDownShiftDisplay();
//StartDisplayFlag = ColumnScan;
break;
case LEFT_RIGHT_OPEN_DISPLAY_MODE: //左右对开
WjLeftRightOpenDisplay();
//StartDisplayFlag = ColumnScan;
break;
case LEFT_RIGHT_CLOSE_DISPLAY_MODE: //左右闭合
WjLeftRightCloseDisplay();
//StartDisplayFlag = ColumnScan;
break;
case UP_DOWN_OPEN_DISPLAY_MODE: //上下对开
WjUpDownOpenDisplay();
//StartDisplayFlag = ColumnScan;
break;
case UP_DOWN_CLOSE_DISPLAY_MODE: //上下闭合
WjUpDownCloseDisplay();
//StartDisplayFlag = ColumnScan;
break;
case LEFT2RIGHT_COLUMN_SCAN_DISPLAY_MODE: //向右镭射
WjLeft2RightScanDisplay();
//StartDisplayFlag = ColumnScan;
break;
case RIGHT2LEFT_COLUMN_SCAN_DISPLAY_MODE: //向左镭射
WjRight2LeftScanDisplay();
//StartDisplayFlag = ColumnScan;
break;
case UP2DOWN_LINE_SCAN_DISPLAY_MODE: //向下镭射
WjUp2DownScanDisplay();
//StartDisplayFlag = ColumnScan;
break;
case DOWN2UP_LINE_SCAN_DISPLAY_MODE: //向上镭射
WjDown2UpScanDisplay();
//StartDisplayFlag = ColumnScan;
break;
case NO_DISPLAY_MODE:
WjNoDisplay();
break;
default:
break;
}
}
void WjColumn2LineTransform(uint8_t *Obj,uint8_t *Src) //逐列顺向阴码-->> 逐行逆向阴码
{
uint8_t SrcInd = 0;
uint8_t SrcBitInd = 0;
uint8_t ObjInd = 0;
memset(Obj,0,ARRAY_ROW_NUM); //每次要清零
for(SrcBitInd = 0,ObjInd=0; SrcBitInd<8; ObjInd+=3,SrcBitInd++) //24*24上半部分
{
for(SrcInd = 0;SrcInd < 8; SrcInd++)
Obj[ObjInd] += ((Src[SrcInd*3]>>(7-SrcBitInd))&0x01) << SrcInd; //低位在前
//UART_PRINTF("0x%x",Obj[ObjInd]);
for(SrcInd = 0;SrcInd < 8;SrcInd++)
Obj[ObjInd+1] += ((Src[24+3*SrcInd]>>(7-SrcBitInd))&0x01)<>(7-SrcBitInd))&0x01)<>(7-SrcBitInd))&0x01) << SrcInd; //低位在前
//UART_PRINTF("0x%x",Obj[ObjInd]);
for(SrcInd = 0;SrcInd < 8;SrcInd++)
Obj[ObjInd+1] += ((Src[25+3*SrcInd]>>(7-SrcBitInd))&0x01)<>(7-SrcBitInd))&0x01)<>(7-SrcBitInd))&0x01) << SrcInd; //低位在前
//UART_PRINTF("0x%x",Obj[ObjInd]);
for(SrcInd = 0;SrcInd < 8;SrcInd++)
Obj[ObjInd+1] += ((Src[26+3*SrcInd]>>(7-SrcBitInd))&0x01)<>(7-SrcBitInd))&0x01)<
74hc595Led.h代码
#ifndef _74HC595LED_H_
#define _74HC595LED_H_
#define ARRAY_RANK_NUM 4
#define ARRAY_ROW_NUM 72 //32 //16*16点阵
#define SERIES_DISPLAY_END_TO_FIRST_DELAY 100
#define FLASH_STORE_TOTAL_ADDR 0x42000
#define FLASH_STORE_LED_ADDR 0x42100 //用的是扇区擦除,程序中只擦除了0x42000 -->0x43000一个扇区 == (0x43000-0x42100)/75 = 51个汉字
#define FLASH_STORE_LED_ADDR_UNIT 75 //struct DisplayContent 结构体的大小
#define LED2X64LEN 74 //34
typedef struct DisplayContent
{
//uint8_t Total; //需要显示的总条数
//uint8_t Colour; //显示颜 {MOD}
uint8_t Mode; //显示模式
uint8_t Speed; //显示速度 10ms的单位
uint8_t Time; //显示时间
uint8_t DisplayBuf[ARRAY_ROW_NUM]; //显示的点阵
}DisplayContent;
enum DisPlayMode
{
NO_DISPLAY_MODE,
STATIC_DISPLAY_MODE,
SERIES_LEFT_SHIFT_DISPLAY_MODE,
SERIES_RIGHT_SHIFT_DISPLAY_MODE,
SERIES_UP_SHIFT_DISPLAY_MODE,
SERIES_DOWN_SHIFT_DISPLAY_MODE,
LEFT_SHIFT_DISPLAY_MODE,
RIGHT_SHIFT_DISPLAY_MODE,
UP_SHIFT_DISPLAY_MODE,
DOWN_SHIFT_DISPLAY_MODE,
LEFT_RIGHT_OPEN_DISPLAY_MODE, //0x0a
LEFT_RIGHT_CLOSE_DISPLAY_MODE,
UP_DOWN_OPEN_DISPLAY_MODE,
UP_DOWN_CLOSE_DISPLAY_MODE,
LEFT2RIGHT_COLUMN_SCAN_DISPLAY_MODE,
RIGHT2LEFT_COLUMN_SCAN_DISPLAY_MODE,
UP2DOWN_LINE_SCAN_DISPLAY_MODE,
DOWN2UP_LINE_SCAN_DISPLAY_MODE
};
enum DelayDisplayNum
{
NO_DELAY_DISPLAY,
SERIES_DISPLAY_DELAY_NEXT_CHAR_NUM = 4,
DISORDER_DISPLAY_DELAY_NEXT_CHAR_NUM = 25, // 20 ==>>24_24 38 ==>> 32*32
END_DISPLAY_DELAY_NEXT_FRAME_NUM = 30
};
typedef enum DisplayStartMidEndFlag
{
NoFlag,
MidFlag,
EndFlag,
UpDataFlag
}DisplayTag;
typedef enum ScanDisplayFlag
{
NoScan,
ColumnScan,
LineScan
}ScanDisplay;
extern uint8_t Mould[3]; //控制该列的取模值,低电平亮灯,每个模组16行,占2字节 //行
extern uint8_t upright[3]; //控制某一列,高电平亮灯,每个模组16列,占2字节 //列
extern uint8_t LED2X64[LED2X64LEN]; //开辟缓存空间,被定时器随时调用。每列两个字节,多加2个用于移位操作。
extern uint8_t DisplayTotal;
extern uint8_t CharDisplayInd1;
extern uint8_t CharDisplayInd2;
extern ScanDisplay StartDisplayFlag;
extern bool StartDelayFlag;
extern DisplayTag DisplayTagFlag;
extern DisplayContent DisplayBuf[ARRAY_RANK_NUM];
void HC595WriteLineScan(void);
void HC595WriteColumnScan(void);
void WjLedDisplayModeSelectFun(void);
void WjColumn2LineTransform(uint8_t *Obj,uint8_t *Src);
#endif
在main.c的while循环中调用接口WriteColumnScan,把要显示的点阵数据复制给LED2X64数组ji即可