74HC595驱动点阵屏(24_24)

项目中使用74HC595驱动24x24点阵屏遇到上电显示乱码的挑战。为解决此问题,尝试了三种方法:1.反相RCK信号;2.使用单片机控制OE;3.增加C26电容值。最终选择增大C26电容的方法成功避免595在上电时的误输出。硬件设计中,点阵屏行低电平亮,列高电平亮,并利用MOS管进行反向驱动。代码实现包括74hc595Led.c和74hc595Led.h,通过WriteColumnScan接口更新显示数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

项目开发中遇到的问题:

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
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Flipped--0228

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值