单片机论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 145|回复: 9
收起左侧

51单片机控制74LS164芯片输出64位的数组

[复制链接]
izhonguo 发表于 2019-2-12 02:37 | 显示全部楼层 |阅读模式
各位大神新年好,想请教一个简单的程序如何写。想利用51单片机的P00和P01两个串口输出一个16位的数组【0 0 0 1 1 1 0 0 ****】等数据,然后利用LS164这个芯片实现并口输出,写的程序如下,请各位大佬看一下是哪里有问题,为何不能按照想要的结果输出?

#include <reg52.h>
sbit LS164_DATA = P0^0;  //74LS164数据线
sbit LS164_CLK = P0^1;  //74LS164时钟线

void LS164_Write(unsigned long state)  //74LS164写16位扩展引脚函数
{
        unsigned char i;
        for(i=0;i<16;i++)  //循环写16位扩展引脚状态
        {
                LS164_CLK = 0;
                if(state & 0x8000)
                {
                        LS164_DATA = 1;
                }
                else
                {
                        LS164_DATA = 0;
                }
                LS164_CLK = 1;
                state = state<<1;
        }
}

void delayms(unsigned char ms)
{
        unsigned char i;
        while(ms--)
        {
        for(i = 0; i < 120; i++);
        }
}
/********************************************************************
* 名称 : Main()
* 功能 : 主函数
* 输入 : 无
* 输出 : 无
***********************************************************************/
void main(void)
{
        unsigned char state_input[] = {0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0};  //16进制0x0101, 把这组数据逐一写出到LS164芯片的16个输出上QA~QH
        unsigned char j;
        unsigned long state=0x0;
        LS164_Write(0x0);  
        for(j=0;j<16;j++)  
        {
                if(state_input[j]==1)
                {
                        state = state^(0x8000>>j); //异或运算,把输入的16位0或1状态逐个写入到state中
                }
        }
        LS164_Write(state);
        while(1)
        {
                   LS164_Write(state);
                delayms(100);
        }
}



异或运算

异或运算
回复

使用道具 举报

wulin 发表于 2019-2-12 16:54 | 显示全部楼层
标题与内容描述不符,内容描述与程序不符,程序中数据类型定义与实际需要不符,看不明白楼主最终目的是什么。
回复

使用道具 举报

 楼主| izhonguo 发表于 2019-2-12 18:08 | 显示全部楼层
用仿真跑的输入结果显示是正确的,但是把相同的hex文件烧入单片机去控制真实的LS164却出现不一样的结果,这个是为什么呢?
TIM截图20190212180715.png
回复

使用道具 举报

yaoji123 发表于 2019-2-13 07:39 | 显示全部楼层
AT89C52的P0口在用时要加上拉电阻,否则电平不对
回复

使用道具 举报

 楼主| izhonguo 发表于 2019-2-13 15:36 | 显示全部楼层
wulin 发表于 2019-2-12 16:54
标题与内容描述不符,内容描述与程序不符,程序中数据类型定义与实际需要不符,看不明白楼主最终目的是什么 ...

总工程师您好,因为自己一直再改代码,所以最终放上去的一个和题目描述的不对,就是我现在需要处理一个64位的数组,这里面随机的分布着0或者1, 然后我需要8个LS164的位移芯片共计64个输出端口上输出这个数组里的高电平和低电平。仿真结果我看是正确的,但是打上实物,用万用表量LS164的输出端口电压不能和仿真上的结果一样。
64位数组.png
回复

使用道具 举报

 楼主| izhonguo 发表于 2019-2-13 15:40 | 显示全部楼层
yaoji123 发表于 2019-2-13 07:39
AT89C52的P0口在用时要加上拉电阻,否则电平不对

您好,请问P0的上拉电阻如何接线?是和51单片机的最小系统里的上拉电阻一样接法就可以吗?直接插一个10KΩ的电阻接地就可以吗?谢谢!
回复

使用道具 举报

 楼主| izhonguo 发表于 2019-2-13 17:29 | 显示全部楼层
