美文网首页Arduino我爱编程
74HC595等串口转并口芯片的Arduino实用封装

74HC595等串口转并口芯片的Arduino实用封装

作者: redexpress | 来源:发表于2018-01-14 00:02 被阅读80次

在74HC595等串口转并口芯片接线的时候,我们会遇到两个问题:


74HC595
  1. 有时候按次序接线较困难。比如上图,我的我这样接线是方便,但是一些图形显示的库就不能直接用了,因为这些库需要按固定次序连线,当然,我们可以改造数码管字库数据,但太麻烦了。

  2. 我的74HC595某引脚连接的电路坏了,或者我只想使用部分引脚。比如我焊接的8个LED有3个坏了,我想在LED顺序点亮的时候只点亮5个。或者我只想用4个LED,传数据的时候,我只传0~15即可。

我写了两个函数来解决这些问题。这两个函数均是可变长参数,感觉还比较好用。

shiftOutQPins 这个函数可以用来解决问题2。用法和shirtOut相同,后面多了几个参数,表示你要使用的针脚。数字对应使用的Q引脚号。引脚使用的次序是按MSBFIRSTLSBFIRST来的,和输入的次序无关。

如果要们要使用Q7,Q5,Q3,Q2,前几个参数和shiftOut类似,后面加上4,7,5,3,2。4表示参数的个数。

shiftOutQPinsOrder 可以用来解决问题1和2。和shiftOutQPin不同的是,是按次序使用制定的引脚的,所以少了bitOrder参数。
shiftOutQPinsOrder(dataPin, clockPin, val, 8, 7, 6, 5, 4, 3, 2, 1, 0);
等同于shiftOut(dataPin, clockPin, MSBFIRST, val);
shiftOutQPinsOrder(dataPin, clockPin, val, 8, 0, 1, 2, 3, 4, 5, 6, 7);
等同于shiftOut(dataPin, clockPin, LSBFIRST, val);
上图应该用shiftOutQPinsOrder(dataPin, clockPin, val, 8, 6, 7, 1, 2, 3, 5, 4, 0);

这两个函数本质是对shiftOut的封装,能用shiftOut的情况皆可用这两个封装。

// 只使用74HC595等芯片部分引脚输出数据
//
// 和系统shiftOut函数参数对比
//     shiftOutQPins(dataPin, clockPin, bitOrder, value, count, pins...);
//          shiftOut(dataPin, clockPin, bitOrder, val);
// dataPin, clockPin, bitOrder:用法与shiftOut函数相同
// value:使用的针脚能表示的数值,如果用到n个针脚,数值最大应为2^n-1,若超过范围,只截取后面n位的数据
// count:要使用的QPin个数
// pins:使用的QPin针脚,次序可任意
//
// 使用范例
//     DS,SH_CP分别接在Arduino 11,12引脚,使用Q6, Q4, Q2, Q1, Q0五个引脚,使 Q6 与 Q2 输出高电平:
//     shiftOutQPins(11, 12, MSBFIRST, B10100, 5, 6, 4, 2, 1, 0);
void shiftOutQPins(uint8_t dataPin, uint8_t clockPin, uint8_t order, uint8_t value, int count, ...) {
  int8_t pins[8] = { -1, -1, -1, -1, -1, -1, -1, -1};
  if (count <= 0) return;
  if (count > 8) count = 8;
  int8_t pin;
  va_list ap;
  va_start(ap, count);
  uint8_t index = 0;
  for (uint8_t i = 0; i < count; i++) {
    pin = va_arg(ap, int);
    if (pin < 0 || pin > 7) continue;
    pins[index] = pin;
    index++;
  }
  va_end(ap);

  qsort(pins, index, sizeof(int8_t), &ascending);
  if (order == LSBFIRST) {
    shiftOutQPinsOrder(dataPin, clockPin, value, 8, pins[0], pins[1], pins[2],
                       pins[3], pins[4], pins[5], pins[6], pins[7]);
  } else {
    shiftOutQPinsOrder(dataPin, clockPin, value, 8, pins[7], pins[6], pins[5],
                       pins[4], pins[3], pins[2], pins[1], pins[0]);
  }
}

// 使74HC595等芯片按指定的引脚次序输出数据,可只使用部分引脚
//
// void shiftOutQPinsOrder(uint8_t dataPin, uint8_t clockPin, uint8_t value, int count, pins...)
// dataPin, clockPin:用法与shiftOut函数相同
// value:使用的针脚能表示的数值,如果用到n个针脚,数值最大应为2^n-1,若超过范围,只截取后面n位的数据
// count:要使用的QPin个数
// pins:使用的QPin针脚,有次序
//
// shiftOutQPinsOrder(dataPin, clockPin, val, 8, 7, 6, 5, 4, 3, 2, 1, 0);
// 等同于shiftOut(dataPin, clockPin, MSBFIRST, val);
//
// shiftOutQPinsOrder(dataPin, clockPin, val, 8, 0, 1, 2, 3, 4, 5, 6, 7);
// 等同于shiftOut(dataPin, clockPin, LSBFIRST, val);
//
// 使用范例(1)
//     DS,SH_CP分别接在Arduino 11,12引脚,要按照Q7, Q6, Q2, Q1, Q0,Q3, Q5, Q4次序输出:
//     shiftOutQPinsOrder(11, 12, B11111111, 8, 7, 6, 2, 1, 0, 3, 5, 4);
// 使用范例(2)
//     DS,SH_CP分别接在Arduino 11,12引脚,使用Q6, Q4, Q2, Q1, Q0五个引脚,使 Q6 与 Q2 输出高电平:
//     shiftOutQPinsOrder(11, 12, B10100, 5, 6, 4, 2, 1, 0);
void shiftOutQPinsOrder(uint8_t dataPin, uint8_t clockPin, uint8_t value, int count, ...) {
  int8_t pins[8] = { -1, -1, -1, -1, -1, -1, -1, -1};
  if (count <= 0) return;
  if (count > 8) count = 8;
  int8_t pin;
  va_list ap;
  va_start(ap, count);
  uint8_t index = 0;
  for (uint8_t i = 0; i < count; i++) {
    pin = va_arg(ap, int);
    if (pin < 0 || pin > 7) continue;
    pins[index] = pin;
    index++;
  }
  va_end(ap);

  // 7, 4, 6, 1, 2  // 引脚数组pins(忽略未使用的引脚)
  // 1, 2, 4, 6, 7  // 排序后数组pinsOrdered
  // 4, 2, 3, 0, 1  // 7,4,6,1,2在pinsOrdered中的索引(position)
  int8_t pinsOrdered[8];
  memcpy(pinsOrdered, pins, sizeof(pins));  // 复制pins数据到pinsOrdered
  qsort(pinsOrdered, index, sizeof(int8_t), &ascending);
  uint8_t val = 0;
  for (uint8_t i = 0; i < index; i++) {
    uint8_t position = 0;
    for (; position < index; position++) {
      if (pins[i] == pinsOrdered[position]) break;
    }
    uint8_t bitValue = (!!(value & (1 << position))) << (index - 1 - i);
    val += bitValue;
  }
  shiftOut(dataPin, clockPin, 1, val);
}

// 用于qsort函数,从小到大排列
int ascending(const void * a, const void * b) {
  return *((int8_t *)a) - *((int8_t *)b);
}

相关文章

网友评论

    本文标题:74HC595等串口转并口芯片的Arduino实用封装

    本文链接:https://www.haomeiwen.com/subject/sfwhoxtx.html