好东东啊,楼主的诺基亚5110屏码表源程序如下:
- /*=========自行车码表=========*/
- #include "Arduino.h"
- #include "U8glib.h"
- #include <Wire.h>
- #include <EEPROM.h>
- #include <DS1307.h>
- //#include <IRremote.h>
- //#define LCD_CMD 0
- #define zdpin 1 //中断源可选值为0或1,分别对应2号和3号引脚
- #define timeOUT 3000 //检测速度超时
- #define EEPDELAY 5000 //EEPROM更新检测
- #define refresh 5 //刷新圈数
- #define EEPROM_write(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) EEPROM.write(address+i, pp[i]);}
- #define EEPROM_read(address, p) {int i = 0; byte *pp = (byte*)&(p);for(; i < sizeof(p); i++) pp[i]=EEPROM.read(address+i);}
- int adc_key_val[5] ={50, 200, 400, 600, 800 };
- int NUM_KEYS = 5;
- int adc_key_in;
- int key = -1;
- int oldkey = -1;
- #define jsLCD 6000 //设置时显示时间
- boolean lcda = false; //boolean 数据类型 boolean 变量存储为 8 位(1 个字节)的数值形式,但只能是 True 或是 False
- boolean lcdb = false;
- long TIMELCDa; //长整数型变量 可以存储32位(4字节)
- long TIMELCDb;
- int LCDSW=0;//整数数据类型占用2字节,范围-32768到32767
- int lcdSW=0;
- int R; //cm
- int V; //km/h
- boolean Rsetup,Vsetup; //半径数值
- long CACHEDELAY;
- int Reep; //xxeep判断数值是否更改,set为设置值
- int Veep;
- float MILEeep; //浮点型数据,就是有小数点的数字,经常被用来模拟连续值
- struct config_type
- {
- int EEPROMMILE;
- int EEPROMMILEs;
- int EEPROMR;
- int EEPROMV;
- };
- /*-------lcd------*/
- U8GLIB_PCD8544 u8g(5, 6, 8, 7, 9); // SPI Com: CLK = 5, DIN = 6, CE = 8, DC = 7, Reset = 9
- int BGKEY = 10;//背光灯按键引脚
- int SUM = 0; //背光灯亮度值
- int Flag_up = 1; //按键扫描
- int beeppin = 12; //蜂鸣器引脚定义
- int num;
- float SPEED;
- float MSPEED; //平均速度
- float ALLMILE; //所有的里程
- float ONEMILE,ONEMILEcache;
- long RPM; //每分钟的旋转次数
- /*------计时-----*/
- long timea,timeb;
- long time,timecache;
- boolean timeSTA;
- //*----time----*/
- String comdata = ""; //串口数据缓存
- int numdata[7] = {0}, j = 0, mark = 0;
- int rtc[7];
- int TIMEshi, TIMEfen, TIMEmiao; //时钟
- #define SHEtimeOUT 6000
- int sheshi, shefen;
- int shenum;
- boolean shesta = false, shesw, sheDOWN = false, sheUP = false;
- long SHEtime;
- /*----MENU----*/
- //#define MENUtimeOUT 5000
- boolean MENUup = false, MENUdown = false;//MENUsta = false, MENUsw = false, MENUup10x = false, MENUdown10x = false;
- //int MENUswNUM = 0;
- //long MENUtime;
- /*-------ir------*/
- //int RECV_PIN = A0; //红外输入
- //IRrecv irrecv(RECV_PIN);//定义IRrecv对象来接收红外线信号
- //decode_results results;//解码结果放在decode_results构造的对象results里
- /*-----------------按键设置-----------------*/
- //将adc(模数转换器)值转换为键号
- int get_key(unsigned int input)
- {
- int k;
- for (k = 0; k < NUM_KEYS; k++)
- {
- if (input < adc_key_val[k])
- return k;
- }
- if (k >= NUM_KEYS)k = -1; // 未按有效键
- return k;
- }
- /*利用芯片内部1.1v基准电压反算出电源电压(模拟输入端口A7)*/
- unsigned int ADCValue;
- double Voltage;
- double Vcc;
- //读取vcc电压
- long readVcc() {
- long result;
- // Read 1.1V reference against AVcc 读取1.1V AVcc
- ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
- delay(2); // Wait for Vref to settle 等待Vref解决
- ADCSRA |= _BV(ADSC); // Convert 转换
- while (bit_is_set(ADCSRA,ADSC));
- result = ADCL;
- result |= ADCH<<8;
- result = 1125300L / result; // Back-calculate AVcc in mV 反算出AVcc 为mv
- return result;
- }
- void setup ()
- {
- u8g.setContrast(140);//设置对比度0-255
- pinMode(BGKEY, INPUT_PULLUP); //按键IO设定为带上拉输入
- pinMode(11,OUTPUT); //该端口需要选择有~号标识的数字口(有~号表示是支持PWM的引脚)*/
- pinMode(beeppin, OUTPUT);//蜂鸣器输出
-
- /*按着背光灯按键同时上电,开机后数据清零*/
- if(digitalRead(BGKEY) == LOW)
- {
- for (int i = 0 ; i < EEPROM.length() ; i++) {
- EEPROM.write(i, 0);
- }
- }
- Serial.begin(9600);
- /*EEPROM读取赋值*/
- config_type config_readback;
- EEPROM_read(0, config_readback);
- ALLMILE = float(config_readback.EEPROMMILE+(config_readback.EEPROMMILEs/10.0));
- MILEeep = config_readback.EEPROMMILE;
- R = config_readback.EEPROMR;
- V = config_readback.EEPROMV;
- Reep = config_readback.EEPROMR;
- Veep = config_readback.EEPROMV;
- attachInterrupt(zdpin,light,FALLING); //检测中断
- /*中断函数(attachInterrupt):attachInterrupt(interrupt,function,mode)
- interrupt:中断源(在Arduino中,中断源可选值为0或1,一般分别对应2号和3号引脚)
- function:需要中断的函数名
- mode:LOW(低电平触发)、CHANGE(变化时触发)、
- RISING(低电平变为高电平触发)、FALLING(高电平变为低电平触发)
- 注意:在写代码时,interrupt处要写成0或1,不能写成2或3*/
- CACHEDELAY=millis();
- ONEMILEcache=ALLMILE;
-
- RTC.SetOutput(DS1307_SQW32KHZ);
- // irrecv.enableIRIn(); //启动红外解码 开始采集
-
- adc_key_in = analogRead(0); //从传感器读取值
- key = get_key(adc_key_in); //转换成按键
- }
-
- void loop()
- {
- Rsetup = false;
- Vsetup = false;
- MENUup = false;
- MENUdown = false;
- // MENUup10x = false;
- //MENUdown10x = false;
- //MENUsw = false;
- shesw = false;
- RTC.get(rtc, true);
- TIMEshi = rtc[2];
- TIMEfen = rtc[1];
- TIMEmiao = rtc[0];
- /*----------背光灯亮度调整----------*/
- if ( ScanKey() == 1) //当有按键按下时
- {
- SUM+=63; //SUM加一
- tone(beeppin,4000);
- delay(30);
- noTone(beeppin);
- }
- if (SUM >252)
- {
- SUM = 0;
- }
- /*=================红外控制=================*/
- //if (irrecv.decode(&results))
- // {
- // voir();
- //}
- /*=================按键控制=================*/
- adc_key_in = analogRead(0); //从传感器读取值
- key = get_key(adc_key_in);
- if (key != oldkey) //如果检测到按键
- {
- delay(50); //去抖动时间
- tone(beeppin,4000);
- delay(30);
- noTone(beeppin);
- voir();
- }
-
- /*=======码表=======*/
- if(num>refresh)
- {
- jisuan();
- timea=millis();
- num=1;
- }
- ONEMILE=ALLMILE-ONEMILEcache;
- if(millis()-timeb>timeOUT)
- {
- RPM=0; //每分钟圈数=0
- SPEED=0;
- timeSTA=false;
- timecache=millis()-time;
- }
- else
- {
- timeSTA=true;
- time=millis()-timecache;
- }
- if(ALLMILE>9999)
- {
- ALLMILE=0;
- }
- /*==========EEPROM==========*/
- if (millis() - CACHEDELAY > EEPDELAY)
- {
- if(MILEeep != ALLMILE||Reep!=R||Veep!=V) //判断EEPROM是否有改变
- {
- eeprom_write();
- MILEeep = ALLMILE;
- Reep = R;
- Veep =V;
- }
- CACHEDELAY=millis();
- }
- /*==============半径设置=================*/
- if(Rsetup==true)
- R++;
- if(R>50)
- R=1;
- // if(R<10)
- // R=60;
- /* ==============限速警报设置================= */
- if(Vsetup==true)
- V += 5; //每按一次加 5 km/h
-
- if(V>120) //大于120 km/h 返回 5km/h
- V=5;
- /*==================Time======================*/
- if(shesta == true) //进入设置状态
- {
- voshe();
- }
- if(shesw == true) //切换
- shenum++;
- if(shenum > 2) //范围
- shenum = 1;
- /* RTC.get(rtc, true);
- TIMEshi = rtc[2];
- TIMEfen = rtc[1];
- TIMEmiao = rtc[0];*/
- if (sheshi > 23)
- {
- sheshi = 1;
- }
- if (sheshi < 0)
- {
- sheshi = 23;
- }
- if (shefen > 59)
- {
- shefen = 0;
- }
- if (shefen < 0)
- {
- shefen = 59;
- }
- /*===========LCD===========*/
- if(Rsetup == true ) //半径设置触发
- {
- TIMELCDa = millis();
- lcda = true;
-
- }
- if(lcda == true)
- {
- voLCDadelay();
- }
-
- if( Vsetup == true) //限速报警设置触发
- {
- TIMELCDb = millis();
- lcdb = true;
-
- }
- if(lcdb == true)
- {
- voLCDbdelay();
- }
-
- u8g.firstPage();
- do {
- draw();
- }
- while( u8g.nextPage() );
-
- if(SPEED > V) //
- {
- baojing();
- }
- else
- {
- digitalWrite(beeppin, LOW);
- }
- }
- void jisuan()
- {
- ALLMILE+=((float(refresh)*(2.0*3.1416*(R/100.0))))/1000.0; //总里程累加
- RPM=60000/((millis()-timea)/refresh); //转速
- SPEED=((RPM*(2.0*3.14159*(R/100.0)))*60.0)/1000.0; //速度
- }
- void light() //计数
- {
- num++;
- timeb=millis();
- }
- void eeprom_write()
- {
- config_type config; // 定义结构变量config,并定义config的内容
- config.EEPROMMILE = int(ALLMILE);
- config.EEPROMMILEs = int(ALLMILE*10)%10;
- config.EEPROMR = R;
- config.EEPROMV = V;
- EEPROM_write(0, config); // 变量config存储到EEPROM,地址0写入
- }
-
- void voadd(int add)
- {
- if (add < 10)
- u8g.print("0");
- }
- void voLCDadelay() //显示超时
- {
- if (millis() - TIMELCDa > jsLCD && lcda == true) //设置刷新频率
- {
- lcda = false;
- }
- }
- void voLCDbdelay()
- {
- if (millis() - TIMELCDb > jsLCD && lcdb == true) //设置刷新频率
- {
- lcdb = false;
- }
- }
- void voir()
- {
- switch(key)
- {
- case 0:
- Rsetup = true;
- LCDSW=1;
- break;
- case 1:
- Vsetup = true;
- lcdSW=1;
- break;
- case 2:
- shesw = true;
- voshe();
- voshesta();
- break;
- case 3:
- MENUdown = true;
- break;
- case 4:
- MENUup = true;
- break;
- }
-
- delay(100);
- }
- //将ADC值转换为键号
- /*
- unsigned long remote = results.value; //设红外信号为remote
- if(remote == (-1)) //溢出时
- {
- Serial.print(results.value, HEX); //输出红外线解码结果(十六进制)
- }
- switch (remote)
- {
- case 0xFD6897: //CH+
- Rsetup = true;
- LCDSW=1;
- break;
- case 0xFDE817: //CH-
- Rsetdown = true;
- LCDSW=1;
- break;
- case 0xFDA857: //EQ
- shesw = true;
- voshe();
- voshesta();
- break;
- case 0xFD9867: //-
- MENUdown = true;
- break;
- case 0xFD18E7: //+
- MENUup = true;
- break;
- case 0xFD12ED: //PREV
- MENUdown10x = true;
- break;
- case 0xFD48B7: //NEXT
- MENUup10x = true;
- break;
- }
- irrecv.resume(); // 返回值
- }
- */
- void draw() {
- Vcc = readVcc()/1000.0;//将读取的vcc电压mv转换为v
- ADCValue = analogRead(7);
- Voltage = (ADCValue / 1023.0) * Vcc;
- MSPEED=(ONEMILE/time)*1000*60*60;
- u8g.setDefaultForegroundColor();
- u8g.drawLine(0, 19, 83, 19);
- u8g.drawLine(0, 27, 83, 27);
- u8g.drawLine(27, 28, 27, 40);
- u8g.drawLine(0, 41, 84, 41);
-
- u8g.setFont(u8g_font_ncenB08r);
- u8g.setPrintPos(45, 18);
- u8g.print("Km/h");
- /*--------电量显示--------*/
- if (Voltage >=3.9){
- u8g.drawLine(80, 2, 81, 2);
- u8g.drawFrame(78,3,6,15);//电池外形
- u8g.drawBox(80,5,2,2);//电池电量段
- u8g.drawBox(80,8,2,2);
- u8g.drawBox(80,11,2,2);
- u8g.drawBox(80,14,2,2);
- }
- if (Voltage <3.9 && Voltage >=3.7 ){
- u8g.drawLine(80, 2, 81, 2);
- u8g.drawFrame(78,3,6,15);//电池外形
- u8g.drawBox(80,8,2,2);//电池电量段
- u8g.drawBox(80,11,2,2);
- u8g.drawBox(80,14,2,2);
- }
- if (Voltage <3.7 && Voltage>=3.5 ){
- u8g.drawLine(80, 2, 81, 2);
- u8g.drawFrame(78,3,6,15);//电池外形
- u8g.drawBox(80,11,2,2);//电池电量段
- u8g.drawBox(80,14,2,2);
- }
- if (Voltage <3.5 && Voltage >=3.2){
- u8g.drawLine(80, 2, 81, 2);
- u8g.drawFrame(78,3,6,15);//电池外形
- u8g.drawBox(80,14,2,2);//电池电量段
- }
- if (Voltage <3.2 && Voltage >=3.0 ){
- u8g.drawLine(80, 2, 81, 2);
- u8g.drawFrame(78,3,6,15);//电池外形
- }
- if (Voltage < 3.0 ) { //当VCC电压小于3v时图标闪烁,电池电量不足警告
- if(millis()/1000%2!=0){
- u8g.drawLine(80, 2, 81, 2);
- u8g.drawFrame(78,3,6,15);//电池外形
- u8g.drawLine(79, 4, 82, 17);
- }
- else{
- u8g.setPrintPos(80, 2); //只要是不影响其他显示此位置可任选
- u8g.print("");
- }
- }
- /*背光灯4档可调,当电池电压低于3.2v时背光灯熄灭,节约电能*/
- if(Voltage >=3.2){
- analogWrite(11,SUM);//使用PWM控制11号口输出,变量n的取值范围是0-255
- }
- else{
- digitalWrite(11, LOW);
- }
-
- u8g.setPrintPos(47, 7);
- if(shesta == true) //进入设置状态
- {
- u8g.setFont(u8g_font_6x12);
- switch(shenum)
- {
- case 1:
- {
- if((millis() / 1000) % 2 != 0)
- {
- voadd(sheshi);
- u8g.print(sheshi);
- }
- else
- u8g.print(" ");
- u8g.print(":");
- voadd(shefen);
- u8g.print(shefen);
- }
- ;
- break;
- case 2:
- {
- voadd(sheshi);
- u8g.print(sheshi);
- u8g.print(":");
- if((millis() / 1000) % 2 != 0)
- {
- voadd(shefen);
- u8g.print(shefen);
- }
- else
- {
- u8g.print(" ");
- }
- }
- ;
- break;
- }
- }
- else //正常显示时间
- {
- u8g.setFont(u8g_font_6x12);
- voadd(TIMEshi);
- u8g.print(TIMEshi); //hou
- if(millis()/1000%2!=0)
- u8g.print(":");
- else
- u8g.print(" ");
- voadd(TIMEfen);
- u8g.print(TIMEfen); //min
- }
- u8g.setPrintPos(1, 26);
- {
- u8g.setDefaultForegroundColor();
- u8g.drawBox(0, 20, 84, 8);
- u8g.setDefaultBackgroundColor();
- u8g.setFont(u8g_font_chikitar);
- u8g.print("MSPEED:");//平均时速
- u8g.setPrintPos(40, 26);
- voadd(MSPEED);
- u8g.print(int (MSPEED*10)/10);
- u8g.print(".");
- u8g.print(int (MSPEED*10)%10);
- }
- u8g.setFont(u8g_font_04b_03b);
- u8g.setPrintPos(62, 26);
- u8g.print("km/h");
- u8g.setDefaultForegroundColor();
- u8g.setPrintPos(0, 39); //单次里程
- u8g.setFont(u8g_font_6x13);
- u8g.print("ONCE");
- u8g.setPrintPos(32, 34);
- {
- u8g.setFont(u8g_font_chikitar);
- voadd(ONEMILE);
- u8g.print((int)ONEMILE);
- u8g.print(".");
- u8g.print(int(ONEMILE*10)%10);
- u8g.print(int(ONEMILE*100)%10);
- }
- u8g.setPrintPos(32, 40); //单次时间
- {
- u8g.setFont(u8g_font_chikitar);
- voadd(time/1000/60/60);
- u8g.print(time/1000/60/60);
- u8g.print(" hr ");
-
- voadd(time/1000/60%60);
- u8g.print(time/1000/60%60);
- }
- u8g.setFont(u8g_font_chikitar);
- u8g.setPrintPos(70, 34);
- u8g.print("km");
- u8g.setPrintPos(70, 40);
- u8g.print("min");
-
- if (lcda == true) //半径设置
- {
-
- if(LCDSW==1)
- {
- u8g.setDefaultForegroundColor();
- u8g.drawBox(0, 42, 84, 6);
- u8g.setDefaultBackgroundColor();
- u8g.setFont(u8g_font_chikitar);
- u8g.setPrintPos(1, 47);
- u8g.print("Wheel radius: ");
- voadd(R);
- u8g.print(R);
- u8g.setPrintPos(72, 47);
- u8g.print("cm");
- }
- }
- else
- {
- u8g.setDefaultForegroundColor();
- u8g.setFont(u8g_font_chikitar);
- u8g.setPrintPos(0, 48);
- u8g.print("MILE: "); //总里程
- u8g.setPrintPos(32, 48);
- if(int(ALLMILE*10)/10<10)
- {
- u8g.print("000");
- }
- if(int(ALLMILE*10)/10>10 && int(ALLMILE*10)/10<100)
- {
- u8g.print("00");
- }
- if(int(ALLMILE*10)/10>100 && int(ALLMILE*10)/10<1000)
- {
- u8g.print("0");
- }
- u8g.print(int(ALLMILE));
- u8g.print(".");
- u8g.print(int(ALLMILE*10)%10);
- u8g.setPrintPos(70, 48);
- u8g.print("km");
- }
- if (lcdb == true) //报警设置
- {
- if(lcdSW==1)
- {
- u8g.setDefaultForegroundColor();
- u8g.drawBox(0, 0, 44, 19);
- u8g.setDefaultBackgroundColor();
- u8g.setFont(u8g_font_5x8);
- u8g.setPrintPos(5, 8);
- u8g.print("SPEED/L");
- u8g.setPrintPos(4, 18);
- voadd(V);
- u8g.print(V);
- u8g.setPrintPos(21, 18);
- u8g.print("km/h");
- }
- }
- else
- {
- u8g.setDefaultForegroundColor();
- u8g.setFont(u8g_font_timB18r);
- u8g.setPrintPos(0, 18);
- voadd(int(SPEED*10)/10);
- if(SPEED >=100){
- u8g.print(int(SPEED*10)/10); //SPEED
- }
- else{
- u8g.print(int(SPEED*10)/10); //SPEED
- u8g.print(".");
- u8g.print(int(SPEED*10)%10);
- }
- }
- }
- void voshe()
- {
- if(shenum == 0) //初始赋值
- {
- sheshi = TIMEshi;
- shefen = TIMEfen;
- }
- RTC.stop(); //准备写入时间
- if(millis() - SHEtime > SHEtimeOUT) //超时
- {
- shesta = false; //退出设置
- shenum = 0; //初始
- RTC.set(DS1307_HR, sheshi);
- RTC.set(DS1307_MIN, shefen);
- RTC.set(DS1307_SEC, 0);
- RTC.start();
- }
- if(MENUup == true || MENUdown == true )//|| MENUup10x == true || MENUdown10x == true //触发时
- {
- voshesta();
- }
- switch(shenum) //按键作用
- {
- case 1:
- {
- if(MENUup == true)
- {
- sheshi++;
- }
- if(MENUdown == true)
- {
- sheshi--;
- }
- /* if(MENUup10x == true)
- {
- sheshi += 10;
- }
- if(MENUdown10x == true)
- {
- sheshi -= 10;
- }*/
- };
- break;
- case 2:
- {
- if(MENUup == true)
- {
- shefen++;
- }
- if(MENUdown == true)
- {
- shefen--;
- }
- /* if(MENUup10x == true)
- {
- shefen += 10;
- }
- if(MENUdown10x == true)
- {
- shefen -= 10;
- }*/
- };
- break;
- }
- }
- void voshesta() //触发时间设置状态
- {
- SHEtime = millis();
- shesta = true;
- }
- int ScanKey() //按键扫描程序,返回键值
- {
- if (Flag_up && digitalRead(BGKEY) == LOW) //当Flag_up = 1并且按键按下时
- {
- Flag_up = 0; //清空Flag_up
- delay(20); //延时去抖动
- if (digitalRead(BGKEY) == LOW) //按键按下
- {
- return 1; //返回键值1
- }
- }
- if (digitalRead(BGKEY) == HIGH) //按键松开时候
- {
- Flag_up = 1; //置位Flag_up
- }
- return 0; //返回键值0
- }
- void baojing()
- {
- tone(beeppin,4500);
- delay(50);
- noTone(beeppin);
- tone(beeppin,4500);
- delay(50);
- noTone(beeppin);
- }
复制代码 |