赞
踩
功能介绍:
0.本系统采用STC89C52作为单片机
1.采用LCD1602来实时显示计步器的数据
2.预留有串口可以自己开发蓝牙功能
3.设计EEPROM可以保存计步的相关数据,断电后下次上电依然可以查询
4.采用DC002作为电源接口可直接输入5V给整个系统供电
5.计步的传感器采用的是加速度传感器ADXL345
原理图:
PCB:
主程序:
#include "main.h" enum _MODE_DF_ dispMode; unsigned char setIndex = 0; char dis0[16]; //数组 bit readAdx = 0; //定时读取adxl345 bit refreshFlag = 0; //定时更新屏幕 unsigned int stepCnt = 0; //累计步数 float distance = 0; //累计距离 float calorie = 0; //累计卡路里 unsigned char statusFlag = 0; //状态 unsigned char isNewFlag = 0; //数据记录 unsigned char saveCnt = 0; //数据记录 void main(void) { Init_Timer0(); //定时器0初始化 LCD_Init(); //初始化液晶 DelayMs(20); //延时有助于稳定 LCD_Clear(); EEPROM_Init(); isNewFlag = EEPROM_ReadByte(IS_NEW_ADDR); //读取芯片标志 if (isNewFlag != 0) //如果是新机 { isNewFlag = 0; EEPROM_WriteByte(IS_NEW_ADDR, isNewFlag); //将不是新芯片标志写入EEPROM EmptyData(); } else { saveCnt = EEPROM_ReadByte(SAVECNT_ADDR); //读取存储数量 } Init_ADXL345(); //清屏 if (Single_Read_ADXL345(0X00) == 0xe5) //读出的数据为0XE5,表示正确 { DelayMs(5); } else { DelayMs(3); } while (1) //主循环 { if (readAdx) //定时读取adxl345数据 { readAdx = 0; StepCheck(); //检测步数 } if (refreshFlag) { refreshFlag = 0; if (dispMode == NORMAL) { DispNormal(); } } KeyScan(); } } //步数检测 void StepCheck(void) { static unsigned char ErrorNum = 0; //变量定义 static unsigned char NormalNum = 0; static unsigned char CheckNum = 0; //变量定义 static unsigned char standNum = 0; static unsigned char sidewaysNum = 0; static unsigned int remStep = 0; ReadData_x(); CheckNum++; //检测次数 if ((temp_X < 650) || (abs(temp_Y) > 400)) //查看正常次数 { LED_STATUS = 0; //呼吸灯 ErrorNum++; //记录次数 standNum++; //竖直状态++ } else { NormalNum++; sidewaysNum++; LED_STATUS = 1; } //呼吸灯//侧着状态++ if ((NormalNum != 0) && (ErrorNum != 0)) // 从角度判断走了一步 { ErrorNum = 0; NormalNum = 0; stepCnt++; distance = (float)(stepCnt / 2) * 0.45; //计算距离 calorie = distance * 70 * 0.832; //卡路里计算 走路 距离*体重*系数 } if (CheckNum >= 20) { if ((sidewaysNum != 0) && (standNum == 0)) { statusFlag = 0; //站着状态 } else if ((sidewaysNum == 0) && (standNum != 0)) { statusFlag = 1; //躺着状态 } else if ((sidewaysNum != 0) && (standNum != 0)) { if ((stepCnt - remStep) >= 6) //跑着 一个周期大于3步 { statusFlag = 2; } //跑着状态 else { statusFlag = 3; } //走着状态 remStep = stepCnt; //记录上次步数 } CheckNum = 0; sidewaysNum = 0; //清空计数 standNum = 0; } } //正常显示 void DispNormal(void) { sprintf(dis0, "S:%04d D:%6.1fm ", stepCnt / 2, distance); //打印 LCD_Write_String(0, 0, dis0); //显示 sprintf(dis0, "%7.2fcal ", calorie); //打印 LCD_Write_String(0, 1, dis0); //显示 if (statusFlag == 0) //站着状态 { LCD_Write_String(11, 1, "Stand"); } else if (statusFlag == 1) 躺着状态 { LCD_Write_String(11, 1, "Lie "); } else if (statusFlag == 2) //跑着状态 { LCD_Write_String(11, 1, "Run "); } else if (statusFlag == 3) //走着状态 { LCD_Write_String(11, 1, "Walk "); } } //显示选择界面 void DispSelect(unsigned char setIndex) { LCD_Write_String(1, 0, "1.Search"); //选项1查询 LCD_Write_String(1, 1, "2.Empty All"); //选项2删除所有 if (setIndex == 1) { DispOneChar(0, 0, '>'); DispOneChar(0, 1, ' '); } else if (setIndex == 2) { DispOneChar(0, 0, ' '); DispOneChar(0, 1, '>'); } } //显示读取步数 void DispReadStep(unsigned char i) { unsigned int readStep = 0; readStep = ReadData(i); sprintf(dis0, "Data %02d S:%04d", (int)i, readStep); //打印 LCD_Write_String(0, 0, dis0); //显示 } //存储数据 void SaveData(void) { if (saveCnt >= MAXCNT) //最大存储数量 { LCD_Clear(); LCD_Write_String(0, 0, " Storage Full! "); //显示存储空间已满 DelayMs(200); DelayMs(200); DelayMs(200); DelayMs(200); } else { EEPROM_WriteByte(START_ADDR + 2*saveCnt, (((stepCnt/2) & 0xFF00) >> 8)); DelayMs(1); EEPROM_WriteByte(START_ADDR + 2*saveCnt + 1, ((stepCnt/2) & 0x00FF)); DelayMs(1); saveCnt++; EEPROM_WriteByte(SAVECNT_ADDR, saveCnt); //将存储数据总数写入EEPROM DelayMs(1); } } //读取数据 unsigned int ReadData(unsigned char i) { unsigned int readStep = 0; readStep = EEPROM_ReadByte(START_ADDR + 2*i); DelayMs(1); readStep = EEPROM_ReadByte(START_ADDR + 2*i + 1) | (readStep << 8); DelayMs(1); return readStep; } //清空数据 void EmptyData(void) { unsigned char i; saveCnt = 0; stepCnt = 0; EEPROM_WriteByte(SAVECNT_ADDR, saveCnt); //将存储数据总数写入EEPROM DelayMs(1); for (i = 0; i < MAXCNT; i++) { EEPROM_WriteByte(START_ADDR + 2*i, (((stepCnt/2) & 0xFF00) >> 8)); DelayMs(1); EEPROM_WriteByte(START_ADDR + 2*i + 1, ((stepCnt/2) & 0x00FF)); DelayMs(1); } } //按键扫描 void KeyScan() { static char cnt = 0; if (!KEY_SEARCH) //查询键按下 { DelayMs(5); if (!KEY_SEARCH) { if (dispMode == NORMAL) { LCD_Clear(); dispMode = SELECT; setIndex = 1; } else if (dispMode == SELECT) { LCD_Clear(); dispMode = NORMAL; setIndex = 0; } switch (dispMode) { case SELECT: DispSelect(setIndex); break; } } while (!KEY_SEARCH) ; } if (!KEY_ENTER) //确认键按下 { DelayMs(5); if (!KEY_ENTER) { if (dispMode == SELECT) { if (setIndex == 1) { LCD_Clear(); dispMode = SEARCH; cnt = 0; } else if (setIndex == 2) { LCD_Clear(); LCD_Write_String(0, 0, " Empty All! "); EmptyData(); DelayMs(200); DelayMs(200); DelayMs(200); DelayMs(200); LCD_Clear(); dispMode = NORMAL; } } else if (dispMode == SEARCH) { LCD_Clear(); dispMode = NORMAL; } switch (dispMode) { case SELECT: DispSelect(setIndex); break; case SEARCH: DispReadStep(cnt); break; } } while (!KEY_ENTER) ; } if (!KEY_UP) //上键按下 { DelayMs(5); if (!KEY_UP) { if (dispMode == NORMAL) { LCD_Clear(); sprintf(dis0, "Save %2d Success!", (int)(saveCnt)); LCD_Write_String(0, 0, dis0); SaveData(); //存储数据 DelayMs(200); DelayMs(200); DelayMs(200); DelayMs(200); stepCnt = 0; //归零本次数据 distance = 0; calorie = 0; } else if (dispMode == SELECT) { setIndex++; if (setIndex > 3) { setIndex = 1; } } else if (dispMode == SEARCH) { cnt++; if (cnt >= MAXCNT) { cnt = 0; } } switch (dispMode) { case SELECT: DispSelect(setIndex); break; case SEARCH: DispReadStep(cnt); break; } } while (!KEY_UP) ; } if (!KEY_DOWN) //下键按下 { DelayMs(5); if (!KEY_DOWN) { if (dispMode == NORMAL) { stepCnt = 0; //归零本次数据 distance = 0; calorie = 0; } else if (dispMode == SELECT) { setIndex--; if (setIndex < 1) { setIndex = 2; } } else if (dispMode == SEARCH) { cnt--; if (cnt < 0) { cnt = MAXCNT - 1; } } switch (dispMode) { case SELECT: DispSelect(setIndex); break; case SEARCH: DispReadStep(cnt); break; } } while (!KEY_DOWN) ; } } //定时器0初始化 void Init_Timer0(void) { TMOD &= 0xF0; TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 TH0 = (65536 - 18432) / 256; //重新赋值 20ms TL0 = (65536 - 18432) % 256; EA = 1; //总中断打开 ET0 = 1; //定时器中断打开 TR0 = 1; //定时器开关打开 } //定时器0中断 void Timer0_isr(void) interrupt 1 { static unsigned int time_20ms = 0; //定时器计数; TH0 = (65536 - 18432) / 256; //重新赋值 20ms TL0 = (65536 - 18432) % 256; time_20ms++; if (time_20ms >= 200) { time_20ms = 0; } if (time_20ms % 10 == 0) { refreshFlag = 1; } if (time_20ms % 5 == 0) { readAdx = 1; } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。