|
這是我們暑假參加比賽的作品,含源碼,實(shí)物圖,原理圖。請(qǐng)大家多多指教,一起學(xué)習(xí) 。本作品設(shè)計(jì)了一種可以同時(shí)檢測(cè)心率和體溫,并可以實(shí)現(xiàn)計(jì)步功能的手表,該裝置包括單片機(jī)控制器、MLX90614紅外測(cè)溫模塊、MMA7455計(jì)步模塊、系統(tǒng)實(shí)時(shí)時(shí)鐘、Pulse Sensor心率模塊、OLED12864顯示模塊、nRF24L01無(wú)線通信模塊和計(jì)算機(jī)控制軟件、電源九部分。
利用MLX90614紅外測(cè)溫模塊及Pulse Sensor心率模塊采集到人的實(shí)時(shí)體溫和心率數(shù)據(jù),通過(guò)nRF24L01無(wú)線通信模塊將采集到的數(shù)據(jù)發(fā)送到單片機(jī)控制器,經(jīng)過(guò)STC89LE5A60S2微控制器進(jìn)行數(shù)據(jù)處理,再將數(shù)據(jù)傳到OLED12864顯示,并通過(guò)數(shù)據(jù)線串口發(fā)送數(shù)據(jù)到電腦,然后通過(guò)LabVIEW軟件對(duì)采集到的數(shù)據(jù)進(jìn)一步的處理和分析。
同時(shí)本作品還可以將計(jì)步模塊的數(shù)據(jù)通過(guò)STC89LE5A60S2單片機(jī)送到OLED12864顯示,實(shí)現(xiàn)計(jì)步功能。該作品可當(dāng)作一個(gè)便攜式家用醫(yī)療小系統(tǒng),實(shí)時(shí)監(jiān)測(cè)體溫和心率,并可實(shí)現(xiàn)戶外運(yùn)動(dòng)的計(jì)步功能,達(dá)到方便、快捷、可自由移動(dòng)的目的。
實(shí)物圖計(jì)步器功能:
手表端
下面是電路原理圖:
手表端原理圖
下面是整機(jī)圖:
耳聞模塊
心率儀
耳聞原理圖
多功能醫(yī)療健康手表設(shè)計(jì)的所有資料下載
(里面包含2個(gè)單片機(jī)源程序,分別實(shí)現(xiàn)了2個(gè)功能MLX90614程序-發(fā)送-耳溫和手表顯示):
程序.rar
(253.42 KB, 下載次數(shù): 240)
2017-2-28 19:12 上傳
點(diǎn)擊文件名下載附件
計(jì)步程序jibu.h文件:
- #include<reg51.h>
- #include <intrins.h>
- //#define uchar unsigned char
- //#define uint unsigned int
- void KeyScan1(void);
- sbit Key_jibu=P2^0;
- #define SET_TR2 AUXR |= 0x10
- #define CLR_TR2 AUXR &= ~0x10
- #define SET_ET2 IE2 |= 0x04
- #define CLR_ET2 IE2 &= ~0x04
- //nop指令個(gè)數(shù)定義
- #define nops() {_nop_();_nop_();_nop_();_nop_();_nop_();}
- bit start_flag=0;
- //端口定義,可修改
- sbit SDA1=P1^1; //IIC數(shù)據(jù)線定義 (可自行定義引腳)
- sbit SCL=P1^0; //IIC時(shí)鐘線定義 (可自行定義引腳)
- //內(nèi)部數(shù)據(jù)定義
- unsigned char IIC_ad_main; //器件從地址
- unsigned char IIC_ad_sub; //器件子地址
- unsigned char *IIC_buf; //發(fā)送接收數(shù)據(jù)緩沖區(qū)
- unsigned char IIC_num; //發(fā)送接收數(shù)據(jù)緩個(gè)數(shù)
- unsigned int step_num=0;
- unsigned char x1,y1,z1;
- int x,y,z;
- bit x_flag=0;
- //bit z_flag=0;
- #define ack 1 //主應(yīng)答
- #define no_ack 0 //從應(yīng)答
- /*延時(shí)子程序,實(shí)現(xiàn)按鍵消抖功能*/
- void delayms( )
- { int i=10,j=110;
- for(i=10;i>0;i--)
- for(j=110;j>0;j--);
- }
- void send232byte(unsigned char bytebuf)
- {
- SBUF=bytebuf;
- while(!TI);
- TI=0;
- }
- void IIC_start(void){
- SCL=0;
- SDA1=1;
- _nop_();
- SCL=1;
- nops();
- SDA1=0;
- nops();
- SCL=0;
- }
- //************************************************
- //送停止位SDA=0->1
- void IIC_stop(void){
- SCL=0;
- _nop_();
- SDA1=0;
- _nop_();
- SCL=1;
- nops();
- SDA1=1;
- nops();
- SCL=0;
- }
- //************************************************
- //主應(yīng)答(包括ack:SDA=0和no_ack:SDA=0)
- void IIC_ack_main(bit ack_main){
- SCL=0;
- if(ack_main)SDA1=0; //ack主應(yīng)答
- else SDA1=1; //no_ack無(wú)需應(yīng)答
- nops();
- SCL=1;
- nops();
- SCL=0;
- }
- //*************************************************
- //字節(jié)發(fā)送程序
- //發(fā)送c(可以是數(shù)據(jù)也可以是地址),送完后接收從應(yīng)答
- //不考慮從應(yīng)答
- void send_byte(unsigned char c)
- {
- unsigned char i;
- for(i=0;i<8;i++)
- {
- SCL=0;
- if((c<<i) & 0x80)SDA1=1; //判斷發(fā)送位
- else SDA1=0;
- _nop_();
- SCL=1;
- nops();
- SCL=0;
-
- nops();
- SCL=0;
- }
- nops();
- SDA1=1; //發(fā)送完8bit,釋放總線準(zhǔn)備接受應(yīng)答位
- _nop_();
- SCL=1;
- nops(); //sda上數(shù)據(jù)即是從應(yīng)答位
- SCL=0; //不考慮從應(yīng)答但要控制好時(shí)序
- }
- //**************************************************
- //字節(jié)接收程序
- //接受器件傳來(lái)的數(shù)據(jù),此程序應(yīng)配合主應(yīng)答函數(shù)IIC-ack main()使用
- //return: uchar型1字節(jié)
- unsigned char read_byte(void){
- unsigned char i;
- unsigned char c;
- c=0;
- SCL=0;
- _nop_();
- SDA1=1; //置數(shù)據(jù)線為輸入方式
- for(i=0;i<8;i++){
- _nop_();
- SCL=0; //置時(shí)鐘線為低,準(zhǔn)備接收數(shù)據(jù)位
- nops();
- SCL=1; //置時(shí)鐘線為高,使數(shù)據(jù)線上數(shù)據(jù)有效
- _nop_();
- c<<=1;
- if(SDA1)c+=1; //讀數(shù)據(jù)位,將接收的數(shù)據(jù)存c
- }
- SCL=0;
- return c;
- }
- //***************************************************
- //向無(wú)子地址器件發(fā)送單字節(jié)數(shù)據(jù)
- void send_to_byte(unsigned char ad_main,unsigned char c){
- IIC_start();
- send_byte(ad_main); //發(fā)送器件地址
- send_byte(c); //發(fā)送數(shù)據(jù)c
- IIC_stop();
- }
- //***************************************************
- //向有子地址器件發(fā)送多字節(jié)數(shù)據(jù)
- void send_to_nbyte(unsigned char ad_main,unsigned char ad_sub,unsigned char *buf,unsigned char num)
- { unsigned char i;
- IIC_start();
- send_byte(ad_main); //發(fā)送器件地址
- send_byte(ad_sub); //發(fā)送器件子地址
- for(i=0;i<num;i++){
- send_byte(*buf); //發(fā)送數(shù)據(jù)buf
- buf++;
- }
- IIC_stop();
- }
- //***************************************************
- //從無(wú)子地址器件讀單字節(jié)數(shù)據(jù)
- //function:器件地址,所讀數(shù)據(jù)存在接收緩沖區(qū)當(dāng)前字節(jié)
- void read_from_byte(unsigned char ad_main,unsigned char *buf){
- IIC_start();
- send_byte(ad_main); //發(fā)送器件
- *buf=read_byte();
- IIC_ack_main(no_ack); //無(wú)需應(yīng)答<no_ack=0>
- IIC_stop();
- }
- //***************************************************
- //從有子地址器件讀多個(gè)字節(jié)數(shù)據(jù)
- //function:
- void read_from_nbyte(unsigned char ad_main,unsigned char ad_sub,unsigned char *buf,unsigned char num){
- unsigned char i;
- IIC_start();
- send_byte(ad_main);
- send_byte(ad_sub);
- for(i=0;i<num-1;i++){
- *buf=read_byte();
- IIC_ack_main(ack); //,主應(yīng)答<ack=1>
- buf++;
- }
- *buf=read_byte;
- buf++; //本次指針調(diào)整無(wú)意義,目的是操作后buf指向下一地址
- IIC_ack_main(no_ack); //無(wú)需應(yīng)答<no_ack=0>
- IIC_stop();
- }
- unsigned char MMA7455_readbyte(unsigned char address)
- {
- unsigned char ret = 100;
- IIC_start(); //啟動(dòng)
- send_byte(0x3A); //寫(xiě)入設(shè)備ID及寫(xiě)信號(hào)
- send_byte(address); //X地址
- IIC_start(); //重新發(fā)送開(kāi)始
- send_byte(0x3B); //寫(xiě)入設(shè)備ID及讀信號(hào)
- ret = read_byte(); //讀取一字節(jié)
- IIC_stop();
- return ret;
- }
- //寫(xiě)入
- void MMA7455_writebyte(unsigned char address, unsigned char thedata)
- {
- IIC_start(); //啟動(dòng)
- send_byte(0x3A); //寫(xiě)入設(shè)備ID及寫(xiě)信號(hào)
- send_byte(address); //X地址
- send_byte(thedata); //寫(xiě)入設(shè)備ID及讀信號(hào)
- IIC_stop();
- }
- //初始化
- //初始化為指定模式
- void MMA7455_init()
- { //2g輸出 測(cè)量模式
- MMA7455_writebyte(0x16, 0x05);
- //根據(jù)實(shí)際環(huán)境修改校驗(yàn)值
- /*MMA7455_writebyte(0x10,0x10);//校正X值
- MMA7455_writebyte(0x12,0x30);//校正Y值
- MMA7455_writebyte(0x14,0x00);//校正Z值 */
- }
- /************************顯示程序**********************************/
- void display()
- {
- if (step_num/10000>0) //萬(wàn)
- OLED_ShowNum(0+8*5,4,step_num/10000,1,8*16);
- else
- OLED_ShowNum(0+8*5,4,0,1,8*16);
- if (step_num/1000>0) //千
- OLED_ShowNum(0+8*6,4,step_num%10000/1000,1,8*16);
- else
- OLED_ShowNum(0+8*6,4,0,1,8*16);
- if (step_num/100>0) //百
- OLED_ShowNum(0+8*7,4,step_num%1000/100,1,8*16);
- else
- OLED_ShowNum(0+8*7,4,0,1,8*16);
- if (step_num/10>0) //十
- OLED_ShowNum(0+8*8,4,step_num%100/10,1,8*16);
- else
- OLED_ShowNum(0+8*8,4,0,1,8*16);
- //個(gè)
- OLED_ShowNum(0+8*9,4,step_num%10,1,8*16);
- }
- /************讀取重力信息**************/
- void Dat_dispose()
- {
- if(start_flag)
- { x1=MMA7455_readbyte(0x06);
- y1=MMA7455_readbyte(0x07);
- z1=MMA7455_readbyte(0x08);
- }
- x=x1;
- y=y1;
- z=z1;
- if((x&0x80)==0x00)
- { x=(int)((x*196)/127); //轉(zhuǎn)變成加速度值
- }
- else { x=255-x;
- x=(int)((x*196)/127);//轉(zhuǎn)變成加速度值
- x=(-1)*x;
- }
- if((y&0x80)==0x00)
- { y=(int)((y*196)/127); //轉(zhuǎn)變成加速度值
- }
- else { y=255-y;
- y=(int)((y*196)/127);//轉(zhuǎn)變成加速度值
- y=(-1)*y;
- }
- if((z&0x80)==0x00)
- { z=(int)(((z-10)*196)/127); //轉(zhuǎn)變成加速度值
- }
- else { z=255-z;
- z=(int)(((z+12)*196)/127);//轉(zhuǎn)變成加速度值
- z=(-1)*z;
- }
- if(start_flag)
- {
- if(y>30&&x_flag==0&&z>70&&z<100)
- {x_flag=1;
- step_num++;}
- else if(y<0)
- { x_flag=0;}
- }
- else x_flag=0;
- }
復(fù)制代碼
主程序:
- #include "REG51.h"
- #include "OLED.h"
- //#include "bmp.h"
- #include "DS1302.h"
- #include "NRF24L01.h"
- #include "key_deal.h"
- #include "MMA7455.h"
- #define false 0
- #define true 1
- #define FOSC 11059200L //系統(tǒng)時(shí)鐘
- #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 ADC_init(unsigned char channel);
- void InitTimer0(void);
- unsigned char ReturnPulse(void);
- unsigned int analogRead(unsigned char channel);
- unsigned char PulsePin = 5; // Pulse Sensor purple wire connected to analog pin 0(P1.0為傳感器輸入口)
- int fadeRate = 0; // used to fade LED on with PWM on fadePin
- unsigned char pp1;
- unsigned char pp0;
- unsigned char pp2;
- unsigned char pp3;
- unsigned int PL1=0;
- void UART_init(void);
- void Send(void);
- // these variables are volatile because they are used during the interrupt service routine!
- volatile unsigned int BPM; // used to hold the pulse rate
- volatile unsigned int Signal; // holds the incoming raw data
- volatile unsigned int IBI = 600; // holds the time between beats, must be seeded!
- volatile bit Pulse = false; // true when pulse wave is high, false when it's low
- volatile bit QS = false; // becomes true when Arduoino finds a beat.
- volatile int rate[10]; // array to hold last ten IBI values
- volatile unsigned long sampleCounter = 0; // used to determine pulse timing
- volatile unsigned long lastBeatTime = 0; // used to find IBI
- volatile int Peak =512; // used to find peak in pulse wave, seeded
- volatile int Trough = 512; // used to find trough in pulse wave, seeded
- volatile int thresh = 512; // used to find instant moment of heart beat, seeded
- volatile int amp = 100; // used to hold amplitude of pulse waveform, seeded
- volatile bit firstBeat = true; // used to seed rate array so we startup with reasonable BPM
- volatile bit secondBeat = false; // used to seed rate array so we startup with reasonable BPM
- static unsigned char order=0;
- unsigned char DisBuff[4]={0};
- void Int0_Init(void);
- //void Int1_Init(void);
- void Display_Init(void);
- static unsigned char data temp[10];
- bit data T0_FLAG=0;
- bit data key_flag;
- bit data key_flag1;
- unsigned int mode1 = 0;
- void delay(unsigned int n)
- {
- unsigned int i,j;
- for(i=0;i<n;i++)
- for(j=0;j<100;j++);
- }
- int main(void)
- { //u8 t;
- //delay_init(); //延時(shí)函數(shù)初始化
- // NVIC_Configuration(); //設(shè)置NVIC中斷分組2:2位搶占優(yōu)先級(jí),2位響應(yīng)優(yōu)先級(jí) LED_Init(); //LED端口初始化
- OLED_Init(); //初始化OLED
- Ds1302_Init();
- InitTimer0();
- Display_Init();
- ADC_init(PulsePin);
- //InitTimer1();
- Int0_Init();
- init_NRF24L01();
- SetRX_Mode();
- UART_init();
- //Int1_Init();
- while(1)
- {
- delay_ms(10);
-
- Ds1302_Read_Time();
- /*判斷按鍵2是否啟動(dòng)測(cè)試*/
- if(0 == Key_Down)
- {
- delay_ms(100);
- if(0 == Key_Down)
- {
- mode1=mode1+1;
- }
- }
-
- /* 測(cè)心率 */
- if(mode1==1)
- {
- OLED_ShowCHinese(0,0,0); //心
- OLED_ShowCHinese(16,0,1); //率
- OLED_ShowString(32,0,":");
- OLED_ShowCHinese(0,2,2); //體
- OLED_ShowCHinese(16,2,3); //溫
- OLED_ShowString(32,2,":");
-
- if (QS == true&&PL1>1000)
- { // Quantified Self flag is true when arduino finds a heartbeat
-
- QS = false;
- delay(100);
- OLED_ShowNum(0+8*5,0,DisBuff[2],1,8*16); //百位顯示
- OLED_ShowNum(0+8*6,0,DisBuff[1],1,8*16); //個(gè)十位顯示
- OLED_ShowNum(0+8*7,0,DisBuff[0],1,8*16);
- OLED_ShowString(64,0,"bpm");
-
- ///判斷是否異常
- if((DisBuff[1]*10+DisBuff[0])<100&&(DisBuff[1]*10+DisBuff[0])>=60&&DisBuff[2]!=1)
- {
- OLED_ShowCHinese(0+8*12,0,24); //正常
- OLED_ShowCHinese(0+8*14,0,26);
- }
- else if(DisBuff[1]==0&&DisBuff[2]==0&&DisBuff[0]==0)
- {
- OLED_ShowCHinese(0+8*12,0,29); //空
- OLED_ShowCHinese(0+8*14,0,29);
- }
- else
- {
- OLED_ShowCHinese(0+8*12,0,25); //異常
- OLED_ShowCHinese(0+8*14,0,26);
- }
-
- }
- delay(138); // take a break 19.6ms
- /*溫度測(cè)量 */
- if(nRF24L01_RxPacket(temp)&&PL1>1000) //接收溫度
- {
- SetTX_Mode();
- delay(100);
- OLED_ShowString(56,2,".");
- OLED_ShowCHinese(72,2,19);
- OLED_ShowNum(0+8*5,2,temp[3]%100/10,1,8*16); //temp[3]存放十位
- OLED_ShowNum(0+8*6,2,temp[3]%10,1,8*16); //個(gè)位
- OLED_ShowNum(0+8*8,2,temp[2]%100/10,1,8*16); //temp[2]存放小數(shù)位
- if(temp[3]>=36&&temp[3]<38)
- {
- OLED_ShowCHinese(0+8*12,2,24);
- OLED_ShowCHinese(0+8*14,2,26);
- }
- else
- {
- OLED_ShowCHinese(0+8*12,2,25);
- OLED_ShowCHinese(0+8*14,2,26);
- }
- temp[4] = ReturnPulse();
- nRF24L01_TxPacket(temp);
- SetRX_Mode();
-
- }
- if(PL1>1000)
- {
- PL1=0;
- Send();
- }
- }
- if(mode1>=3)
- {
- mode1=0;
- OLED_ShowCHinese(0,0,29); //心
- OLED_ShowCHinese(16,0,29); //率
- OLED_ShowCHinese(32,0,29);
- OLED_ShowCHinese(64,0,29);
- OLED_ShowCHinese(72,0,29);
- OLED_ShowCHinese(48,0,29);
- OLED_ShowCHinese(56,0,29);
- OLED_ShowCHinese(40,0,29);
- OLED_ShowCHinese(0+8*12,0,29);
- OLED_ShowCHinese(0+8*14,0,29);
-
-
- OLED_ShowCHinese(0,2,29); //
- OLED_ShowCHinese(16,2,29); //
- OLED_ShowCHinese(32,2,29);
- OLED_ShowCHinese(72,2,29);
- OLED_ShowCHinese(64,2,29);
- OLED_ShowCHinese(48,2,29);
- OLED_ShowCHinese(56,2,29);
- OLED_ShowCHinese(40,2,29);
- OLED_ShowCHinese(0+8*12,2,29);
- OLED_ShowCHinese(0+8*14,2,29);
-
- }
-
- OLED_ShowNum(0+8*10,4,time_buf1[6]/10,1,8*16);
- OLED_ShowNum(0+8*11,4,time_buf1[6]%10,1,8*16);
- if(0 == time_buf1[6])
- {
- OLED_ShowNum(0+8*7,4,time_buf1[5]/10,1,8*16);
- OLED_ShowNum(0+8*8,4,time_buf1[5]%10,1,8*16);
- if(0 == time_buf1[5])
- {
- EA = 0; //////
- OLED_ShowNum(0+8*4,4,time_buf1[4]/10,1,8*16);
- OLED_ShowNum(0+8*5,4,time_buf1[4]%10,1,8*16);
- if(0 == time_buf1[4])
- {
- OLED_ShowNum(0+8*9,6,time_buf1[3]/10,1,8*16);
- OLED_ShowNum(0+8*10,6,time_buf1[3]%10,1,8*16);
- OLED_ShowCHinese(8*12,6,WEEK[time_buf1[7]]);
- if(0 == time_buf1[3])
- {
- OLED_ShowNum(0+8*6,6,time_buf1[2]/10,1,8*16);
- OLED_ShowNum(0+8*7,6,time_buf1[2]%10,1,8*16);
- if(0 == time_buf1[2])
- {
- OLED_ShowNum(0+8*3,6,time_buf1[1]/10,1,8*16);
- OLED_ShowNum(0+8*4,6,time_buf1[1]%10,1,8*16);
- }
- }
- }
-
- InitTimer0(); //每隔一小時(shí),重新初始化一次
- }
-
- }
- /* 時(shí)間調(diào)整/計(jì)步按鍵判斷 */
- //按鍵判斷
- if(key_flag == 1) //進(jìn)入按鍵掃描
- {
- KeyScan();
- key_flag = 0;
- mode1=0;
- }
-
-
- }
- }
-
- …………余下代碼請(qǐng)下載附件……
復(fù)制代碼 |
評(píng)分
-
查看全部評(píng)分
|