原理图
代码看不懂的留言。该库函数需要一点点c语言基础。
首先定义74hc165.h头文件
#ifndef __74HC165D_H_
#define __74HC165D_H_
#ifndef uchar
#define uchar unsigned char
#define uint unsigned int
#endif
//STC系列,STC8H头文件可以使用大部分单片机,硬件PWM除外,STC8A的pwm和STC8H不一样
#include "STC8H.h"
#include "intrins.h"
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
#define HC165_NUM (3) //74hc165芯片数量
#define HC165_bit_NUM (HC165_NUM*8) //74hc165芯片读的位数
#define HC165_IN_EXIST (0) //0表示有输入
#define HC165_IN_VANISH (1) //1表示无输入
//定义74HC165控制管脚
/*硬件将引脚15CE(对应CLK INH)连接到低电平,则自动使能时钟输入
引脚10DS(对应SER),连接到上一级的Q7,即可实现级联
*/
//并行口的H 就相当于最高位,A 为最低位,原理图中D0_1 - D7_1对应A-H
sbit HC165_QH =P3^3; //串行数据输出 9脚 对应Q7
sbit HC165_CLK =P3^4;//时钟输入 2脚 对应CP
sbit HC165_SHLD=P3^5;//寄存器存储控制 1脚 对应PL
//sbit HC165_CE = P2^6;//CE 时钟使能,低电平有效
void _74hc165_init(void);
void hc165_read_data(unsigned char* Data,unsigned char num);
void HC165_IN_UPdata(void);
typedef struct {
unsigned char Status[HC165_NUM]; //记录芯片整体输入状态
unsigned char Bit_Status[HC165_bit_NUM]; //记录每个位的输入状态
} HC165_IN_CTRL_OBJ;
extern HC165_IN_CTRL_OBJ HC165_IN_Ctrl;
#endif
然后编写C文件
#include "74HC165/74HC165d.h"
#include "Uart/uart.h"
HC165_IN_CTRL_OBJ HC165_IN_Ctrl = {0};
void _74hc165_init(void)
{
HC165_SHLD = 1; //禁止并行置数功能
HC165_CLK = 1; //时钟输入端,上升沿有效
}
/*******************************************************************************
* 函 数 名 : hc165_read_data()
* 函数功能 : 从74HC165中读取任意字节数据
* 输 入 : unsigned char* Data,保存数据的指针,num为74HC165级联的数量
* 输 出 :
*******************************************************************************/
void hc165_read_data(unsigned char* Data,unsigned char num)
{
uchar i=8;
uchar j=0;
HC165_SHLD=0;//SHLD拉低,165并口数据传入到移位寄存器中
//Delay1us(5);//等待A-H的数据被置入寄存器,预防很多个级联,两三个的话是不需要延时的
HC165_SHLD=1;//SHLD拉高,禁止165并口数据传入到移位寄存器中
for(j=0;j<num;j++){
while(i--){
*(Data+j) |= (unsigned char)HC165_QH << i;//左移1位,先读取的数据是高位,经过8次循环则将第一次读取的位放到字节高位
HC165_CLK=0; HC165_CLK=1;//上升沿读取数据
}
i=8;
}
}
void HC165_IN_UPdata(void){
unsigned char i = 0;
unsigned char k = 0;
unsigned char j = 0;
memset(&HC165_IN_Ctrl,0,sizeof(&HC165_IN_Ctrl));
hc165_read_data(HC165_IN_Ctrl.Status,3);
for(i=0;i<HC165_bit_NUM;i++){
if(i%8==0){
j=0;
k++;
}
HC165_IN_Ctrl.Bit_Status[i] = (((HC165_IN_Ctrl.Status[k-1]& (0x01)<<j) == (unsigned char)(HC165_IN_VANISH)<<j)? 0x01 : 0x00 );
j++;
}
// SendData4(HC165_IN_Ctrl.Bit_Status,HC165_bit_NUM,2);
}
/*使用例子
// uchar d[3]={0};
// hc165_read_data(d,3);
// UartSend(*(d));
// UartSend(*(1+d));
// UartSend(*(2+d));
*/
以读3个74HC165级联为例
void Test_Osu(void){
uchar d[3]={0};
hc165_read_data(d,3);
UartSend(*(d));
UartSend(*(1+d));
UartSend(*(2+d));
}
移植到STM32时可以使用位带操作定义管脚,这样就不需要大改了。