0%

[ESP32]74HC165的使用

简介

看到原理图上有关于这款逻辑芯片相关,因为要按着这个来编程序,所以需要对这个芯片有深入的理解,才能保证编程不会错误。理解有一点错误,可能会对编程造成一定的影响的。

原理图

25210cd61c49221b5e196fda450cdb51.png
上图:使用两个逻辑芯片串联,实现把并行的光口的信号转为串行的SGPIO的信号,进而将串行的信号输入到主芯片中。

该芯片的功能描述

芯片手册上有非常详细的描述,简而言之就是将并行的信号转为串行信号。
36286f4bd19891f3304eb64412b0a644.png

真值表

afd58eb8dbc30ed861970e2f26dfc69e.png
对真值表的解读:

  • 前两行,当PL为低电平时(L),D0-D7 输入的并行信号,会同时也输入到Q0-Q1中,表示D0是L Q0也是L, D0是H Q0也是H,依次类推,D1-D7 也同样 拷贝到 Q1到Q7中。
  • 第3行第4行PL为高电平,CE为低电平,CP来一个上升沿的时候,DS(串行输入的引脚)DS里的值移位到Q0中,而Q0里原来的值移位到Q1中,Q1里原来的值移位到Q2中,。。。依次类推,Q6的值移位到Q7中。Q7原来的值以串行的方式发送出去。

16ed3027ed24dbad346f45fd34b11651.png
按单个芯片来说,每来一个时钟,值会以串行的方式被移出一位,移出的位形成串行的信号。

两个芯片串在一起

把16个并行信号,转为16个串行信号。
25210cd61c49221b5e196fda450cdb51.png
U32的D7第一个被移出到SGPIO_DI(同时也会移入到U28的D0中), D6的值会移入到D7,D5会移入到D6,。。 D0移入到D1。 U28的D7会移入到U32的D0中,每来一个时钟就会向下移动一次,16个时钟之后DI引脚就得到了16个bit的串行信号。

示例程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <ShiftIn.h>

// Init ShiftIn instance with a two chips
ShiftIn<2> shift;

void setup() {
Serial.begin(9600);
// declare pins: pLoadPin, clockEnablePin, dataPin, clockPin
shift.begin(8, 9, 11, 12);
}

void displayValues() {
// print out all 16 buttons
for(int i = 0; i < shift.getDataWidth(); i++)
Serial.print( shift.state(i) ); // get state of button i
Serial.println();
}

void loop() {
if(shift.update()) // read in all values. returns true if any button has changed
displayValues();
delay(1);
}

ShiftIn.h文件内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/* ShiftIn.h - Arduino library that reads in values from an 8 bit shift register (74HC165).
* You can daisy-chain several shift register in order to read in up to 64 buttons by only using 4 Arduino pins.
*
* Created by Henrik Heine, July 24, 2016
*
LICENSE
The MIT License (MIT)

Copyright (c) 2016 Henrik

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
#ifndef ShiftIn_h
#define ShiftIn_h

#include "Arduino.h"

template<byte chipCount, typename ShiftType>
class _ShiftIn {
private:
byte ploadPin;
byte clockEnablePin;
byte dataPin;
byte clockPin;

const uint16_t dataWidth;
uint8_t pulseWidth;

ShiftType lastState;
ShiftType currentState;
public:
_ShiftIn() : dataWidth(chipCount * 8), pulseWidth(5), lastState(0), currentState(0) {}

// setup all pins
void begin(int pload, int clockEN, int data, int clock) {
pinMode(ploadPin = pload, OUTPUT);
pinMode(clockEnablePin = clockEN, OUTPUT);
pinMode(dataPin = data, INPUT);
pinMode(clockPin = clock, OUTPUT);
}

inline uint8_t getPulseWidth() { return pulseWidth; }
inline void setPulseWidth(uint8_t value) { pulseWidth = value; }
inline uint16_t getDataWidth() { return dataWidth; }
// whether some value has changed
inline boolean hasChanged() { return lastState != currentState; }
// whether the value with index 'id' has changed
inline boolean hasChanged(int id) { return state(id) != last(id); }
// returns the state from the last frame
inline ShiftType getLast() { return lastState; }
// returns the current state
inline ShiftType getCurrent() { return currentState; }
// whether button 'id' is pressed or not
inline boolean state(int id) { return bitRead(currentState, id); }
// whether button 'id' was pressed in the last frame
inline boolean last(int id) { return bitRead(lastState, id); }
// whether button 'id' is now pressed, but wasn't pressed in the last frame
inline boolean pressed(int id) { return !last(id) && state(id); }
// whether button 'id' is now released, but was pressed in the last frame
inline boolean released(int id) { return last(id) && !state(id); }

// read in data from shift register and return the new value
ShiftType read() {
lastState = currentState;
ShiftType result = 0;

digitalWrite(clockEnablePin, HIGH);
digitalWrite(ploadPin, LOW);
delayMicroseconds(pulseWidth);
digitalWrite(ploadPin, HIGH);
digitalWrite(clockEnablePin, LOW);

for(uint16_t i = 0; i < dataWidth; i++) {
ShiftType value = digitalRead(dataPin);
result |= (value << ((dataWidth-1) - i));
digitalWrite(clockPin, HIGH);
delayMicroseconds(pulseWidth);
digitalWrite(clockPin, LOW);
}
currentState = result;
return result;
}

// same as read, but it returns whether something has changed or not
boolean update() {
return read() != lastState;
}
};

// fallback with 64 bit state (up to 8 shift registers)
template<byte chipCount>
class ShiftIn : public _ShiftIn<chipCount, uint64_t> {};
// single shift register (8 bit state)
template<>
class ShiftIn<1> : public _ShiftIn<1, uint8_t> {};
// two shift registers (16 bit state)
template<>
class ShiftIn<2> : public _ShiftIn<2, uint16_t> {};
// three shift registers (32 bit state)
template<>
class ShiftIn<3> : public _ShiftIn<3, uint32_t> {};
// four shift registers (32 bit state)
template<>
class ShiftIn<4> : public _ShiftIn<4, uint32_t> {};

#endif

ArduinoShiftIn-master.zip