利用C51和74HC595并行输出两个字节


首先分享一个贴吧神贴(滑稽)

tieba

74HC595概述

74HC595是一个8位串入并出的移位寄存器,其在proteus中的器件图片如下:

595

其中各个端口的定义如下表:

| 引脚 | 描述 | | :----: | :----: | | SH_CP | 数据输入时钟线 | | ST_CP | 输出存储器锁存时钟线 | | /OE | 输出有效(低电平有效) | | /MR | 主复位(低电平有效) | | Q0~Q7 | 8位并行输出口 | | Q7' | 串行数据输出口 | | DS | 串行数据输入口 |
在SH_CP的上升沿,串行数据由DS输入并由Q7'输出;在ST_CP的上升沿,8位数据存入并行输出缓存器,并在当/OE为低电平时输出。 此为proteus中595的基本功能的概述。 # 将要实现的功能概述 C51单片机与两个595移存器连接,一个595的串行输出口Q7'与另一个595的串行输入口DS相连;C51的IO口发送两个字节的数据,一共有6种组合,所有组合中第一个字节都为0x01,第二个分别为0x00,0x01,0x02,0x03,0x04,0x05,然后让两个595进行接收并通过并行输出口输出这两个字节;数据组合的切换由按键进行。
| | 1 | 2 | 3 | 4 | 5 | 6 | | :---: | :-: | :-: | :-: | :-: | :-: | :-: | |第一个字节| 0x01| 0x01| 0x01| 0x01| 0x01| 0x01| |第二个字节| 0x00| 0x01| 0x02| 0x03| 0x04| 0x05|

proteus器件连接图

pro

  • /MR为主复位端口,本次不使用,全置高。
  • /OE为控制输出有效端口,将其置为低电平,即所有时候均有效。
  • 下方的595的串行输入口DS连接单片机的P1^0端口,上方的595的DS连接下方595的串行输出口Q7’。即意味着上方595最终输出的是第二个字节,下方595最终输出的是第一个字节。
  • 按钮一端连接P1\^7口,一端接地,意味着按钮按下,P1^7为低电平。
  • 两个595的输出存储器锁存时钟线ST_CP与单片机IO口P3^5相连,且/OE为始终为低,说明单片机控制着两个595的并行输出同时进行。
  • 两个595的数据输入时钟线SH_CP与单片机IO口P1^2相连,说明单片机控制着两个595的串行输入同时进行,即使此时上方的串行出入来自于下方的串行输出。

keil C51 程序代码:

头文件以及定义

#include <REG2051.H>
sbit out=P1^0;     //串行输出口
sbit rclk=P1^2;  //时钟脉冲信号-上升沿有效
sbit sclk=P3^5;  //打入信号-上升沿有效
sbit key=P1^7;     //按键
unsigned char code table[]={0,0x00,0x01,0x02,0x03,0x04,0x05};  //数组
unsigned char i,aa,bb,flag;

延时函数

void delayms(unsigned char z) //延时函数,delayms(1)延时1ms
{
    unsigned char x,y;
    for(x=z;x>0;x--);
    for(y=110;y>0;y--);
}

输出第一个字节(0x01)函数

void output_0x01()     //输出0x01
{
    aa=0x01;
    for(i=8;i>0;i--)
    {
        out=aa&0x80;     //将最低位取出
        aa<<=1;          //左移一位
        delayms(5);     //延时5ms
        rclk=0;          //clock
        rclk=1;             //rising edge effective
        rclk=0;          //重新置低
    }    
    sclk=0;  //74HC592 output relase clock
    sclk=1;  //rising edge effective      
    sclk=0;  //74HC592 output relase clock    
}

输出第二个字节(table[])函数

void output_table()     //输出数组内的值
{
    aa=table[bb];
    for(i=8;i>0;i--)  
    {
        out=aa&0x80;     //将最低位取出
        aa<<=1;          //左移一位
        delayms(5);
        rclk=0;          //clock
        rclk=1;          //rising edge effective
        rclk=0;
    }    
    sclk=0;              //74HC592 output relase clock
    sclk=1;              //rising edge effective      
    sclk=0;              //74HC592 output relase clock
}

键盘扫描函数

void keyscan()                //键盘扫描函数
{
    if(key==0)                //按键按下,P1^7口为低电平
    {
        delayms(10);            //按键消抖
        if(key==0)
        {
            while(!key);        //松手消抖
            if(bb==6) bb=1;    //四种情况(0x01,0x02,0x03,0x04)循环
            bb++;
            flag=1;             //标志位置1,作用是有按键按下才能运行两个output函数且运行一次
        }
    }
}

主函数

void main()
{
    while(1)                    //大循环
    {
        keyscan();            //键盘扫描函数
        if(flag==1)            //当标志位置1时,开始输出(有按键按下标志位才置1)
        {
            flag=0;            //作用是只输出一次
            output_0x10();    //先输出table,再输出0x01,这样0x01会在下面的595并行输出
            delayms(200);    //延时500ms(不是必须的)
            output_table(); 
        }    
    }
}

注:程序里面的延时函数都不是必须的,只是为了保证运行的稳定,去掉可能也没问题(延时是门玄学),或者也可以换上_nop_()短暂延时,此时应加上头文件:

#include<intrins.h>

文章作者: Mat Jenin
文章链接: http://matjenin.xyz
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Mat Jenin !
  目录