arduino(esp8266)驱动74hc595进行流水灯异常一例

32 篇文章 2 订阅
25 篇文章 0 订阅

这两天重新来玩74HC595,因为前一段时间为了点亮led 像素屏用了查理复用,但是查理复用的GPIO占用实在太高,而且接线其实也非常不方便;因此打算重新用74HC595来点灯,毕竟595的价格喜人啊。

之前一直不愿意用595的原因是它的文档实在看起来头疼的很,什么sclk,rclk,sclr,stcp ,shcp,ds,si 等等,同样是595 芯片,不同文档介绍的时候,pin的名称是两套,不论是那一套都让人容易晕头转向。

同时为了更深入理解595的运行机制,加上前端时间用了tm1637,学习了异或和对应的二进制转换,所以打算手工来驱动595 ,不使用shiftout函数。

布线如下:

代码如下:


int latchPin = D8;  //Pin connected to ST_CP(pin 12) of 74HC595 //ST
int clockPin = D6; //Pin connected to SH_CP(pin 11) of 74HC595  //这个pin居然可以没有 SH
int dataPin = D7;  //Pin connected to DS(pin 14) of 74HC595
int r = 8;
unsigned char sequence[8] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000,};

void setup() {
  Serial.begin(115200);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}
uint8_t cur = 0;
void loop() {
  for (int a = 0; a < 8; a++) {
    cur = sequence[a];
    digitalWrite(latchPin, LOW);
    for (int c = 0; c < 8; c++) {
      digitalWrite(clockPin, LOW);
      if (cur & 0x01)digitalWrite(dataPin, HIGH);
      else digitalWrite(dataPin, LOW);
      digitalWrite(clockPin, HIGH);
      cur >>= 1;
    }
    digitalWrite(latchPin, HIGH);
    delay(800);
  }
  delay(2000);
}

这样的代码就是从8->1输出流水灯,结果8->2都运行起来正常,但是2->1的时候出了问题,本来应该是2灭1亮,结果2和1 一期亮了,如下图:

 代码问题找了无数遍找不出原因,各种测试和尝试,找不出原因。

按照595的手册:

1、SI(DS)输入数据;

2、CLK(SHCP)上升沿,输入数据到移位寄存器;

3、重复上面过程到数据输入结v束;

4、RCLK(STCP) 上升沿,移入数据到锁存器并行输出Q0-Q8并行输出;

所以上面的代码是没有错的,网上搜到过由于电压不对,导致输出不对的情况,595 的电压是5V,SI(DS)的电压是3.3V这种情况导致输出不对,于是就试了一下,结果在3.3V 的情况下,8->1确实输出正常。

由于3.3V 下,LED不够亮,重新回到了5V折腾,于是开始怀疑是不是各种接线不对,于是把MR接到了GND,之前没有接,如下图

这次调整后,MR接了GND, 5.5V下8-1输出正常,这其实已经是最标准的做法,因为之前没有接MR.

然而这件事并没有完,后来在MR没有接入GND的情况下,为了对比一下效果,使用了shiftout函数,发觉MR没有接入GND,同样意图8->1输出,我自己的代码2->1 同时亮,而shiftout函数又是完全正常的,代码如下:


int latchPin = D8;  //Pin connected to ST_CP(pin 12) of 74HC595 //ST
int clockPin = D6; //Pin connected to SH_CP(pin 11) of 74HC595  //这个pin居然可以没有 SH
int dataPin = D7;  //Pin connected to DS(pin 14) of 74HC595
int r = 8;
unsigned char sequence[8] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000,};

void setup() {
  Serial.begin(115200);
  pinMode(latchPin, OUTPUT);
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
}
uint8_t cur = 0;
void loop() {
  for (int a = 0; a < 8; a++) {
    cur = sequence[a];
    digitalWrite(latchPin, LOW);
    for (int c = 0; c < 8; c++) {
      digitalWrite(clockPin, LOW);
      if (cur & 0x01)digitalWrite(dataPin, HIGH);
      else digitalWrite(dataPin, LOW);
      digitalWrite(clockPin, HIGH);
      cur >>= 1;
    }
    digitalWrite(latchPin, HIGH);
    delay(800);
  }
  for (int m = r - 1; m >= 0; m--) {
    digitalWrite(latchPin, LOW);
    shiftOut(dataPin, clockPin, MSBFIRST, sequence[m]);
    digitalWrite(latchPin, HIGH); delay(800);
  }
  delay(2000);
}

视频对比如下:

WeChat_20221108223820

于是又各种找原因,怀疑是不是各种上升沿出了问题,各种怀疑,各种调试,反正就是觉得奇怪:

1、在MR接入GND的情况下,都正常;

2、在MR没有GND的情况下,3.3V电压 一切正常;5V电压,为啥shiftout函数亮灯正常,而我自己的函数亮灯前面正常,最后两位出了问题,如果说我的代码有问题,那么为啥有的情况下工作正常,有的不正常?

一直到最后实在不行,祭出了终极大法,查看shiftout的源代码:

void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) {
    uint8_t i;

    for(i = 0; i < 8; i++) {
        if(bitOrder == LSBFIRST)
            digitalWrite(dataPin, !!(val & (1 << i)));
        else
            digitalWrite(dataPin, !!(val & (1 << (7 - i))));

        digitalWrite(clockPin, HIGH);
        digitalWrite(clockPin, LOW);
    }
}

这一下就对比出来了,shiftout对于时钟线的上升沿用的是:

digitalWrite(clockPin, HIGH);
digitalWrite(clockPin, LOW);

而我自己用的是:

      digitalWrite(clockPin, LOW);

      digitalWrite(clockPin, HIGH);

当把代码重新修改后,在MR不接GND的情况下,5V电压,从8->1 shiftout和我自己的代码都工作正常。

在网上其他人的代码也是同我最初的情况一样:

 应该说很多人都是这么写的,先low后high.

一般情况下,MR接入GND,这段代码都会工作正常,但是我上面的经历说明了某些情况下如果不按照shiftout所示的先high后low,会存在难以找到原因的异常,包括网上流传的5V电压74HC595不稳定要用到3.3V电压的谣传大概也是因为这个原因。

不过最后还是没有搞明白为啥是先high后low,而不是先low和high呢?

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值