当前位置 博文首页 > xuanzhigu的博客:LabVIEW大作业
一、设计简介
设计目标:利用proteus实验仿真软件设计一个基于stc12c5a单片机的心率采集系统,并在PC机上的Windows环境下利用LabVIEW软件实现心率数据的处理与显示。
实现功能:
1、利用pulse sensor心率脉冲传感器实现对血管脉动进行采集;
2、利单片机可以通过串口通讯向PC机传输数据;
3、在PC机上的Windows环境下利用LabVIEW软件实现对心率的监视;
4、单片机实时显示心率;
4、进行心率分析,对异常心率有报警提示功能;
5、心率数据进行保存与发送;
实验设备:
1、PC机
2、安装LabVIEW软件
3、安装Keil uVision4软件
4、51单片机
5、pulse sensor心率脉冲传感器
二、总体设计
本设计主要利用pulse sensor心率脉冲传感器通过血管搏动时造成透光率变化影响感光器件阻值进而影响输出电压来反应心率变化。
通过单片机对传感器传输的模拟量进行数模转换,采取定时器查询方式检测转换计算心率,通过串口通讯向LabVIEW传输数据,labview对数据进行解析运算实现对心率的实时显示、对异常心率有报警提示、心率数据进行保存与发送等功能。
三、硬件设计
硬件选择:
设备电路板:51开发板;
芯片选择 :STC12C5A60S2;
单片机显示:LCD1602;
心率采集传感器:pulse sensor心率脉冲传感器;
四、软件设计
软件部分分为单片机程序编程与LabVIEW程序编程。
LabVIEW上位机编程部分:
五、程序
LabVIEW程序:以后发
单片机程序:
main.c
//ADC PIN:P1.0
//SYSTEM CLOCK:11.0592MHz
//Baudrate:115200
//UART:P3.0/rxd P3.1/txd
#include <STC12C5A60S2.h>
#include "stdio.h"
#include <LCD1602.h>
#define false 0
#define true 1
#define FOSC 11059200L //系统时钟
#define BAUD 115200 //波特率
#define T0MS (65536-FOSC/12/500)//500HZ in 12T MODE
#define ADC_POWER 0x80 //ADC POWER CONTROL BIT
#define ADC_FLAG 0x10 //ADC COMPLETE FLAG
#define ADC_START 0x08; //ADC START CONTROL BIT
#define ADC_SPEEDLL 0x00 //540 CLOCKS
#define ADC_SPEEDL 0x20 //360 CLOCKS
#define ADC_SPEEDH 0x40 //180 CLOCKS
#define ADC_SPEEDHH 0x60 //90 CLOCKS
#define ADC_MASK 0x01
void UART_init(void);
void ADC_init(unsigned char channel);
void T0_init(void);
void sendDataToProcessing(char symbol, int dat);
void UART_send(char dat);
unsigned char PulsePin = 0; // P1.0为传感器输入口)
int fadeRate = 0;
volatile unsigned int BPM;
volatile unsigned int Signal;
volatile unsigned int IBI = 600;
volatile bit Pulse = false;
volatile bit QS = false;
volatile int rate[10];
volatile unsigned long sampleCounter = 0; // 用于确定脉冲时序
volatile unsigned long lastBeatTime = 0;
volatile int Peak =512;
volatile int Trough = 512;
volatile int thresh = 512;
volatile int amp = 100;
volatile bit firstBeat = true;
volatile bit secondBeat = false;
static unsigned char order=0;
unsigned char code ucForum0[]="Heart rate test";
unsigned char code ucForum1[]=" BPM: ";
unsigned char DisBuff[4]={0};
void sys_init()
{
UART_init();
ADC_init(PulsePin);
T0_init();
LCD1602_Init(); //液晶初始化
}
void main(void)
{
sys_init();
LCD1602_DisplayString(ucForum0); //显示的内容
LCD1602_MoveToPosition(1,0); //显示位置移动到指定位置
LCD1602_DisplayString(ucForum1); //显示的内容
while(1)
{
sendDataToProcessing('S', Signal); // 发送数据
if (QS == true)
{
fadeRate = 255;
sendDataToProcessing('B',BPM);
sendDataToProcessing('Q',IBI);
QS = false;
LCD1602_MoveToPosition(1,9);
LCD1602_DisplayString(DisBuff);
}
delay(138); // take a break 19.6ms
}
}
void sendDataToProcessing(char symbol, int dat )
{
putchar(symbol);
printf("%d\n",dat); //串口发送
}
void UART_init(void)
{
PCON &= 0x7f; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
BRT = 0xFD; //独立波特率产生器初值
AUXR |= 0x04; //时钟设置为1T模式
AUXR |= 0x01; //选择独立波特率产生器
AUXR |= 0x10; //启动波特率产生
}
char putchar(unsigned char dat)
{
TI=0;
SBUF=dat;
while(!TI);
TI=0;
return SBUF;
}
void T0_init(void)
{
TMOD |= 0x01; // 初始化定时器0,2mS一个中断。
TL0=T0MS;
TH0=T0MS>>8;
TR0=1;
ET0=1;
EA=1;
}
void ADC_init(unsigned char channel)
{
P1ASF=ADC_MASK<<channel; //启用PlusePin作为ADC输入
ADC_RES=0;
ADC_RESL=0;
AUXR1 |= 0x04; //调整ADC结果的格式
ADC_CONTR=channel|ADC_POWER|ADC_SPEEDLL|ADC_START; //打开ADC电源并开始转换
}
unsigned int analogRead(unsigned char channel)
{
unsigned int result;
ADC_CONTR &=!ADC_FLAG; //clear ADC FLAG
result=ADC_RES;
result=result<<8;
result+=ADC_RESL;
ADC_CONTR|=channel|ADC_POWER|ADC_SPEEDLL|ADC_START;
return result;
}
// Timer 0中断子程序,每2MS中断一次,读取AD值,计算心率值
void Timer0_rountine(void) interrupt 1
{
int N;
unsigned char i;
// 保持最后10个IBI值的总和
unsigned int runningTotal = 0;
EA=0;
TL0=T0MS;
TH0=T0MS>>8; //重新加载16位计时器0
Signal = analogRead(PulsePin);
sampleCounter += 2;
N = sampleCounter - lastBeatTime;
if(Signal < thresh && N > (IBI/5)*3)
{ // 通过等待最后一个IBI的3/5来避免二脉噪声 IBI
if (Signal < Trough)
{ //T是低谷
Trough = Signal; //跟踪脉搏波的最低点
}
}
if(Signal > thresh && Signal > Peak)
{ //避免噪音
Peak = Signal; // P是峰值
} // 跟踪脉搏波的最高点
// 每次有脉冲时,信号的值就会飙升
if (N > 250)
{ // avoid high frequency noise
if ( (Signal > thresh) && (Pulse == false) && (N > (IBI/5)*3) )
{
Pulse = true; // 当我们认为有脉冲时设置脉冲标志
IBI = sampleCounter - lastBeatTime; // 测量拍之间的时间(毫秒