功能介绍:
0.本系统采用STC89C52作为单片机
1.系统实现监测跑步者心率和跑步机速度并显示
2.可以设置跑步速度
3.当心率低于设定下限阈值时跑步机升高速度档位
4.当心率超过设定上限阈值时跑步机降低速度档位,同时蜂鸣器发出警报
5.采用DC002作为电源接口可直接输入5V给整个系统供电
原理图:
PCB :
主程序:
#include <reg52.h> //调用单片机头文件
#include <intrins.h>
#include <stdio.h>
#include "lcd1602.h"
#include "main.h"
#define DIAMETER 20 //直径mm
bit rekey; //按键标志
bit startFlag = 0; //启动标志
bit setFlag = 0; //设置标志
unsigned char setIndex = 0;
unsigned char datIndex = 0;
unsigned int heartRateBuf[6] = {0}; //暂存心率值
unsigned int heartRate = 0;
unsigned int heartRateH = 120;
unsigned int heartRateL = 60;
unsigned char tab0[16]; //显示内容缓存
unsigned char motorPWM = 1; //设定速度档位
unsigned char realMotorPWM = 1; //真实速度档位
unsigned int xdata pulseCnt = 0;
unsigned int timeCnt = 0;
bit dispFlag = 0; //更新显示标志
bit updateFlag = 0; //更新心率标志
bit refreshFlag = 0;
/****************主函数***************/
void main()
{
LED_GREEN = OFF;
LED_RED = ON;
BUZZER = OFF;
EA = 0;
Timer0_Init(); //初始化定时器
Timer1_Init();
Ext0_1_Init(); //外部中断0初始化程序
LCD_Init(); //初始化液晶
DelayMs(20); //延时有助于稳定
LCD_Clear(); //清屏
DelayMs(10);
MOTOR_INA = 1;
MOTOR_INB = 1;
EA = 1;
while (1)
{
if (refreshFlag == 1) //刷新心率
{
EX0 = 0;
TR0 = 0;
refreshFlag = 0;
heartRateBuf[datIndex] = timeCnt * 5; //算出间隔时间
TH0 = 0xEE; //(65536 - 0.005*11059200/12 + 200) / 256
TL0 = 0xC8; //(65536 - 0.005*11059200/12 + 200) % 256 5ms
timeCnt = 0; //50ms计数清零
datIndex++;
if (datIndex > 3) //记录到超过等于2次时间
{
datIndex = 1; //计数从1开始
updateFlag = 1; //测得4次开始显示
}
EX0 = 1;
TR0 = 1;
}
if (dispFlag == 1) //更新显示标志置位
{
dispFlag = 0; //更新显示标志清零
if (setFlag == 0)
{
if (updateFlag == 0) //如果显示关 检测心率是否真实
{
heartRate = 0;
}
else //如果显示开
{
heartRate = 60000 / ((heartRateBuf[1]>>1) + (heartRateBuf[2]>>1)); //心率计算 2次求平均值
}
if (startFlag == 1) //跑步机启动情况下
{
if (heartRate > heartRateH) //心率超过阈值
{
realMotorPWM = motorPWM - 1; //速度档位降低1档
//BUZZER = ON; //蜂鸣器报警
}
else if (heartRate < heartRateL)
{
realMotorPWM = motorPWM + 1; //速度档位升高1档
BUZZER = OFF;
}
else
{
realMotorPWM = motorPWM; //速度档位等于设定档位
BUZZER = OFF;
}
}
else
{
realMotorPWM = motorPWM; //速度档位等于设定档位
BUZZER = OFF;
}
DelayMs(20);
DispNormal();
}
}
KeyProcess();
}
}
/************************* 正常显示 *************************/
void DispNormal(void)
{
sprintf(tab0, "H:%3dbpm S%2d A%2d", heartRate, (int)motorPWM, (int)realMotorPWM); //显示心率和速度档位
EA = 0;
LCD_DispStr(0, 0, tab0); //显示心率
EA = 1;
sprintf(tab0, "Speed:%5.1fkm/h", (float)pulseCnt*3.6*3.14*DIAMETER/1000); //显示速度
pulseCnt = 0;
EA = 0;
LCD_DispStr(0, 1, tab0); //显示转速
EA = 1;
}
/************************* 显示设定心率上下限 *************************/
void DispSetLimit(unsigned char setIndex)
{
LCD_DispStr(0, 0, " Set Limit ");
sprintf(tab0, " L:%3d H:%3d ", heartRateL, heartRateH); //显示心率上下限
LCD_DispStr(0, 1, tab0); //显示心率
switch (setIndex)
{
case 1: LCD_SetCursor(6, 1, 1); break;
case 2: LCD_SetCursor(13, 1, 1); break;
default:;
}
}
/************************* 按键处理 *************************/
void KeyProcess()
{
if (KEY_SET == 0) //设置键按下
{
DelayMs(20);
if (KEY_SET == 0) //设置键按下
{
if (setFlag == 0)
{
setFlag = 1; //进入设置
setIndex = 1;
DispSetLimit(setIndex);
}
else
{
setIndex++; //切换设置位置
DispSetLimit(setIndex);
if (setIndex > 2)
{
setFlag = 0;
setIndex = 0;
LCD_WriteCommand(0x0C, 0); //关闭闪烁
}
}
}
while (KEY_SET == 0);
}
if (KEY_ADD == 0) //加键按下
{
DelayMs(200);
if (KEY_ADD == 0) //加键按下
{
if (setFlag == 0)
{
if (motorPWM < 10)
{
motorPWM++;
}
}
else
{
if (setIndex == 1)
{
heartRateL++;
if (heartRateL >= heartRateH)
{
heartRateL = 60;
}
}
else if (setIndex == 2)
{
heartRateH++;
if (heartRateH > 140)
{
heartRateH = heartRateL + 1;
}
}
DispSetLimit(setIndex);
}
}
}
if (KEY_SUB == 0) //减键按下
{
DelayMs(200);
if (KEY_SUB == 0) //减键按下
{
if (setFlag == 0)
{
if (motorPWM > 1)
{
motorPWM--;
}
}
else
{
if (setIndex == 1)
{
heartRateL--;
if (heartRateL < 60)
{
heartRateL = heartRateH - 1;
}
}
else if (setIndex == 2)
{
heartRateH--;
if (heartRateH <= heartRateL)
{
heartRateH = 140;
}
}
DispSetLimit(setIndex);
}
}
}
if (KEY_SWITCH == 0) //启停
{
DelayMs(20);
if (KEY_SWITCH == 0) //启停
{
startFlag = ~startFlag;
if (startFlag == 1)
{
LED_GREEN = ON;
LED_RED = OFF;
}
else
{
LED_GREEN = OFF;
LED_RED = ON;
}
}
while (KEY_SWITCH == 0);
}
}
/*************定时器初始化程序***************/
void Timer0_Init()
{
TMOD &= 0xF0;
TMOD |= 0x01; //定时器0工作方式1
TH0 = 0xB8; //(65536 - 0.02*11059200/12) / 256
TL0 = 0x00; //(65536 - 0.02*11059200/12) % 256 20ms
//PT0 = 1; //设置高优先级
ET0 = 1; //开定时器0中断
TR0 = 1; //允许定时器0定时
}
void Timer1_Init() //定时器1初始化
{
TMOD &= 0x0F;
TMOD |= 0x10;
TL1 = 0x00; //设置定时初始值
TH1 = 0xEE; //设置定时初始值 5ms
PT1 = 1; //设置高优先级
ET1 = 1;
TR1 = 1;
}
/***********外部中断0初始化程序****************/
void Ext0_1_Init() //外部中断0和1初始化程序
{
IT0 = 1; //外部中断0负跳变中断
IT1 = 1; //外部中断1负跳变中断
PX0 = 1; //设置高优先级
EX0 = 1; //允许外部中断0中断
EX1 = 1; //允许外部中断0中断
}
void Ext0_Interrupt() interrupt 0
{
if (timeCnt < 80) //当连续两次检测时间间隔小于80*5ms=400ms不处理
{
TR0 = 1; //开定时器
}
else
{
refreshFlag = 1;
}
}
/*************定时器0中断服务程序***************/
void Timer0_Interrupt() interrupt 1
{
TH0 = 0xEE; //(65536 - 0.005*11059200/12 + 200) / 256
TL0 = 0xC8; //(65536 - 0.005*11059200/12 + 200) % 256 5ms
timeCnt++; //每5ms一次计数
if (timeCnt > 250) //当超过25*50ms=1.5s没有检测到信号停止显示
{
datIndex = 0; //数据个数清零
timeCnt = 0; //50ms计数清零
updateFlag = 0; //显示关
TR0 = 0; //定时器关
}
}
void Ext1_Interrupt() interrupt 2
{
pulseCnt++;
}
void Timer1_Interrupt(void) interrupt 3
{
static unsigned int time5ms = 0;
static unsigned char IN1Count = 0;
TL1 = 0x00; //设置定时初始值
TH1 = 0xEE; //设置定时初始值 5ms
time5ms++;
if (time5ms > 200) //定时1秒
{
time5ms = 0;
dispFlag = 1; //更新数据标志置位
}
/************************* 电机PWM控制 *************************/
if (startFlag == 1) //跑步机启动情况下
{
IN1Count++;
if (IN1Count > realMotorPWM+15) //关闭时间段
{
MOTOR_INA = 1; //关闭
}
else if (IN1Count <= realMotorPWM+15) //占空比调节
{
MOTOR_INA = 0; //开启
}
if (IN1Count > 10+15)
{
IN1Count = 0; //一个周期结束
}
}
else
{
MOTOR_INA = 1;
}
}