这两天又改了一下代码,现在可以正确按照顺序输出我自己定义的64bit的数组里面的0或者1,但是我有个疑问想向论坛的大牛确认一下,这样子用位移寄存器的64个输出端一个一个推出我64bit数组里的高电平和低电平取控制比如说5V的继电器的闭合状态的话,会不会导致位移高电平过程中,意外导致其他继电器不断被打开。比如说不幸情况下64bit的数组最右的是个1,然后我需要推64步才能把这个1推到我第8块的74LS164芯片的第八位输出上,但是推这个1到指定位置的时候不是要经过前面63个位置吗?这样这63个位置的继电器不是都要被触发一遍吗?还望各位大佬耐心指点。多谢!
还有一个问题,我用这个生成的HEX文件烧入单片机然后在面包板上测量LS164输出的电压,发现和仿真结果完全不同,是乱七八槽的。是仿真有问题还是实物接线有其他特别需要注意的地方(74LS164在面包板上的接线检查了很多遍,应该不会有问题)。再次感谢大家的时间。



64位数组.png
回复

使用道具 举报

wulin 发表于 2019-2-13 20:39 | 显示全部楼层
izhonguo 发表于 2019-2-13 15:36
总工程师您好,因为自己一直再改代码,所以最终放上去的一个和题目描述的不对,就是我现在需要处理一个64 ...

建议改用74HC595连级输出。ST_CP(12脚):上升沿时移位寄存器的数据进入数据存储寄存器,下降沿时存储寄存器数据不变。通常将ST_CP置为低电平,这样在移位过程中各输出端状态保持不变,当移位结束后,在ST_CP端产生一个正脉冲(5V时,大于几十纳秒就行了。通常都选微秒级),更新输出数据。
回复

使用道具 举报

wulin 发表于 2019-2-14 08:48 | 显示全部楼层
izhonguo 发表于 2019-2-13 17:29
这两天又改了一下代码,现在可以正确按照顺序输出我自己定义的64bit的数组里面的0或者1,但是我有个疑问想 ...

你的上述疑问是真实存在的,如果改用74HC595连级输出可以解决你的上述疑问。给你一个示例程序和仿真。

无标题.jpg


#include <reg51.H>
#define uint unsigned int
#define uchar unsigned char
sbit        P_HC595_SER   = P0^0;
sbit        P_HC595_SRCLK = P0^1;
sbit        P_HC595_RCLK  = P0^2;

/*******************定义8个字节64 bit缓存数组*************************/
uchar data dis_buf[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};//

/**************** 向HC595发送一个字节函数 ******************/
void Send_595(uchar dat)
{               
        uchar i;
        for(i=0;i<8;i++)
        {
                dat <<= 1;
                P_HC595_SER  = CY; //溢出位赋值数据输出端
                P_HC595_SRCLK = 1; //移位时钟
                P_HC595_SRCLK = 0;
        }
}
/**************** 向HC595发送八个字节函数 ******************/
void DisplayScan()
{       
        uchar j;
        for(j=0;j<8;j++)
        {
                Send_595(dis_buf[j]);//向HC595发送一个字节
        }
        P_HC595_RCLK = 1;//锁存输出数据
        P_HC595_RCLK = 0;
}

void main()
{
        P_HC595_SRCLK = 0;//初始化移位时钟端
        P_HC595_RCLK  = 0;//初始化锁存输出端
        DisplayScan();                //发送八个字节
        while(1);
}

回复

使用道具 举报

 楼主| izhonguo 发表于 2019-2-19 20:47 来自手机 | 显示全部楼层
wulin 发表于 2019-2-14 08:48
你的上述疑问是真实存在的,如果改用74HC595连级输出可以解决你的上述疑问。给你一个示例程序和仿真。

...

太感谢大神了!看的小弟我热泪盈眶
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|小黑屋|单片机论坛 |51黑电子论坛单片机.

Powered by 单片机教程网

快速回复 返回顶部 返回列表