51单片机8位流水灯改16位流水灯问题

heyicandoit 2017-11-30 05:56:51

这是我用proteus仿真的图。应该没有问题。
#include<reg51.h>
#include <intrins.h>
#define uchar unsigned char
sbit clr=P1^0;
void delay( )
{
uchar i,j;
for(i=0;i<255;i++)
for(j=0;j<255;j++);
}
void main( )
{
uchar i,temp;
clr=0;
_nop_( );
_nop_( );
_nop_( );
clr=1;
while(1)
{
temp=0xfe; //初值为11111110
for(i=0;i<7;i++)
{
SBUF=temp; //temp值送入SBUF
while(TI==0)
{;} //未移位输出完数据,等待
TI=0; //清TI标志
delay( ); //延时
temp=_crol_(temp,1); //temp值循环左移1位
}

}
}

这是第8个流水灯的程序,我不知道怎么通过程序的更改该为16个流水灯。
是否要使用switch-case语句呢。
求教
...全文
1652 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
tianxj001 2017-12-02
  • 打赏
  • 举报
回复
这里面根本没串口通讯什么事情啊,只是数据是串行的而已。 如果仅仅是16路流水灯,程序是这样的: while(1){ LED_CLK=0; LED_D=1; LED_CLK=1; //延时函数 LED_D=0; for(u8 i=0;i<15;i++) { LED_CLK=0; LED_CLK=1; //延时函数 } }
heyicandoit 2017-12-01
  • 打赏
  • 举报
回复
不得不说我还是没明白怎么做实现16个流水灯。您的意思是发一个16位的数?我所了解的串口通信似乎只能使用8位数。看您使用了时钟,这方面我还不是很了解,也不知道如何应用。是否在程序的时候将P3^1口定义为LED_CLK呢?您主函数下的显示函数我也不知道是什么样的。
tianxj001 2017-12-01
  • 打赏
  • 举报
回复
程序出现这样的问题,看来你对164的原理,还不是很清楚,其实说起来很简单,164会在时钟的上升沿,把数据端的点位移动一位,到Q1,同时原来Q1的电平,被移动到后面一位,以此类推。 你程序里面的流水灯用法,其实不是164典型用法,164典型用法,每个刷新周期,必须是完整的8个时钟,然后数据端以串口形式把需要显示的数据同步送出,这样,当8个刷新时钟过后,164的8个驱动口,就寄存并输出了刚才串行数据。这样我们需要这次刷新某几段点亮,串行数据的对应几位就为0其余为1,。 通常是用一个显示函数,连续8个移位+时钟,驱动输出。函数传递要显示的数据。扩展到多个8位的,函数一般会采用显示缓存数组,刷新后缓存后,一次性刷新需要的时钟数量和数据就可以了。 而流水灯数据其实是类似这样一串{}0XFE,0XFD,0XFB,-----0XBF,0X7F},当我们把这一串数据修改成0xFE,0xFC,0XF8,0xF0.....0xC0,0X80,0X00.这样就变成了8段光柱高度显示器了,当然解码还可以变成7段LED数码显示的ABCDEFG字段解码数据,就可以实现LED数字显示。这样做,我们只需要修改解码表,而不需要修改显示函数本身,通用性高的多。解码表,通常我们用数据表的形式,保存在程序里面,通过静态数组引用,直接获得需要的输出数据。 这才是164驱动8段LED的典型用法。
__root const u8 LED_TAB_8[]={0,0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF}; 	//8段光柱数码管0-8的编码
void LED_disp_8(u8 LED_CON)
    {
        u8 tmp=LED_TAB_8[LED_CON];
		for (u8 i=0 ;i<=7;i++)
			{
				LED_CLK=0;
				LED_DATA=tmp;
				LED_CLK=1;
				tmp>>=1;
			}
	}

void main(void) 
  {
    u8 temp=0;
    for(u8 i=0;i<9;i++)
        {
            LED_disp_8(i);
            //插入延时函数
        }
   }
tianxj001 2017-12-01
  • 打赏
  • 举报
回复
你这个循环不对了,初值为11111110 发16个时钟,必然是每8个灯里面有一个会亮 当循环改为16计数时,你的初值必须是int 的16位,1111111111111110,然后进行16位移位,并通过时钟驱动出去,这样才对。
heyicandoit 2017-12-01
  • 打赏
  • 举报
回复
#include<reg51.h>
#include <intrins.h>
#define uchar unsigned char
sbit clr=P1^0;
sbit clr1=P1^1;
void delay( )
{
uchar i,j;
for(i=0;i<255;i++)
for(j=0;j<255;j++);
}
void main( )
{
uchar i,temp;
clr=0;
_nop_( );
_nop_( );
_nop_( );
clr=1;
while(1)
{
temp=0xfe; //初值为11111110
for(i=0;i<15;i++)
{
SBUF=temp; //temp值送入SBUF
while(TI==0)
{;} //未移位输出完数据,等待
TI=0; //清TI标志
delay( ); //延时
temp=_crol_(temp,1); //temp值循环左移1位
}

}
}

程序是这样改吗?

图我改成了这样,但实现的结果并不如意,是同时闪烁的。
tianxj001 2017-11-30
  • 打赏
  • 举报
回复
164只能控制8路,16路需要2路串联,你线路图有误,后一个164 输入,必须是前一个的最高位,时钟是并联的没错。 至于程序,原来8节拍为一个周期的改为16节拍就可以了。其他的没有变化。 典型的164驱动8段LED数码管,就是这样节连,要点几个数码管,串联几个164。由于164可以用非常高的时钟20MHz以上,因此接联数量几十个是看不见闪烁的。

27,373

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