51单片机-RGB灯带

这个实验是灯带上有30颗RGB灯,每颗芯片控制3颗RGB灯,要使这30颗灯全亮蓝色。

这个DIN就是输入口,它输出高电平或者低电平,然后将高低电平分配给OUTR(红),OUTG(绿),OUTB(蓝),硬件上用P0_6作为 输入口,配置的时候根据手册配置为输入。

 

 发数据的时候首先高位先发,上面那个输出码型,就是输出高电平和低电平的占空比,

0码就是输出0,前提是输出0的时候要高电平要延时0.3us  ,低电平要延时0.9us  

1码就是输出1,前提是输出1的时候要高电平延时0.9us  , 低电平要延时0.3us

下面那个Reset码也是比较重要的,当我们将24bit数据发送出去后,此时灯是不会亮的,它需要有一个大于80us的低电平过来,然后才会将刚刚发送过来的24bit数据应用到灯上。

发数据的时候如果R7~R0全为0,G7~G0全为0,B7~B0全位1,则亮蓝色,也可以显示其他的颜色,具体可以去找对应的RGB值。

上图是一个级联电路,也就是说当我传输3组数据给第一个芯片后,分配给第一个芯片的三颗灯,DOUT检测到后面还有数据,它就会把数据传输给DIN。

解题思路:定时器每0.3us进入中断,用一个标志位检测数据是否准备好,准备好了就等下一次中断进入发送数据,但是发送因为有占空比,也就是上面说的0码和1码,所以当定时器计时到了进入中断要发送数据,就给一个变量加1,加一次就是0.3us,加两次就是0.6us,加3次就是0.9us,0码就是输出0,前提是输出0的时候要高电平要延时0.3us  ,低电平要延时0.9us  ,下面有个判断time_cnt < 2就是为1次,也就是0.3us,而ime_cnt < 5,就是0.9us,按照这个逻辑进行发送。

u32 time_cnt;
u16 i=0,j=0,send_over_flag=1,temp;
uint8_t z;

uint8_t rgb_data[3] = {0X00,0X00,0XFF};

//0.31us
void inital_Timer3()
{
	TH3 = (65536-5) >> 8;  //存储高八位
	TL3 = (65536-5);       //存储低八位
	T3CON = 0x04;          //打开定时器3
	IE1 |=  0x04;          //打开中断
}

void IRQ_TIME3(void) interrupt T3_VECTOR
{	
	if(send_over_flag == 0) //发送未完成标志位
	{
		if(z == 0)//要发送逻辑0
		{
			time_cnt++;  //定时器进来一次就加1,表示进来一次就是0.3us,
			if(time_cnt < 2)
			{
					P0_6 = 1;
			}
			else if(time_cnt < 5)
			{
					P0_6 = 0;
					if(time_cnt == 4)
					{
						time_cnt = 0;
						send_over_flag = 1;
					}
			}
		}
		else if(z == 1)     //要发送逻辑1
		{
				time_cnt++;
				if(time_cnt < 4)
				{
						P0_6 = 1;
				}
				else if(time_cnt < 5)
				{
						P0_6 = 0;
						if(time_cnt == 4)
						{
							time_cnt = 0;
							send_over_flag = 1;
						}
				}
		}
	}
	else         //if(send_over_flag == 1) 1发送1bit完成,可以准备下一个bit
	{
		if(j > 8)   
		{
			j = 0;
			i++;
			if(i > 3)
			{
				i = 0;
			}
		}
		else if(j >= 0&&j <= 7)    //j是位数,一个灯有24bit,数组定义了3个十六进制,一个十六进制就是8bit
		{
			temp = rgb_data[i];    //把8位赋值给临时变量
			z=((temp<<j)&0x80);    //先移位,再取出高位,例如1000 0000 第一次,i=0,左移没变化,还是取出1     
            if(z)                  //取出如果z为真,给1
            {
               z=1;     
            }                      //取出为假,给0
            else
            {
               z=0;
            }
			j++;
			send_over_flag = 0;    //发送标志位表示数据准备好了,可以发送了
		}
	}
}

微信技术交流