74HC595驱动点阵屏(24_24)

2019-04-13 14:55发布

项目开发中遇到的问题: 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即可