基于MC2302D的LED显示控制器

        在一块LED显示模块上发现了这个MC2302D控制芯片,查了一下,功能比较强大,控制使用也是比较简单,鉴于一开始没有找到太多的相关资料,故决定分享下来。

可以看到这个模块有很多的LED,都可以单独控制的哦,,控制芯片有两个MC2302D,控制线有4根,分别对应公共数据(DIN),公共时钟(CLK),片选1(STB1),片选2(STB2),VCC,GND不用说,电源引脚,供电范围2.7 - 5.5V。用来制作多功能仪表盘是再合适不过了,当然了,做个时钟也不错,不过只能用12小时制(为啥?因为最大18:88),配合功能窗指示上午,下午。

 这里我用的STM32主控,以下是具体引脚

 

介绍MC2302D

首先去官网把相应的数据手册下载下来,看一下相关功能,引脚等

前面介绍就这么多,大家可以看看,也没什么解释的,很容易理解

驱动时序

说白了和SPI一样,片选拉低,DIN数据在时钟线拉低时候赋值就写入,DOUT平时拉高,DIN写入一个字节后芯片输出DOUT数据,具体细节可看SPI协议。DIN是写命令和数据的,DOUT只是用来读按键状态的,如果未接按键,可不用管DOUT引脚。

协议说明

一共4条命令,分别对应置命令,置命令,地址置命令,示控制命令。

