矿石收音机论坛

 找回密码
 加入会员

QQ登录

只需一步,快速开始

搜索
查看: 1738|回复: 2

请教单片机+74hc165程序的疑惑

[复制链接]
     
发表于 2021-5-10 19:01:15 | 显示全部楼层 |阅读模式
#include <reg52.H>
#include <intrins.h>

#define  NOP()   _nop_()   /* 定义空指令 */

//SPI 接口
sbit    CLK    = P3^6;           //串行时钟
sbit    IN_PL  = P1^6;    //把数据加载到锁存器中
sbit    IN_Dat = P1^7;    //数据通过P1.7脚移进单片机内处理

sbit    RELAY  = P1^4;
sbit    BEEP   = P1^5;

unsigned char bdata Key;
sbit    K0=Key^0;         //位定义
sbit    K1=Key^1;         //位定义
sbit    K2=Key^2;         //位定义
sbit    K3=Key^3;         //位定义
sbit    K4=Key^4;
sbit    K5=Key^5;
sbit    K6=Key^6;
sbit    K7=Key^7;

bit  M0 ,K0J;  //位定义
unsigned long ReHC74165(void);         //函数声名
void beep();   

/********************************************************
*        主函数                                                                                                 *
*                                                                                                                 *
********************************************************/
main()
  {         

  while(1)
  {
    unsigned long  Input=ReHC74165();//调用165驱动程序
         Key=Input&0xff;  //将数据传给位变量
         RELAY = 1;
     P2 = 0xff;          //清除

          //实现脉冲输入  大家仔细体会
    if(K0&K0J)M0=~M0;      
           K0J=~K0;  

        if(M0) {RELAY = 0; P2 = 0x7f;        }//实现脉冲输入
        if(K1) {beep();    P2 = 0xbf;   }//K1 为1时开启蜂鸣器和2个灯
        if(K2) {beep();    P2 = 0xdf;   }
    if(K3) {beep();    P2 = 0xef;   }
        if(K4) {beep();    P2 = 0xf7;   }
        if(K5) {beep();    P2 = 0xfb;   }
        if(K6) {beep();    P2 = 0xfd;   }
        if(K7) {beep();    P2 = 0xfe;   }
   }   

}

/**********************************************************
*                                                                                                                   *
*        蜂鸣器 (让蜂鸣器发出动听声音)                                                   *
************************************************************/
void beep()
{
  unsigned char i , j;
  for (i=0;i<2;i++)
   {

   for (j = 0; j<255; j++) {_nop_();}
   BEEP=!BEEP;                 //BEEP取反
   }
  BEEP=1;                      //关闭蜂鸣器
}

/*************************此部分为74HC165的驱动程序使用SPI总线连接*************************************/


/*********************************************************************************************************
** 函数名称:  74HC165
** 功能描述:
** 管脚描述:请参考相关的芯片资料(学习光盘中以配)
*********************************************************************************************************/
unsigned long ReHC74165(void)
{  
  unsigned char i;
  unsigned int indata;
               
   IN_PL=0;
   NOP();    //短暂延时 产生一定宽度的脉冲
   IN_PL=1;         //将外部信号全部读入锁存器中
   NOP();

   indata=0;   //保存数据的变量清0  
   for(i=0; i<8; i++)
    {
          indata=indata<<1;         //左移一位

           CLK=0;   //时钟置0
      NOP();
         indata|=IN_Dat;
      CLK=1;   //时钟置1         
        }

   return indata;         //将保存数据的变量取反后返回
}
其中这部分,请教大神释疑:
indata|=IN_Dat;
意思是通过或运算把数据赋值给indata,请问IN_Dat的数据是在最低位吗?
0000 0000 0000 0000|0000 0000 0000 0001 ,是这个意思吗?
IN_Dat是单一位的芯片数据输出脚,感觉和16位的数据有点不合,是不是还有不知道的规则,就是想问这一点。
也就是说:是不是遇到这样的数据输出单片机就自动把它放在最低位?



     
发表于 2021-5-10 19:31:57 | 显示全部楼层
| :按位与,其中一个是1位,那就只在最低位上“与”。没有其他规则与秘密。你可以在debug上看到运行情况,看看就知道了。
回复 支持 反对

使用道具 举报

     
发表于 2021-5-10 20:11:08 | 显示全部楼层
是不是遇到这样的数据输出单片机就自动把它放在最低位?
++++++++
串行数据有高位在前(MSB Frist)和低位在前(LSB Frist)两种排列,所以你要知道你用的器件如何排列,74165 输出数据时,从最高位 D7/Q7(MSB)开始输出,然后到 D6、D5...D0(LSB),所以数据输入单片机时,从最低位输入到 byte,然后左移一位,再输入,这样 8 个时钟脉冲后,最先输入的那一位就被移动到最高位了。

至于为何你的单片机输入一个 byte 用了一个 int 保存然后返回的函数又是 long,只能说这代码真奇葩,写的人真的是高手高手高高手。



回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 加入会员

本版积分规则

小黑屋|手机版|矿石收音机 ( 蒙ICP备05000029号-1 )

蒙公网安备 15040402000005号

GMT+8, 2025-4-28 06:07

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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