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