项目场景:
通过多个HEF4021BT移位寄存器级联来节省主控io口。
问题描述
HEF4021BT移位寄存器网上能找到的datasheet基本都是古早版本,九几年的,相关时序描述也很粗略。单靠它的datasheet资料,挺难开发的。
解决方案:
参考网上常见的74hc165移位寄存器的操作逻辑来操作HEF4021BT
哔哩哔哩上面一个视频讲得很好:5分钟了解74HC165并行输入串行输出移位寄存器原理及在Arduino上的使用(PISO)_哔哩哔哩_bilibili
硬件原理图
原理图上看,默认的开关都是上拉vcc,也就是默认都是高电平。默认上电后PL低电平的话,那对应的第一次读数据会是U3:1111 1111 ; U2:1000 1011 ; U1: 1111 1111。从低到高位排序。
datasheet看出,PL为高,并行输入有效,串行无效,跟时钟状态无关。PL为低,串行输入有效,时钟上升沿一位一位输出。(这里吐槽,真的这个datasheet做得不是很好。很臭。对新手特别不友好。)
象征性看下datasheet而已。实际操作里面描述的内容还是有差别。直接看代码逻辑,简陋的验证而已,可以优化,里面还有些调试用的逻辑代码,直接就注释。arduino上的代码
String indate="";
String val=""; //变量定义 indate是用来接收pc传来的数据、val暂存indate数据。
delay(50);
// while(Serial.available()>0){
// indate+=char(Serial.read());
// delay(2);
// if(Serial.available()<=0){
// //Serial.println(indate);
// }
// } //读取电脑传来的数据
//if(indate.length()>0){
if(1){
//val=indate; //将indate暂存到val中
//if(val.indexOf("777")!= -1){ //判断val数据并进行下一步操作
if(1){
digitalWrite(PLPin, HIGH);
digitalWrite(CPPin, HIGH);//important
delay(5);
digitalWrite(PLPin, LOW);
byte buttonState = shiftIn(buttonPin,CPPin,LSBFIRST);
byte buttonState1 = shiftIn(buttonPin,CPPin,LSBFIRST);
for (byte i = 0; i < 8; i++) {
Joystick.setButton(i+2, abs(!!(buttonState1 & (1 << (7 - i)))-1));
}
byte buttonState2 = shiftIn(buttonPin,CPPin,LSBFIRST);
for (byte i = 0; i < 8; i++) {
Joystick.setButton(i+10, abs(!!(buttonState2 & (1 << (7 - i)))-1));
}
}
}
首先是PL high,使并行输入有效,然后这个CP一定一定要拉高,不然读数据会出问题。这个datasheet并没有体现,是参考74那款移位寄存器来的。接着PL low,进入串行输入有效,并且在U2的Q7中输出。
因为是三个移位寄存器级联,所以每次读取数据要读三个字节。也就是代码里面的buttonstate、buttonstate1、buttonstate2。
joystick是arduino作为游戏外设上报button用的,不用看。
代码很简单,主要是对移位寄存器的操作逻辑理解。级联后的移位寄存器,怎么读写切换。当然,上手摸一摸很快就懂的。