标题:
STM32血氧程序无法编译 求帮助
[打印本页]
作者:
chenzuoxiang_
时间:
2021-12-31 11:22
标题:
STM32血氧程序无法编译 求帮助
STM32血氧程序
#include "stm32f103c8t6.h"
//#include "stm32f1xx_hal_gpio.h"
#include "mbed.h"
#include "algorithm.h"
#include "MAX30102.h"
//#include "lcd_5110.h"
#include "ascii5x8.h" //5x8ASCII字符集
#include "charcode.h" //12x16(14)汉字子集
#include "asciicode.h" //5x8(8)ASCII子集
//#include "sys.h"
/************ 定义LCD相关的管脚功能 ***********/
#define LCD_RST_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET);}while(0) //复位脚① PB11
#define LCD_RST_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET);}while(0)
#define LCD_CE_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET);}while(0) //片选脚②PB10
#define LCD_CE_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);}while(0)
#define LCD_DC_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);}while(0) //数据/命令选择脚③PB0
#define LCD_DC_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);}while(0)
#define LCD_DIN_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);}while(0) //数据输入④PB1
#define LCD_DIN_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);}while(0)
#define LCD_CLK_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);}while(0) //时钟信号脚⑤PB5
#define LCD_CLK_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);}while(0)
/************** 结束管脚定义 *****************/
#define CLOCK 72/8 //时钟=72M
#define MAX_BRIGHTNESS 255
uint32_t aun_ir_buffer[500]; //红外LED传感器数据
int32_t n_ir_buffer_length; //数据长度
uint32_t aun_red_buffer[500];//红色LED传感器数据
int32_t n_sp02; //SPO2血氧值
int8_t ch_spo2_valid; //血氧值有效标志
int32_t n_heart_rate; //心率值
int8_t ch_hr_valid; //心率值有效标志
uint8_t uch_dummy;
const uint8_t level[]={0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF};//波形
//const uint8_t level[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//曲线
uint8_t disp=1; //动态显示列
Serial pc(SERIAL_TX, SERIAL_RX);//初始化串行端口, TX-PA2, RX-PA3
PwmOut pwmled(PB_3); //初始化连接到LED的PWM输出PB3(亮度变化)
DigitalIn INT(PB_7); //PB7连接MAX30102的INT输出引脚
DigitalOut led(PC_13); //PC13连接板载用户LED
void LCD_Config(void); //LCD配置引脚
void LCD_init(void); //LCD初始化
void LCD_write_byte(uint8_t dat,uint8_t dc);//LCD写字节
void LCD_set_XY(uint8_t X,uint8_t Y);//LCD设置坐标
void LCD_clear(void); //LCD清屏
void LCD_write_ASCII(uint8_t X,uint8_t Y,uint8_t *stru);//LCD显示5x7字符串
void LCD_write_ASC_SIN(uint8_t X,uint8_t Y,uint8_t cid);//LCD显示5x7字符
void LCD_write_ASC7x12(uint8_t X,uint8_t Y,uint8_t cid);//LCD显示7x12字符
void LCD_write_char(uint8_t x,uint8_t y,uint8_t cid); //LCD显示12x14字符
void LCD_write_value(uint8_t X,uint8_t Y,uint8_t L,uint8_t D,uint16_t val);//LCD显示变量
void LCD_write_string(uint8_t x,uint8_t y,uint8_t *stru);//LCD显示12x14字符串
void display_main(void); //主屏幕显示
void display_erro(void); //信号错误
void display_wait(void); //等待信号
void display_ir(uint16_t ir);//动态显示曲线
/*------------------------------------------------------------
us延时函数
------------------------------------------------------------*/
void delay_us(uint16_t us)
{
uint8_t n;
while(us--)for(n=0;n<CLOCK;n++);
}
/*------------------------------------------------------------
ms延时函数
------------------------------------------------------------*/
void delay_ms(uint16_t ms)
{
while(ms--)delay_us(1000);
}
// 当您按重置时,设置程序运行一次。
int main() {
uint32_t un_min, un_max, un_prev_data;//用于计算反映心跳的车载LED亮度的变量
int i;
int32_t n_brightness;
float f_temp;
uint8_t flag = 0;
maxim_max30102_reset(); //重置MAX30102
//初始化串行口波特率
pc.baud(115200);
pc.format(8,SerialBase::None,1);
wait(1);
//初始化LCD5110
LCD_init();
display_main();
//读取和清除状态寄存器
maxim_max30102_read_reg(0,&uch_dummy);
maxim_max30102_init(); //初始化MAX30102
n_brightness=0;
un_min=0x3FFFF;
un_max=0;
n_ir_buffer_length=500; //缓冲区长度100存储以100sps运行的5秒样本
//读取前500个样本,确定信号范围
for(i=0;i<n_ir_buffer_length;i++)
{
while(INT.read()==1);//等待直到中断pin生效
maxim_max30102_read_fifo((aun_red_buffer+i),(aun_ir_buffer+i));//从MAX30102的FIFO读数据
if(un_min>aun_red_buffer[i])
un_min=aun_red_buffer[i];//更新信号最小值
if(un_max<aun_red_buffer[i])
un_max=aun_red_buffer[i];//更新信号最大值
pc.printf("red=");
pc.printf("%i", aun_red_buffer[i]);
pc.printf(", ir=");
pc.printf("%i\n\r", aun_ir_buffer[i]);
}
un_prev_data=aun_red_buffer[i];
//计算前500个样本(前5秒样本)后的心率和血氧数值。
maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
//从MAX31022连续取样。每1秒计算一次心率和血氧饱和度。
while(1)
{
i=0;
un_min=0x3FFFF;
un_max=0;
//将前100组样本转储到内存中,并将最后400组样本移到顶部
for(i=100;i<500;i++)
{
aun_red_buffer[i-100]=aun_red_buffer[i];
aun_ir_buffer[i-100]=aun_ir_buffer[i];
//更新信号最小值和最大值
if(un_min>aun_red_buffer[i])
un_min=aun_red_buffer[i];
if(un_max<aun_red_buffer[i])
un_max=aun_red_buffer[i];
}
//在计算心率前取100组样本。
for(i=400;i<500;i++)
{
un_prev_data=aun_red_buffer[i-1];
while(INT.read()==1); //等待传感器信号
maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
if(aun_red_buffer[i]>un_prev_data) //只是根据相邻两个AD数据的偏差来确定LED的亮度
{
f_temp=aun_red_buffer[i]-un_prev_data;
f_temp/=(un_max-un_min);
f_temp*=MAX_BRIGHTNESS;
n_brightness-=(int)f_temp;
if(n_brightness<0)
n_brightness=0;
}
else
{
f_temp=un_prev_data-aun_red_buffer[i];
f_temp/=(un_max-un_min);
f_temp*=MAX_BRIGHTNESS;
n_brightness+=(int)f_temp;
if(n_brightness>MAX_BRIGHTNESS)
n_brightness=MAX_BRIGHTNESS;
}
if(flag==0) //两个循环显示一次
{
if(n_heart_rate>180)//脉搏过速
display_erro();
else
{
if(n_heart_rate<20)
display_wait();
else
display_ir((float)n_brightness/5);
}
flag++;
}
else
flag = 0;
pwmled.write(1-(float)n_brightness/256);//PWM控制LED亮度
if(n_brightness<120)
led=1;
else
led=0;
}
maxim_heart_rate_and_oxygen_saturation(aun_ir_buffer, n_ir_buffer_length, aun_red_buffer, &n_sp02, &ch_spo2_valid, &n_heart_rate, &ch_hr_valid);
pc.printf("HR=%i, ", n_heart_rate);
pc.printf("SpO2=%i",n_sp02);
LCD_write_value(24,5,3,0,n_sp02);
LCD_write_value(67,5,3,0,n_heart_rate);
}
}
/*********************************************
* 函数名称:LCD_Config
* 函数功能:配置LCD引脚
* 入口参数:无
* 出口参数:无
*********************************************/
void LCD_Config(void)
{
GPIO_InitTypeDef GPIO_InitTypeDef; //定义结构体
GPIO_InitTypeDef.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11; //配置LCD引脚
GPIO_InitTypeDef.Mode = GPIO_MODE_OUTPUT_PP; //推挽输出
GPIO_InitTypeDef.Speed = GPIO_SPEED_FREQ_HIGH; //速度
HAL_GPIO_Init(GPIOB, &GPIO_InitTypeDef); //初始化GPIO
}
/*********************************************
* 函数名称:LCD_init
* 函数功能:5110初始化
* 入口参数:无
* 出口参数:无
* 备注:接通电源后需要一个RES低电平脉冲复位,当VDD变为高电平之后
* 最多100ms,RST输入低电平(<0.3VDD)
*********************************************/
void LCD_init(void)
{
LCD_Config(); //配置LCD连线
LCD_RST_RESET; //LCD_RST = 0 复位LCD5110
delay_us(2);
LCD_RST_SET; //LCD_RST = 1;
LCD_CE_RESET; //LCD_CE = 0; 关闭LCD
delay_us(2);
LCD_CE_SET; //LCD_CE = 1; 关闭LCD
LCD_write_byte(0x21,0); //使用扩展LCD令设置LCD模式
LCD_write_byte(0xc8,0); //设置液晶偏置电压
LCD_write_byte(0x06,0); //温度校正(温度系数2)
LCD_write_byte(0x13,0); //1:48
LCD_write_byte(0x20,0); //使用基本命令,V=0,水平寻址
LCD_write_byte(0x0c,0); //设定显示模式,正常显示
LCD_clear(); //清屏
LCD_CE_SET; //LCD_CE = 1; //关闭LCD
}
/*********************************************
* 函数名称:LCD_write_byte
* 函数功能:模拟SPI接口时序写数据/命令LCD
* 入口参数:data :写入的数据;
* dc :写数据1/命令0选择
* 出口参数:无
* 备注:管脚D/C(LCD_DC)用于选择写的是命令(D/C=0)还是数据(D/C=1)
*********************************************/
void LCD_write_byte(uint8_t dat,uint8_t dc)
{
uint8_t i;
LCD_CLK_RESET; //先拉低时钟CLK
LCD_CE_RESET; //LCD_CE = 0; 选择5110
if (dc == 1)
{
LCD_DC_SET; //LCD_DC = dc; dc=0数据,dc=1命令
}
else {
LCD_DC_RESET;
}
for (i=0; i<8; i++) //发送8位
{
if (dat & 0x80)
{
LCD_DIN_SET; //LCD_DIN = 1;
}
else {
LCD_DIN_RESET; //LCD_DIN = 0;
}
LCD_CLK_SET; //LCD_CLK = 1;
delay_us(1);
dat = dat << 1; //移位,准备发送下一位
LCD_CLK_RESET; //LCD_CLK = 0; //发送同步时钟
}
LCD_CE_SET; //LCD_CE = 1; //关闭5110
}
/*********************************************
* 函数名称:LCD_set_XY
* 函数功能:设置LCD坐标函数
* 入口参数:X :0-83;
* Y :0-5
* 出口参数:无
* 备注:
*********************************************/
void LCD_set_XY(uint8_t X,uint8_t Y)
{
LCD_write_byte(0x40 | Y,0); //column?
LCD_write_byte(0x80 | X,0); //row?
}
/*********************************************
* 函数名称:LCD_clear
* 函数功能:5110清屏(用空白写满屏幕)
* 入口参数:无
* 出口参数:无
* 备注:
*********************************************/
void LCD_clear(void)
{
uint8_t i,j;
LCD_set_XY(0,0); //定位左上角
for (i=0; i<6; i++)
{
for (j=0; j<84; j++)
{
LCD_write_byte(0x00,1);
}
}
}
/*********************************************
* 函数名称:LCD_write_ASCII
* 函数功能:显示字符串5*7(8)
* 入口参数:x,y,cid :显示ASCII字符
* 出口参数:无 编号(行号)32~127
* 备注:ASCII码表的数组ASC_5[95][8]来寻址
*********************************************/
void LCD_write_ASCII(uint8_t X,uint8_t Y,uint8_t *stru)
{
uint8_t i;
LCD_set_XY(X,Y); //定位(左上角)
while (1)
{
for ( i=0; i<5; i++) //输出一个5*7字符
{
LCD_write_byte(ASC_5[*stru-32][i],1);
}
stru++;
if(*stru == '\0') break; //在每个字符串的最后,会有一个'\0'
LCD_write_byte(0x00,1); //插入空列
}
}
/*********************************************
* 函数名称:LCD_write_ASC_SIN
* 函数功能:显示单个字符5*7(8)
* 入口参数:x,y,cid :显示ASCII字符
* 出口参数:无 编号(行号)32~127
* 备注:ASCII码表的数组ASC_5[95][8]来寻址
*********************************************/
void LCD_write_ASC_SIN(uint8_t X,uint8_t Y,uint8_t cid)
{
uint8_t i;
LCD_set_XY(X,Y); //定位(左上角)
for ( i=0; i<5; i++) //输出一个5*7字符
{
LCD_write_byte(ASC_5[cid-32][i],1);
}
}
/*********************************************
* 函数名称:LCD_write_ASC7x12
* 函数功能:显示自定义字符7*12(16)
* 入口参数:x,y,cid :显示的字符 0 1 2 3 4 5 6 7 8 9 = m s
* 出口参数:无 编号(行号)0,1,2,3,4,5,6,7,8,9,10,11,12
* 备注:ASCII码表的数组ASC_7[13][14]来寻址
*********************************************/
void LCD_write_ASC7x12(uint8_t X,uint8_t Y,uint8_t cid)
{
uint8_t i;
LCD_set_XY(X,Y); //定位{左上角)
for (i=0; i<7; i++) //显示字符的上半部分(7列)
{
LCD_write_byte(ASC_7[cid][i],1);
}
LCD_set_XY(X,Y+1); //显示字符的下半部分
for (i=7; i<14; i++)
{
LCD_write_byte(ASC_7[cid][i],1);
}
}
/*********************************************
* 函数名称:LCD_write_CHAR
* 函数功能:显示自定义字符12*14(16)
* 入口参数:x,y,cid :显示的字符 电子点焊机接间隔毫秒时
* 出口参数:无 编号(行号)0,1,2,3,4,5,6,7,8,9,10
* 备注:CHAR字库的数组CHAR_12[11][24]来寻址
***********************************************/
void LCD_write_char(uint8_t x,uint8_t y,uint8_t cid)
{
uint8_t i;
LCD_set_XY(x,y); //定位(左上角)
for (i=0; i<12; i++) //写字符的上半部分(12列)
{
LCD_write_byte(CHAR_12[cid][i],1);
}
LCD_set_XY(x,y+1); //写字符的下半部分
for (i=12; i<24; i++)
{
LCD_write_byte(CHAR_12[cid][i],1);
}
}
/*********************************************
* 函数名称:LCD_write_value
* 函数功能:显示变量字符5*7(8)或7*12(16)
* 入口参数:x,y,L,val :座标、长度、小数、变量
* 出口参数:无 编号(行号)
* 备注:ASCII码表的数组ASC_5[95][8]来寻址
*********************************************/
void LCD_write_value(uint8_t X,uint8_t Y,uint8_t L,uint8_t D,uint16_t val)
{
uint8_t i,j,f = 0; //列循环、字循环、显示标志
uint16_t n,t,cid; //当前倍数、余数、当前数字
t = val;
n = 1;
for (j = 0; j < L; j++)
n = n * 10;
LCD_set_XY(X,Y); //定位(左上角)
for (j = L; j > 0; j--) //字符循环开始
{
n = j < 2 ? 1: n / 10; //计算当前的倍数
cid = t / n; //当前位数字
t = t - (cid * n);
if (cid > 0)
f = 16;
for ( i=0; i<5; i++) //写一个5*7字符
{
LCD_write_byte(ASC_5[cid + f][i],1);
}
if ( D > 0 & D == (j - 1))
{
for ( i=0; i<5; i++) //写小数点
{
LCD_write_byte(ASC_5[14][i],1);
}
}
else
if(j>1) LCD_write_byte(0x00,1);//插入空列
}
}
……………………
…………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
MAX30102_uvision5_stm32f103c8.7z
2022-1-6 04:39 上传
点击文件名下载附件
678.56 KB, 下载次数: 2
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1