// C++ code
//左邊第1顆按鈕 start/pause
//第2顆按鈕 reset 歸0
//第3顆按鈕 up/down
//第4顆按鈕 10-16-8 進制切換
#define delayT 200
//-------- 74595 IC 控制 8LED 元件接腳名稱控制參數設定 ----------------------------------------
#define SH_CP1 8 //SHift Register ClocK INPUT -> SRCLK,SCK;資料輸入序列時脈(前) 74595 PIN_11 接至 PD7,GPIO_7 需設為OUTPUT 模式
#define ST_CP1 7 //STorage Register ClocK INPUT -> RCLK,RCK;暫存器時脈(後) 74595 PIN_12 接至 PD6,GPIO_6 需設為OUTPUT 模式
#define DATA_SER1 6//SERrial Data INPUT -> SER,SI;資料序列輸入 74595 PIN_14 接至 PD5,GPIO_5 需設為OUTPUT 模式
//-------- 74595 IC 控制 七段顯示器 元件接腳名稱控制參數設定 ----------------------------------------
#define SH_CP2 11 //SHift Register ClocK INPUT -> SRCLK,SCK;資料輸入序列時脈(前) 74595 PIN_11 接至 PD7,GPIO_10 需設為OUTPUT 模式
#define ST_CP2 10 //STorage Register ClocK INPUT -> RCLK,RCK;暫存器時脈(後) 74595 PIN_12 接至 PD6,GPIO_9 需設為OUTPUT 模式
#define DATA_SER2 9//SERrial Data INPUT -> SER,SI;資料序列輸入 74595 PIN_14 接至 PD5,GPIO_8 需設為OUTPUT 模式
// 使用 74595 的優點 不需要在解碼使用 bitRead 指令控制周邊 直接將8bit
// 的資料並列輸出 輸出方式可以控制 MSB 或 LSB 先行輸出 使用3條輸入控制線
// 可以擴展到 8 個 GPIO 節省 GPIO 的接腳使用
void setup()
{
for(int i=2;i<=13;i++)
pinMode(i, OUTPUT);
for(int i=14;i<=17;i++)
pinMode(i, INPUT_PULLUP); // 設定成 INPUT_PULLUP 使用內建提升電阻 免去外接電阻
//pinMode(i, INPUT); //宣告成 INPUT 該腳位 GPIO 需要外接4.7K歐姆到 5V
Serial.begin(115200);
}
//---------------------------------------------------------
// 2 進制 轉成16進制 減少程式碼的版面
byte seg[]={0x3F,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x27,0x7f,0x6f,
0x77,0x7c,0x39,0x5e,0x79,0x71,0x00};
byte Buff[]={0,0,0,0,0,0,0,0};
byte scan[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};
//---------------------------------------------------------
int leddis=0;
//----------- 七段顯示副程式 ---------------------------
//------------6條掃描線控制6顆共陰極七段顯示 -------------
void disp(byte data7s,byte number7s ) // data7s 七段顯示器的編碼(byte) number7s 點亮第幾個七段顯示器 (0~1)
{
digitalWrite(ST_CP2, LOW);
shiftOut(DATA_SER2, SH_CP2, MSBFIRST, 0x00);
digitalWrite(ST_CP2, HIGH);
digitalWrite(ST_CP1, LOW);
shiftOut(DATA_SER1, SH_CP1, MSBFIRST, ~seg[data7s]);
digitalWrite(ST_CP1, HIGH);
digitalWrite(ST_CP2, LOW);
shiftOut(DATA_SER2, SH_CP2, MSBFIRST, scan[number7s]);
digitalWrite(ST_CP2, HIGH);
// delay(1); // 必須延遲 1ms 否則會看不到顯示
}
byte no=0;
//-----------顯示副程式-------------------------
void show(void)
{
disp(Buff[no],no); // Buff[0]表示十位數 Buff[1]表示個位數
no = (no+1) % 8; // 因為只有兩個七段 no 為 0~5 的變化
//delay(2);
}
//--------------------------------------------
long pow_value(long base,long number) //自己寫一個次方的副程式
{ // arduino 內建的函式好像有問題
long value=1;
for(long i=1;i<=number;i++)
value=base*value;
return value;
}
//---------------------------------------------------------
unsigned long counterM = 0;
unsigned long count=0,count1=0,count2=0;
int startflag=0;
int updown=0,baseflag=0;
int Base=0;
//----------------------------------------------------------
void counter()
{
// 每隔350ms執行一次底下的條件式內容
if (updown==0)
{
digitalWrite(12,1);digitalWrite(13,0);
}
else
{
digitalWrite(12,0);digitalWrite(13,1);
}
switch(baseflag)
{
case 0:Base=10;break;
case 1:Base=16;break;
case 2:Base=8;break;
default:break;
}
if (millis() - counterM >= 300)
{
counterM = millis();
Buff[0]= count/pow_value(Base,7)%Base;
Buff[1]= count/pow_value(Base,6)%Base;
Buff[2]= count/pow_value(Base,5)%Base;
Buff[3]= count/pow_value(Base,4)%Base;
Buff[4]= count/pow_value(Base,3)%Base;
Buff[5]= count/pow_value(Base,2)%Base;
Buff[6]= count/pow_value(Base,1)%Base;
Buff[7]= count%Base;
if(startflag==1)
{
if (updown==0)
{
count=(count+1)%pow_value(Base,8); // count=0 ~ 999999
}
else
{
count=(count+(pow_value(Base,8)-1))%pow_value(Base,8);
}
}
}
}
//-------------------------------------------------
char ReadKey(void)
{
char key=0;
if( digitalRead(14)==0 ) key |= 1; //當S3按下時為低電位,ReadKey()副程式傳回數值4
if( digitalRead(15)==0 ) key |= 2; //當S2按下時為低電位,ReadKey()副程式傳回數值2
if( digitalRead(16)==0 ) key |= 4; //當S1按下時為低電位,ReadKey()副程式傳回數值1
if( digitalRead(17)==0 ) key |= 8; //當S1按下時為低電位,ReadKey()副程式傳回數值1
return key;
}
//---------------------------------------------------
unsigned long switchkeyM = 0;
int newkey,oldkey;
//---------------------------------------------------------------------
void switchkey()
{
// 每隔20ms執行一次底下的條件式內容
if (millis() - switchkeyM >= 50)
{
switchkeyM = millis();
newkey = ReadKey();
if (newkey!=oldkey)
{
if(newkey == 1) {
startflag=(startflag+1)%2;
}
if(newkey == 2) {
count=0;
startflag=0;
}
if(newkey == 4) {
updown=(updown+1)%2;
count=0;
}
if(newkey == 8) {
baseflag=(baseflag+1)%3;
count=0;
}
oldkey = newkey;
}
}
//Serial.println("fun="+String(fun));
//Serial.println("start="+String(start));
}
//----------------------------------------------------------
void loop()
{
switchkey();
counter();
show();
}