示设置命令,这部分和硬件设计有关,具体选择几位几段根据实际情况来,我这里使用了7位11段 (#0000_0011B)。

设置命令,设置数入方式置,地址增量方式置和方式设置。和功能需求有关,我这里只用到了写(#0100_0000B)。

地址设置命令,显示存器有地址置命令址,就是寻址偏移量,和硬件设计,以及功能显示有关,我这里从默认的00 开始寻址(#1100_0000B)。接着就是跟14 个8位数据,(根据官方给的程序,最多14段)。

显示控制命令,就是用来开启关闭显示器,同时可以设8级脉冲宽度(其实是7级,000时候关闭显示),对应不同的亮度,2/16最暗,14/16最亮。


 

 

官方示例代码

 

void Make_Signal()
{
	STB=1;
	CLK=1;
	
	for(i=0; i<8; i++)                                //command 1 (#0000_0011B) 
	{	
		STB=0;  
		CLK=0;
		if(i==1 || i==0)
			DIN=1;
		else
			DIN=0;
		CLK=1;
	}
	STB=1;
	
	for(i=0; i<8; i++)				//command 2 (#0100_0000B)
	{
		STB=0;
		CLK=0;
		if(i==6)
			DIN=1;
		else
			DIN=0;
		CLK=1;
	}
	STB=1;
	
	for(i=0; i<8; i++)				//command 3 (#1100_0000B)
	{
		STB=0;
		CLK=0;
		if(i==6 || i==7)
			DIN=1;
		else
			DIN=0;
		CLK=1;
	}
/*
	for(i=0; i<112; i++)				//data  14*8个,初始化赋0值
	{
		STB=0;
		CLK=0;
		DIN=0;
		CLK=1;
	}
	STB=1;
*/

	for(i=0; i<14; i++)		    //显示数据,操作seg_data[14]这个数组,即可进行相应的显示。   	
	{
		for(j=0; j<8; j++)
		{
			STB=0;
			CLK=0;

			DIN=seg_data[i] & comp_seg;
			CLK=1;
			seg_data[i]=seg_data[i]/2;
		}
	}
	STB=1;

	for(i=0; i<8; i++) 				//command 4 (#1000_0100B)
	{
		STB=0;
		CLK=0;
		switch(f_dimming) //PWM亮度调节  f_dimming  0-7  0默认最亮
		{
			case(0):
				if(i==3 || i==7|| i==2 || i==1|| i==0)
					DIN=1;
				else
					DIN=0;
			break;
			case(1):
				if(i==0 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(2):
				if(i==1 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(3):
				if(i==1 || i==0 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(4):
				if(i==2 ||i==3 || i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(5):
				if(i==2 || i==0 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(6):
				if(i==2 || i==1 ||i==3 || i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(7):
				if(i==2 || i==1 || i==0 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
		}
		CLK=1;

	}
	STB=1;
}

修改驱动代码

其实挺简单的,就是发送 cmd_1 ,cmd_2, cmd_3   14*8数据,cmd_4。稍加修改如下:

void Make_Signal_1(void)
{
uchar i, j;
uchar dis_data = 0;
	
	STB_1=1;
	CLK=1;
	
	for(i=0; i<8; i++)                                //command 1 (#0000_0011B) 
	{	
		STB_1=0;  
		CLK=0;
		if(i==1 || i==0)
			DIN=1;
		else
			DIN=0;
		CLK=1;
	}
	STB_1=1;
	
	for(i=0; i<8; i++)				//command 2 (#0100_0000B)
	{
		STB_1=0;
		CLK=0;
		if(i==6)
			DIN=1;
		else
			DIN=0;
		CLK=1;
	}
	STB_1=1;
	
	for(i=0; i<8; i++)				//command 3 (#1100_0000B)
	{
		STB_1=0;
		CLK=0;
		if(i==6 || i==7)
			DIN=1;
		else
			DIN=0;
		CLK=1;
	}
/*
	for(i=0; i<112; i++)				//data
	{
		STB_1=0;
		CLK=0;
		DIN=0;
		CLK=1;
	}
	STB_1=1;
*/

	for(i=0; i<14; i++)			    	
	{
		dis_data = seg_data_1[i];
		for(j=0; j<8; j++)
		{
			STB_1=0;
			CLK=0;
			DIN=dis_data & 0x01;
			CLK=1;
			dis_data =  dis_data>>1;//右移一位
		}
	}
	STB_1=1;

	for(i=0; i<8; i++) 				//command 4 (#1000_0100B)
	{
		STB_1=0;
		CLK=0;
		switch(f_dimming_1)  //显示亮度模式
		{
			case(0):
				if(i==3 || i==7|| i==2 || i==1|| i==0)
					DIN=1;
				else
					DIN=0;
			break;
			case(1):
				if(i==0 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(2):
				if(i==1 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(3):
				if(i==1 || i==0 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(4):
				if(i==2 ||i==3 || i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(5):
				if(i==2 || i==0 || i==3 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(6):
				if(i==2 || i==1 ||i==3 || i==7)
					DIN=1;
				else
					DIN=0;
			break;
			case(7):
				if(i==2 || i==1 || i==0 ||i==7)
					DIN=1;
				else
					DIN=0;
			break;
		}
		CLK=1;

	}
	STB_1=1;
}

结合模块进行显示

具体断码显示不再赘述,整理如下

uchar f_dimming_1 = 0;  //亮度可调  1-7级   0默认 最亮
uchar f_dimming_2 = 0;  //亮度可调  1-7级   0默认 最亮

uchar Font_Data[10]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};  //数码管
uchar Font_point[4]={0x00, 0x03, 0x01, 0x02};  //数码管 点   
uchar RGY_DIS[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};  //红1绿1黄1  红2绿2黄2 

uchar seg_data_1[14]={0};//缓存数组
uchar seg_data_2[14]={0};//缓存数组

数码管部分使用Font_Data,和Font_point,进行显示,对于杂点,则进行了重新分布设置,这样使用宏定义即可实现对其控制亮灭。

//置位  点亮
//中间杂点   
#define DIS1_SET_1    seg_data_1[10]=(seg_data_1[10]|0X01)
#define DIS1_SET_2    seg_data_1[10]=(seg_data_1[10]|0X02)
#define DIS1_SET_3    seg_data_1[7] =(seg_data_1[7] |0X04)
#define DIS1_SET_4    seg_data_1[10]=(seg_data_1[10]|0X04)
#define DIS1_SET_5    seg_data_1[10]=(seg_data_1[10]|0X08)
#define DIS1_SET_6    seg_data_1[9] =(seg_data_1[9] |0X04)
#define DIS1_SET_7    seg_data_1[0] =(seg_data_1[0] |0X80)
#define DIS1_SET_8    seg_data_1[2] =(seg_data_1[2] |0X80)
#define DIS1_SET_9    seg_data_1[4] =(seg_data_1[4] |0X80)
#define DIS1_SET_10   seg_data_1[5] =(seg_data_1[5] |0X01)
#define DIS1_SET_11   seg_data_1[11]=(seg_data_1[11]|0X04)
#define DIS1_SET_12   seg_data_1[5] =(seg_data_1[5] |0X02)
#define DIS1_SET_13   seg_data_1[10]=(seg_data_1[10]|0X10)
#define DIS1_SET_14   seg_data_1[10]=(seg_data_1[10]|0X20)
#define DIS1_SET_15   seg_data_1[10]=(seg_data_1[10]|0X40)
#define DIS1_SET_16   seg_data_1[10]=(seg_data_1[10]|0X80)
#define DIS1_SET_17   seg_data_1[11]=(seg_data_1[11]|0X01)
#define DIS1_SET_18   seg_data_1[11]=(seg_data_1[11]|0X02)


//左右点
#define DIS2_SET_1    seg_data_1[6]=(seg_data_1[6] |0X01)
#define DIS2_SET_2    seg_data_1[6]=(seg_data_1[6] |0X02)
#define DIS2_SET_3    seg_data_1[6]=(seg_data_1[6] |0X04)
#define DIS2_SET_4    seg_data_1[6]=(seg_data_1[6] |0X08)
#define DIS2_SET_5    seg_data_1[6]=(seg_data_1[6] |0X10)
#define DIS2_SET_6    seg_data_1[6]=(seg_data_1[6] |0X20)
#define DIS2_SET_7    seg_data_1[6]=(seg_data_1[6] |0X40)
#define DIS2_SET_8    seg_data_1[6]=(seg_data_1[6] |0X80)
#define DIS2_SET_9    seg_data_1[7]=(seg_data_1[7] |0X01)
#define DIS2_SET_10   seg_data_1[7]=(seg_data_1[7] |0X02) 
#define DIS2_SET_11   seg_data_1[8]=(seg_data_1[8] |0X01) 
#define DIS2_SET_12   seg_data_1[8]=(seg_data_1[8] |0X02) 
#define DIS2_SET_13   seg_data_1[8]=(seg_data_1[8] |0X04) 
#define DIS2_SET_14   seg_data_1[8]=(seg_data_1[8] |0X08) 
#define DIS2_SET_15   seg_data_1[8]=(seg_data_1[8] |0X10) 
#define DIS2_SET_16   seg_data_1[8]=(seg_data_1[8] |0X20) 
#define DIS2_SET_17   seg_data_1[8]=(seg_data_1[8] |0X40) 
#define DIS2_SET_18   seg_data_1[8]=(seg_data_1[8] |0X80) 
#define DIS2_SET_19   seg_data_1[9]=(seg_data_1[9] |0X01) 
#define DIS2_SET_20   seg_data_1[9]=(seg_data_1[9] |0X02) 
                      
//置0  熄灭           
//中间杂点             
#define DIS1_CLR_1    seg_data_1[10]=(seg_data_1[10]&(~0X01))
#define DIS1_CLR_2    seg_data_1[10]=(seg_data_1[10]&(~0X02))
#define DIS1_CLR_3    seg_data_1[7] =(seg_data_1[7] &(~0X04))
#define DIS1_CLR_4    seg_data_1[10]=(seg_data_1[10]&(~0X04))
#define DIS1_CLR_5    seg_data_1[10]=(seg_data_1[10]&(~0X08))
#define DIS1_CLR_6    seg_data_1[9] =(seg_data_1[9] &(~0X04))
#define DIS1_CLR_7    seg_data_1[0] =(seg_data_1[0] &(~0X80))
#define DIS1_CLR_8    seg_data_1[2] =(seg_data_1[2] &(~0X80))
#define DIS1_CLR_9    seg_data_1[4] =(seg_data_1[4] &(~0X80))
#define DIS1_CLR_10   seg_data_1[5] =(seg_data_1[5] &(~0X01))
#define DIS1_CLR_11   seg_data_1[11]=(seg_data_1[11]&(~0X04))
#define DIS1_CLR_12   seg_data_1[5] =(seg_data_1[5] &(~0X02))
#define DIS1_CLR_13   seg_data_1[10]=(seg_data_1[10]&(~0X10))
#define DIS1_CLR_14   seg_data_1[10]=(seg_data_1[10]&(~0X20))
#define DIS1_CLR_15   seg_data_1[10]=(seg_data_1[10]&(~0X40))
#define DIS1_CLR_16   seg_data_1[10]=(seg_data_1[10]&(~0X80))
#define DIS1_CLR_17   seg_data_1[11]=(seg_data_1[11]&(~0X01))
#define DIS1_CLR_18   seg_data_1[11]=(seg_data_1[11]&(~0X02))
                                          
                                          
//左右点                                  
#define DIS2_CLR_1    seg_data_1[6]=(seg_data_1[6] &(~0X01))
#define DIS2_CLR_2    seg_data_1[6]=(seg_data_1[6] &(~0X02))
#define DIS2_CLR_3    seg_data_1[6]=(seg_data_1[6] &(~0X04))
#define DIS2_CLR_4    seg_data_1[6]=(seg_data_1[6] &(~0X08))
#define DIS2_CLR_5    seg_data_1[6]=(seg_data_1[6] &(~0X10))
#define DIS2_CLR_6    seg_data_1[6]=(seg_data_1[6] &(~0X20))
#define DIS2_CLR_7    seg_data_1[6]=(seg_data_1[6] &(~0X40))
#define DIS2_CLR_8    seg_data_1[6]=(seg_data_1[6] &(~0X80))
#define DIS2_CLR_9    seg_data_1[7]=(seg_data_1[7] &(~0X01))
#define DIS2_CLR_10   seg_data_1[7]=(seg_data_1[7] &(~0X02))  
#define DIS2_CLR_11   seg_data_1[8]=(seg_data_1[8] &(~0X01))  
#define DIS2_CLR_12   seg_data_1[8]=(seg_data_1[8] &(~0X02))  
#define DIS2_CLR_13   seg_data_1[8]=(seg_data_1[8] &(~0X04))  
#define DIS2_CLR_14   seg_data_1[8]=(seg_data_1[8] &(~0X08))  
#define DIS2_CLR_15   seg_data_1[8]=(seg_data_1[8] &(~0X10))  
#define DIS2_CLR_16   seg_data_1[8]=(seg_data_1[8] &(~0X20))  
#define DIS2_CLR_17   seg_data_1[8]=(seg_data_1[8] &(~0X40))  
#define DIS2_CLR_18   seg_data_1[8]=(seg_data_1[8] &(~0X80))  
#define DIS2_CLR_19   seg_data_1[9]=(seg_data_1[9] &(~0X01))  
#define DIS2_CLR_20   seg_data_1[9]=(seg_data_1[9] &(~0X02)) 

如代码,除去数码管,全部点亮

具体驱动应用

到了这一步,驱动显示部分已经完了,接下来驱动显示时间即可,值得注意的是,第一个芯片使用seg_data_1[]数组的每个数据控制不同的显示,0-5为数码管使用和中间杂点7 8 9号这3个使用,具体 ,0 2 4 为3个完整数码管和杂点7 8 9号(,数码管使用7段,杂点一段,如果不使用这3个点,忽略即可),1为第一位“1”使用,3为中间“:”使用,6-11则为中间杂点和两侧使用,12,13未使用。

四周RGY彩灯使用第二个芯片,seg_data_2[]数组,

0   Red1  ,2   Green1  ,4   Yellow1  ,6   Red2  ,8   Green1  ,10   Yellow2 ,其他未使用 。

	seg_data_1[1]=Font_point[time_data.hour/10];   //时的十位
	seg_data_1[0]=Font_Data[time_data.hour%10];    //时的个位
	seg_data_1[2]=Font_Data[time_data.min/10];    //分的十位
	seg_data_1[4]=Font_Data[time_data.min%10];    //分的个位

if(time_data.AM_PM) //上午
{
DIS1_CLR_1 ; 
DIS1_CLR_2 ; 
DIS1_CLR_3 ;

DIS1_SET_4 ;
DIS1_SET_5 ;
DIS1_SET_6 ;
}
else        //下午
{
DIS1_SET_1 ; 
DIS1_SET_2 ; 
DIS1_SET_3 ;

DIS1_CLR_4 ;
DIS1_CLR_5 ;
DIS1_CLR_6 ;
}

	if(sec1 != time_data.sec) //时分之间的点,每隔一秒闪烁
	{
	sec_point = 1 - sec_point;
	seg_data_1[3]=Font_point[sec_point];
	sec1 = time_data.sec;	
	}

Make_Signal_1(); //显示数据

加上彩灯

至于控制彩色流水灯,相关代码例程很多,不再赘述,如下随便截取一点

uchar RGY_DIS[6]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00};  //红1绿1黄1  红2绿2黄2 

uchar  table0[] = {0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f}; //LED从低位往高位移
uchar  table1[] = {0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe}; //LED从高位往低位移
uchar  table2[] = {0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; //LED从1个亮到8个都点亮(从低位往高位)
uchar  table3[] = {0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00}; //LED从1个亮到8个都点亮(从高位往低位)
uchar  table4[] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; //LED从8个全亮到一个都不亮(从低位往高位)
uchar  table5[] = {0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff}; //LED从8个全亮到一个都不亮(从高位往低位)
uchar  table6[] = {0xfe, 0xfc, 0xfa, 0xf6, 0xee, 0xde, 0xbe, 0x7e}; //LED从低位往高位移(最低位始终为0)
uchar  table7[] = {0x7f, 0x3f, 0x5f, 0x6f, 0x77, 0x7b, 0x7d, 0x7e}; //LED从高位往低位移(最高位始终为0)
uchar i, j;		//定义循环变量
int tt = 70;		//定义时间指数

void delay_tim(int time)
{
Make_Signal_2();
delay_ms(time);
seg_data_2[2] = seg_data_2[0];
seg_data_2[8] = seg_data_2[6];
Make_Signal_2();
delay_ms(time);
seg_data_2[4] = seg_data_2[0];
seg_data_2[10] = seg_data_2[6];
Make_Signal_2();
delay_ms(time);
}

void disp0()			//状态0 所有LED闪烁3次
{
	for(i=0;i<3;i++)
	{
		 seg_data_2[0]=0x00; seg_data_2[6]=0x00; 
		delay_tim(300);
		 seg_data_2[0]=0xff; seg_data_2[6]=0xff;
		delay_tim(300);
	}
}

void disp1()			//状态1 LED顺时针转一圈
{
	for(i=0;i<8;i++)
	{
		seg_data_2[0]=table1[i];
		delay_tim(100);
	}
	seg_data_2[0]=0xff;
	for(i=0;i<8;i++)
	{
		seg_data_2[6]=table1[i];
		delay_tim(100);
	}
	seg_data_2[6]=0xff;

}

void disp2()			//状态2 LED逆时针转一圈
{
	for(i=0;i<8;i++)
	{
		seg_data_2[6]=table0[i];
		delay_tim(100);
	}
	seg_data_2[6]=0xff;
	for(i=0;i<8;i++)
	{
		seg_data_2[0]=table0[i];
		delay_tim(100);
	}
	seg_data_2[0]=0xff;
}

void disp3()			//状态3 4个LED同时顺时、逆时针移动1/4圈
{
	for(i=0;i<8;i++)
	{
	
		seg_data_2[0]=table1[i];
		seg_data_2[6]=table0[i];
		delay_tim(100);
	}
	for(i=0;i<8;i++)
	{
		seg_data_2[0]=table0[i];
		seg_data_2[6]=table1[i];
		delay_tim(100);
	}
	seg_data_2[6]=0xff;
}

void disp4()			//状态4  2个LED同时顺时针移动半圈
{
	for(i=0;i<8;i++)
	{
		seg_data_2[0]=table1[i];
		delay_tim(100);
	}
	seg_data_2[0]=0xff; 
	for(i=0;i<8;i++)
	{
		seg_data_2[6]=table1[i];
		delay_tim(100);
	}
	seg_data_2[6]=0xff;
}

void disp5()			//状态5  2个LED同时逆时针移动半圈
{
	for(i=0;i<8;i++)
	{
		seg_data_2[6]=table0[i];
		delay_tim(100);
	}
 seg_data_2[6]=0xff;
	for(i=0;i<8;i++)
	{
		seg_data_2[0]=table0[i];
		delay_tim(100);
	}
seg_data_2[0]=0xff;
}

void disp6()			//状态6 LED自上而下逐渐点亮(一半点亮一半不亮)
{
	for(i=0;i<8;i++)
	{
	
		seg_data_2[0]=table3[i];
		delay_tim(100);
	}
 seg_data_2[0]=0xff;
	for(i=0;i<8;i++)
	{
	
		seg_data_2[6]=table3[i];
		delay_tim(100);
	}
 seg_data_2[6]=0xff;
}

void disp7()			//状态7 LED自下而上逐渐点亮(直到全部点亮)
{
	for(i=0;i<8;i++)
	{
		
		seg_data_2[6]=table2[i];
		delay_tim(100);
	}
	for(i=0;i<8;i++)
	{
		seg_data_2[0]=table2[i];
		delay_tim(100);
	}
}

void disp8()			//状态8 间断8格的4个LED亮并逆时针旋转
{
	for(j=0;j<2;j++)
	{
		for(i=0;i<8;i++)
		{
			seg_data_2[0]=table0[i];
			seg_data_2[6]=table0[i];
			delay_tim(100);
		}
	seg_data_2[0]=0xff;  seg_data_2[6]=0xff;
		for(i=0;i<8;i++)
		{
		
			seg_data_2[0]=table0[i];
			seg_data_2[6]=table0[i];
			delay_tim(100);
		}
	 seg_data_2[0]=0xff; seg_data_2[6]=0xff;
	}
}

void disp9()			//状态9 间断8格的4个LED亮,然后逆时针逐渐点亮(直到全部点亮)
{
	for(i=0;i<8;i++)
	{
		seg_data_2[0]=table2[i];
		seg_data_2[6]=table2[i];
		delay_tim(100);
	}
	delay_tim(500);	
}

相关资料下载

MC2302D相关资料.zip_mc2302d资料-嵌入式文档类资源-CSDN下载

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值