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


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

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

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

    布线如下:

    代码如下:

    1. int latchPin = D8; //Pin connected to ST_CP(pin 12) of 74HC595 //ST
    2. int clockPin = D6; //Pin connected to SH_CP(pin 11) of 74HC595 //这个pin居然可以没有 SH
    3. int dataPin = D7; //Pin connected to DS(pin 14) of 74HC595
    4. int r = 8;
    5. unsigned char sequence[8] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000,};
    6. void setup() {
    7. Serial.begin(115200);
    8. pinMode(latchPin, OUTPUT);
    9. pinMode(clockPin, OUTPUT);
    10. pinMode(dataPin, OUTPUT);
    11. }
    12. uint8_t cur = 0;
    13. void loop() {
    14. for (int a = 0; a < 8; a++) {
    15. cur = sequence[a];
    16. digitalWrite(latchPin, LOW);
    17. for (int c = 0; c < 8; c++) {
    18. digitalWrite(clockPin, LOW);
    19. if (cur & 0x01)digitalWrite(dataPin, HIGH);
    20. else digitalWrite(dataPin, LOW);
    21. digitalWrite(clockPin, HIGH);
    22. cur >>= 1;
    23. }
    24. digitalWrite(latchPin, HIGH);
    25. delay(800);
    26. }
    27. delay(2000);
    28. }

    这样的代码就是从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函数又是完全正常的,代码如下:

    1. int latchPin = D8; //Pin connected to ST_CP(pin 12) of 74HC595 //ST
    2. int clockPin = D6; //Pin connected to SH_CP(pin 11) of 74HC595 //这个pin居然可以没有 SH
    3. int dataPin = D7; //Pin connected to DS(pin 14) of 74HC595
    4. int r = 8;
    5. unsigned char sequence[8] = {B00000001, B00000010, B00000100, B00001000, B00010000, B00100000, B01000000, B10000000,};
    6. void setup() {
    7. Serial.begin(115200);
    8. pinMode(latchPin, OUTPUT);
    9. pinMode(clockPin, OUTPUT);
    10. pinMode(dataPin, OUTPUT);
    11. }
    12. uint8_t cur = 0;
    13. void loop() {
    14. for (int a = 0; a < 8; a++) {
    15. cur = sequence[a];
    16. digitalWrite(latchPin, LOW);
    17. for (int c = 0; c < 8; c++) {
    18. digitalWrite(clockPin, LOW);
    19. if (cur & 0x01)digitalWrite(dataPin, HIGH);
    20. else digitalWrite(dataPin, LOW);
    21. digitalWrite(clockPin, HIGH);
    22. cur >>= 1;
    23. }
    24. digitalWrite(latchPin, HIGH);
    25. delay(800);
    26. }
    27. for (int m = r - 1; m >= 0; m--) {
    28. digitalWrite(latchPin, LOW);
    29. shiftOut(dataPin, clockPin, MSBFIRST, sequence[m]);
    30. digitalWrite(latchPin, HIGH); delay(800);
    31. }
    32. delay(2000);
    33. }

    视频对比如下:

    WeChat_20221108223820

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

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

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

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

    1. void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) {
    2. uint8_t i;
    3. for(i = 0; i < 8; i++) {
    4. if(bitOrder == LSBFIRST)
    5. digitalWrite(dataPin, !!(val & (1 << i)));
    6. else
    7. digitalWrite(dataPin, !!(val & (1 << (7 - i))));
    8. digitalWrite(clockPin, HIGH);
    9. digitalWrite(clockPin, LOW);
    10. }
    11. }

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

    1. digitalWrite(clockPin, HIGH);
    2. digitalWrite(clockPin, LOW);

    而我自己用的是:

    1. digitalWrite(clockPin, LOW);
    2. digitalWrite(clockPin, HIGH);

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

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

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

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

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

  • 相关阅读:
    Jupyter Notebook在指定位置打开
    SpringBoot集成rabbitMq
    [2023 java毕业设计源码]基于SpringBoot的在线交友系统包运行成功]
    失败率高达80%,数字化转型如何正确完成战略规划?
    10.5汇编语言整理
    管式水分仪和三针式土壤水分传感器的区别
    rabbitmq的高级特性
    VR社交应用Rec Room再获1.45亿美元融资,用户突破3700万
    html5期末大作业:自适应网站开发——公司网站7页 ,响应式页面
    大数据讲课笔记1.3 Linux目录操作
  • 原文地址:https://blog.csdn.net/platform/article/details/127759732