74HC595等串列埠轉並口晶片的Arduino實用封裝
在74HC595等串列埠轉並口晶片接線的時候,我們會遇到兩個問題:
有時候按次序接線較困難。比如上圖,我的我這樣接線是方便,但是一些圖形顯示的庫就不能直接用了,因為這些庫需要按固定次序連線,當然,我們可以改造數碼管字型檔資料,但太麻煩了。
我的74HC595某引腳連線的電路壞了,或者我只想使用部分引腳。比如我焊接的8個LED有3個壞了,我想在LED順序點亮的時候只點亮5個。或者我只想用4個LED,傳資料的時候,我只傳0~15即可。
我寫了兩個函式來解決這些問題。這兩個函式均是可變長引數,感覺還比較好用。
shiftOutQPins 這個函式可以用來解決問題2。用法和shirtOut相同,後面多了幾個引數,表示你要使用的針腳。數字對應使用的Q引腳號。引腳使用的次序是按MSBFIRST
和LSBFIRST
來的,和輸入的次序無關。
如果要們要使用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);
}
相關文章
- 關於並口,串列埠問題解決串列埠
- 串列埠SRAM和並口SRAM的引腳區別串列埠
- 第九章openwrt 703N 網口轉串列埠+串列埠轉網口TTL 資料傳輸串列埠
- Arduino 封裝庫UI封裝
- 串列埠,COM口,UART,USART串列埠
- Arduino下的STM32的串列埠通訊UI串列埠
- 沒有真實串列埠裝置時使用"虛擬串列埠驅動"除錯你的串列埠程式碼串列埠除錯
- unity3d透過串列埠接收Arduino資料Unity3D串列埠UI
- IBM串列埠線序以及串列埠線的做法(轉)IBM串列埠
- QT實現串列埠助手中串列埠名的實時更新QT串列埠
- Linux下PCI轉串列埠卡及USB轉串列埠Linux串列埠
- 用VB除錯串列埠通訊 (轉)除錯串列埠
- 前端簡潔並實用的工具類函式封裝前端函式封裝
- MOXA多串列埠卡在Linux下的安裝(轉)串列埠Linux
- 串列埠通訊 (轉)串列埠
- AVR 微控制器串列埠和網口的通訊VR串列埠
- 串列埠通訊應用程式的解決方案 (轉)串列埠
- VC++ 的串列埠通訊 (轉)C++串列埠
- Arduino小車基礎-前進後退和串列埠監視器UI串列埠
- Linux 串列埠程式設計 串列埠裝置程式開發Linux串列埠程式設計
- 用串列埠線連線,終端來安裝aix串列埠AI
- VC++ 串列埠通訊(轉)C++串列埠
- Linux下PCI轉串列埠卡驅動安裝方法Linux串列埠
- 並口與程式設計 (轉)程式設計
- SRAM中晶圓級晶片級封裝的需求晶片封裝
- 使用QSerialport讀取串列埠資料並處理串列埠
- Linux單裝置多路USB串列埠的實現方法介紹Linux串列埠
- ubuntu安裝USB轉串列埠驅動(PL2303)Ubuntu串列埠
- linux下安裝PCIE轉串列埠卡驅動簡介Linux串列埠
- 序列通訊的基本原理及用MFC實現串列埠通訊程式設計 (轉)串列埠程式設計
- uniapp實戰——封裝商品列表元件並使用APP封裝元件
- 串列埠UART串列埠
- C#獲取本地串列埠裝置C#串列埠
- UART串列埠及Linux實現串列埠Linux
- web實現串列埠除錯助手Web串列埠除錯
- QT實現簡易串列埠助手QT串列埠
- VB串列埠使用心得兩則 (轉)串列埠
- 實現埠對埠的聊天 (轉)