1. 程式人生 > >【Arduino】8位LED數碼管(3461BS)

【Arduino】8位LED數碼管(3461BS)

淘寶買了一塊3461BS的8位LED數碼管,寶貝一到就迫不急待的想試試,結果一看文件,好傢伙沒有Arduino的測試程式。莫急~莫急~反正是串列埠操作,大不了瞎蒙唄!

以下兩點是瞎蒙過程中比較有趣的兩點:

1、需要了解什麼是“上升沿”、“下降沿”,否則看參考程式碼(文件只提供51微控制器的DEMO)會覺得很迷糊

2、如何顯示小數點?這個文件中提都沒提到,經研究發現每個字元(如0用0xC0表示)的最高位(即左數第一位)都是1(兩進製表示),於是我試探性的將其與上0x7f(即0xC0 & 0X7F),結果驚喜的發現苦苦尋覓的小數點出現啦!

其它應該問題不大,直接貼出程式碼:

#include <string.h>

int DIO = 2;
int RCLK = 3;
int SCLK = 4;

unsigned char CHAR_MAP[] = { 0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8, 0x80, 0x90, 0x8C, 0xBF, 0xC6, 0xA1, 0x86, 0xFF, 0xbf };
char CHAR_INDEX_MAP[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', '-' };

void ledout(unsigned char chr)
{
	unsigned char i;
	for (i = 8; i >= 1; i--)
	{
		if (chr & 0x80) digitalWrite(DIO, 1); else digitalWrite(DIO, 0);
		chr <<= 1;
		digitalWrite(SCLK, 0);
		digitalWrite(SCLK, 1);
	}
}

void ledshow(const char* str)
{
	int len = strlen(str);
	int hasDot = 0;
	for (int i = len - 1, m = 0; i >= 0; i--) {
		char chr = str[i];
		if (chr == '.') {
			hasDot = 1;
			continue;
		}
		int n = 0;
		for (; n < 17; n++) {
			if (chr == CHAR_INDEX_MAP[n])
				break;
		}
		if (n != 17) {
			unsigned char chr1 = CHAR_MAP[n];
			if (hasDot)
				chr1 &= 0x7f; // 所有字元的最高位(左數第一位)都是1,代表小數點為暗
							// 因此只要將最高位改為0小數點就可以點亮啦
			ledout(chr1); // 顯示字元
			ledout((int)ceil(pow(2, m))); // 位置
			digitalWrite(RCLK, 0);
			digitalWrite(RCLK, 1);
		}

		m++;
		hasDot = 0;
	}
}

void setup()
{
	pinMode(DIO, OUTPUT);
	pinMode(RCLK, OUTPUT);
	pinMode(SCLK, OUTPUT);
}

void loop()
{
	ledshow("3.1415926");
}