找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 465|回复: 0
打印 上一主题 下一主题
收起左侧

STM32血氧程序无法编译 求帮助

[复制链接]
跳转到指定楼层
楼主
ID:673776 发表于 2021-12-31 11:22 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
STM32血氧程序
  1. #include "stm32f103c8t6.h"
  2. //#include "stm32f1xx_hal_gpio.h"
  3. #include "mbed.h"
  4. #include "algorithm.h"
  5. #include "MAX30102.h"
  6. //#include "lcd_5110.h"
  7. #include "ascii5x8.h"           //5x8ASCII字符集
  8. #include "charcode.h"           //12x16(14)汉字子集
  9. #include "asciicode.h"          //5x8(8)ASCII子集
  10. //#include "sys.h"

  11. /************ 定义LCD相关的管脚功能 ***********/

  12. #define LCD_RST_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_SET);}while(0) //复位脚① PB11
  13. #define LCD_RST_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_11,GPIO_PIN_RESET);}while(0)
  14. #define LCD_CE_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_SET);}while(0)  //片选脚②PB10
  15. #define LCD_CE_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_10,GPIO_PIN_RESET);}while(0)
  16. #define LCD_DC_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_SET);}while(0)   //数据/命令选择脚③PB0
  17. #define LCD_DC_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_1,GPIO_PIN_RESET);}while(0)
  18. #define LCD_DIN_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_SET);}while(0)  //数据输入④PB1
  19. #define LCD_DIN_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_0,GPIO_PIN_RESET);}while(0)
  20. #define LCD_CLK_SET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);}while(0)  //时钟信号脚⑤PB5
  21. #define LCD_CLK_RESET do{HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_RESET);}while(0)

  22. /************** 结束管脚定义 *****************/

  23. #define CLOCK 72/8 //时钟=72M


  24. #define MAX_BRIGHTNESS 255

  25. uint32_t aun_ir_buffer[500]; //红外LED传感器数据
  26. int32_t n_ir_buffer_length;  //数据长度
  27. uint32_t aun_red_buffer[500];//红色LED传感器数据
  28. int32_t n_sp02;              //SPO2血氧值
  29. int8_t ch_spo2_valid;        //血氧值有效标志
  30. int32_t n_heart_rate;        //心率值
  31. int8_t  ch_hr_valid;         //心率值有效标志
  32. uint8_t uch_dummy;
  33. const uint8_t level[]={0x80,0xC0,0xE0,0xF0,0xF8,0xFC,0xFE,0xFF};//波形
  34. //const uint8_t level[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};//曲线
  35. uint8_t disp=1;              //动态显示列

  36. Serial pc(SERIAL_TX, SERIAL_RX);//初始化串行端口, TX-PA2, RX-PA3

  37. PwmOut pwmled(PB_3);         //初始化连接到LED的PWM输出PB3(亮度变化)
  38. DigitalIn INT(PB_7);         //PB7连接MAX30102的INT输出引脚
  39. DigitalOut led(PC_13);       //PC13连接板载用户LED

  40. void LCD_Config(void);       //LCD配置引脚
  41. void LCD_init(void);         //LCD初始化
  42. void LCD_write_byte(uint8_t dat,uint8_t dc);//LCD写字节
  43. void LCD_set_XY(uint8_t X,uint8_t Y);//LCD设置坐标
  44. void LCD_clear(void);        //LCD清屏
  45. void LCD_write_ASCII(uint8_t X,uint8_t Y,uint8_t *stru);//LCD显示5x7字符串
  46. void LCD_write_ASC_SIN(uint8_t X,uint8_t Y,uint8_t cid);//LCD显示5x7字符
  47. void LCD_write_ASC7x12(uint8_t X,uint8_t Y,uint8_t cid);//LCD显示7x12字符
  48. void LCD_write_char(uint8_t x,uint8_t y,uint8_t cid);   //LCD显示12x14字符
  49. void LCD_write_value(uint8_t X,uint8_t Y,uint8_t L,uint8_t D,uint16_t val);//LCD显示变量
  50. void LCD_write_string(uint8_t x,uint8_t y,uint8_t *stru);//LCD显示12x14字符串

  51. void display_main(void);    //主屏幕显示
  52. void display_erro(void);    //信号错误
  53. void display_wait(void);    //等待信号
  54. void display_ir(uint16_t ir);//动态显示曲线

  55. /*------------------------------------------------------------
  56.                          us延时函数
  57. ------------------------------------------------------------*/
  58. void delay_us(uint16_t us)
  59. {
  60.     uint8_t n;                    
  61.     while(us--)for(n=0;n<CLOCK;n++);         
  62. }

  63. /*------------------------------------------------------------
  64.                          ms延时函数
  65. ------------------------------------------------------------*/
  66. void delay_ms(uint16_t ms)
  67. {
  68.     while(ms--)delay_us(1000);         
  69. }


  70. // 当您按重置时,设置程序运行一次。
  71. int main() {
  72.     uint32_t un_min, un_max, un_prev_data;//用于计算反映心跳的车载LED亮度的变量
  73.     int i;
  74.     int32_t n_brightness;
  75.     float f_temp;
  76.         uint8_t flag = 0;
  77.         
  78.     maxim_max30102_reset();  //重置MAX30102
  79.    
  80.         //初始化串行口波特率
  81.     pc.baud(115200);
  82.     pc.format(8,SerialBase::None,1);
  83.     wait(1);
  84.         
  85.         //初始化LCD5110
  86.     LCD_init();
  87.         display_main();
  88.         
  89.     //读取和清除状态寄存器
  90.     maxim_max30102_read_reg(0,&uch_dummy);
  91.    
  92.         maxim_max30102_init();   //初始化MAX30102
  93.         
  94.     n_brightness=0;
  95.     un_min=0x3FFFF;
  96.     un_max=0;
  97.   
  98.     n_ir_buffer_length=500;  //缓冲区长度100存储以100sps运行的5秒样本
  99.    
  100.     //读取前500个样本,确定信号范围
  101.     for(i=0;i<n_ir_buffer_length;i++)
  102.     {
  103.         while(INT.read()==1);//等待直到中断pin生效
  104.         
  105.         maxim_max30102_read_fifo((aun_red_buffer+i),(aun_ir_buffer+i));//从MAX30102的FIFO读数据
  106.             
  107.         if(un_min>aun_red_buffer[i])
  108.             un_min=aun_red_buffer[i];//更新信号最小值
  109.         if(un_max<aun_red_buffer[i])
  110.             un_max=aun_red_buffer[i];//更新信号最大值
  111.         pc.printf("red=");
  112.         pc.printf("%i", aun_red_buffer[i]);
  113.         pc.printf(", ir=");
  114.         pc.printf("%i\n\r", aun_ir_buffer[i]);
  115.                
  116.     }
  117.     un_prev_data=aun_red_buffer[i];
  118.     //计算前500个样本(前5秒样本)后的心率和血氧数值。
  119.     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);
  120.     //从MAX31022连续取样。每1秒计算一次心率和血氧饱和度。
  121.    
  122.         while(1)
  123.     {

  124.         i=0;
  125.         un_min=0x3FFFF;
  126.         un_max=0;
  127.         //将前100组样本转储到内存中,并将最后400组样本移到顶部
  128.         for(i=100;i<500;i++)
  129.         {
  130.             aun_red_buffer[i-100]=aun_red_buffer[i];
  131.             aun_ir_buffer[i-100]=aun_ir_buffer[i];
  132.             //更新信号最小值和最大值
  133.             if(un_min>aun_red_buffer[i])
  134.                 un_min=aun_red_buffer[i];
  135.             if(un_max<aun_red_buffer[i])
  136.                 un_max=aun_red_buffer[i];
  137.         }
  138.         //在计算心率前取100组样本。
  139.         for(i=400;i<500;i++)
  140.         {
  141.             un_prev_data=aun_red_buffer[i-1];
  142.             while(INT.read()==1);              //等待传感器信号
  143.             maxim_max30102_read_fifo((aun_red_buffer+i), (aun_ir_buffer+i));
  144.         
  145.             if(aun_red_buffer[i]>un_prev_data) //只是根据相邻两个AD数据的偏差来确定LED的亮度
  146.             {
  147.                 f_temp=aun_red_buffer[i]-un_prev_data;
  148.                 f_temp/=(un_max-un_min);
  149.                 f_temp*=MAX_BRIGHTNESS;
  150.                 n_brightness-=(int)f_temp;
  151.                 if(n_brightness<0)
  152.                     n_brightness=0;
  153.             }
  154.             else
  155.             {
  156.                 f_temp=un_prev_data-aun_red_buffer[i];
  157.                 f_temp/=(un_max-un_min);
  158.                 f_temp*=MAX_BRIGHTNESS;
  159.                 n_brightness+=(int)f_temp;
  160.                 if(n_brightness>MAX_BRIGHTNESS)
  161.                     n_brightness=MAX_BRIGHTNESS;
  162.             }
  163.                         
  164.                         if(flag==0)         //两个循环显示一次
  165.                         {
  166.                                 if(n_heart_rate>180)//脉搏过速
  167.                                     display_erro();
  168.                                 else
  169.                                 {
  170.                                     if(n_heart_rate<20)
  171.                                                 display_wait();
  172.                                         else
  173.                                         display_ir((float)n_brightness/5);
  174.                                 }
  175.                                 flag++;
  176.                         }
  177.                         else
  178.                                 flag = 0;
  179.                         
  180.             pwmled.write(1-(float)n_brightness/256);//PWM控制LED亮度
  181.                         if(n_brightness<120)
  182.                                 led=1;
  183.                         else
  184.                                 led=0;
  185.         }
  186.         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);
  187.         pc.printf("HR=%i, ", n_heart_rate);
  188.             pc.printf("SpO2=%i",n_sp02);
  189.                
  190.                    LCD_write_value(24,5,3,0,n_sp02);
  191.             LCD_write_value(67,5,3,0,n_heart_rate);
  192.                
  193.         }
  194. }

  195. /*********************************************
  196. * 函数名称:LCD_Config
  197. * 函数功能:配置LCD引脚
  198. * 入口参数:无
  199. * 出口参数:无
  200. *********************************************/
  201. void LCD_Config(void)
  202. {
  203.     GPIO_InitTypeDef GPIO_InitTypeDef;             //定义结构体
  204.     GPIO_InitTypeDef.Pin = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_5 | GPIO_PIN_10 | GPIO_PIN_11; //配置LCD引脚
  205.     GPIO_InitTypeDef.Mode = GPIO_MODE_OUTPUT_PP;   //推挽输出
  206.     GPIO_InitTypeDef.Speed = GPIO_SPEED_FREQ_HIGH; //速度
  207.     HAL_GPIO_Init(GPIOB, &GPIO_InitTypeDef);       //初始化GPIO
  208. }

  209. /*********************************************
  210. * 函数名称:LCD_init
  211. * 函数功能:5110初始化
  212. * 入口参数:无
  213. * 出口参数:无
  214. * 备注:接通电源后需要一个RES低电平脉冲复位,当VDD变为高电平之后
  215. *       最多100ms,RST输入低电平(<0.3VDD)
  216. *********************************************/
  217. void LCD_init(void)
  218. {
  219.     LCD_Config();                      //配置LCD连线

  220.     LCD_RST_RESET;                     //LCD_RST = 0 复位LCD5110
  221.         
  222.     delay_us(2);
  223.     LCD_RST_SET;                       //LCD_RST = 1;

  224.     LCD_CE_RESET;                      //LCD_CE = 0;  关闭LCD
  225.     delay_us(2);
  226.     LCD_CE_SET;                        //LCD_CE = 1;  关闭LCD

  227.     LCD_write_byte(0x21,0);            //使用扩展LCD令设置LCD模式
  228.     LCD_write_byte(0xc8,0);            //设置液晶偏置电压
  229.     LCD_write_byte(0x06,0);            //温度校正(温度系数2)
  230.     LCD_write_byte(0x13,0);            //1:48
  231.     LCD_write_byte(0x20,0);            //使用基本命令,V=0,水平寻址
  232.     LCD_write_byte(0x0c,0);            //设定显示模式,正常显示
  233.     LCD_clear();                       //清屏

  234.     LCD_CE_SET;                        //LCD_CE = 1; //关闭LCD
  235. }


  236. /*********************************************
  237. * 函数名称:LCD_write_byte
  238. * 函数功能:模拟SPI接口时序写数据/命令LCD
  239. * 入口参数:data   :写入的数据;
  240. *           dc        :写数据1/命令0选择
  241. * 出口参数:无
  242. * 备注:管脚D/C(LCD_DC)用于选择写的是命令(D/C=0)还是数据(D/C=1)
  243. *********************************************/
  244. void LCD_write_byte(uint8_t dat,uint8_t dc)
  245. {
  246.     uint8_t i;
  247.    
  248.     LCD_CLK_RESET;                            //先拉低时钟CLK
  249.    
  250.     LCD_CE_RESET;                             //LCD_CE = 0; 选择5110
  251.    
  252.     if (dc == 1)
  253.     {
  254.         LCD_DC_SET;                           //LCD_DC = dc; dc=0数据,dc=1命令
  255.     }
  256.     else {
  257.         LCD_DC_RESET;
  258.     }
  259.     for (i=0; i<8; i++)                      //发送8位
  260.     {
  261.         if (dat & 0x80)
  262.         {
  263.             LCD_DIN_SET;                     //LCD_DIN = 1;
  264.         }
  265.         else {
  266.             LCD_DIN_RESET;                   //LCD_DIN = 0;
  267.         }
  268.         LCD_CLK_SET;                         //LCD_CLK = 1;
  269.         delay_us(1);
  270.         dat = dat << 1;                             //移位,准备发送下一位
  271.         LCD_CLK_RESET;                       //LCD_CLK = 0; //发送同步时钟
  272.     }
  273.    
  274.     LCD_CE_SET;                              //LCD_CE = 1;  //关闭5110
  275. }

  276. /*********************************************
  277. * 函数名称:LCD_set_XY
  278. * 函数功能:设置LCD坐标函数
  279. * 入口参数:X      :0-83;
  280. *           Y         :0-5
  281. * 出口参数:无
  282. * 备注:
  283. *********************************************/
  284. void LCD_set_XY(uint8_t X,uint8_t Y)
  285. {
  286.     LCD_write_byte(0x40 | Y,0);              //column?
  287.     LCD_write_byte(0x80 | X,0);              //row?
  288. }


  289. /*********************************************
  290. * 函数名称:LCD_clear
  291. * 函数功能:5110清屏(用空白写满屏幕)
  292. * 入口参数:无
  293. * 出口参数:无
  294. * 备注:
  295. *********************************************/
  296. void LCD_clear(void)
  297. {
  298.     uint8_t i,j;
  299.     LCD_set_XY(0,0);                             //定位左上角
  300.     for (i=0; i<6; i++)
  301.     {
  302.         for (j=0; j<84; j++)
  303.         {
  304.             LCD_write_byte(0x00,1);
  305.         }
  306.     }
  307. }


  308. /*********************************************
  309. * 函数名称:LCD_write_ASCII
  310. * 函数功能:显示字符串5*7(8)
  311. * 入口参数:x,y,cid   :显示ASCII字符
  312. * 出口参数:无               编号(行号)32~127
  313. * 备注:ASCII码表的数组ASC_5[95][8]来寻址
  314. *********************************************/
  315. void LCD_write_ASCII(uint8_t X,uint8_t Y,uint8_t *stru)
  316. {
  317.     uint8_t i;

  318.     LCD_set_XY(X,Y);                     //定位(左上角)
  319.     while (1)
  320.     {
  321.         for ( i=0; i<5; i++)        //输出一个5*7字符
  322.         {
  323.             LCD_write_byte(ASC_5[*stru-32][i],1);
  324.         }
  325.         stru++;
  326.         
  327.         if(*stru == '\0') break;   //在每个字符串的最后,会有一个'\0'
  328.         LCD_write_byte(0x00,1);     //插入空列
  329.     }  
  330. }


  331. /*********************************************
  332. * 函数名称:LCD_write_ASC_SIN
  333. * 函数功能:显示单个字符5*7(8)
  334. * 入口参数:x,y,cid   :显示ASCII字符
  335. * 出口参数:无               编号(行号)32~127
  336. * 备注:ASCII码表的数组ASC_5[95][8]来寻址
  337. *********************************************/
  338. void LCD_write_ASC_SIN(uint8_t X,uint8_t Y,uint8_t cid)
  339. {
  340.     uint8_t i;
  341.     LCD_set_XY(X,Y);                   //定位(左上角)
  342.     for ( i=0; i<5; i++)           //输出一个5*7字符
  343.     {
  344.         LCD_write_byte(ASC_5[cid-32][i],1);
  345.     }
  346. }


  347. /*********************************************
  348. * 函数名称:LCD_write_ASC7x12
  349. * 函数功能:显示自定义字符7*12(16)
  350. * 入口参数:x,y,cid   :显示的字符  0 1 2 3 4 5 6 7 8 9  =  m  s
  351. * 出口参数:无               编号(行号)0,1,2,3,4,5,6,7,8,9,10,11,12
  352. * 备注:ASCII码表的数组ASC_7[13][14]来寻址
  353. *********************************************/
  354. void LCD_write_ASC7x12(uint8_t X,uint8_t Y,uint8_t cid)
  355. {
  356.     uint8_t i;
  357.    
  358.     LCD_set_XY(X,Y);                   //定位{左上角)
  359.     for (i=0; i<7; i++)                //显示字符的上半部分(7列)
  360.     {
  361.         LCD_write_byte(ASC_7[cid][i],1);
  362.     }
  363.    
  364.     LCD_set_XY(X,Y+1);                 //显示字符的下半部分
  365.     for (i=7; i<14; i++)
  366.     {
  367.         LCD_write_byte(ASC_7[cid][i],1);
  368.     }
  369. }


  370. /*********************************************
  371. * 函数名称:LCD_write_CHAR
  372. * 函数功能:显示自定义字符12*14(16)
  373. * 入口参数:x,y,cid  :显示的字符  电子点焊机接间隔毫秒时
  374. * 出口参数:无              编号(行号)0,1,2,3,4,5,6,7,8,9,10
  375. * 备注:CHAR字库的数组CHAR_12[11][24]来寻址
  376. ***********************************************/

  377. void LCD_write_char(uint8_t x,uint8_t y,uint8_t cid)
  378. {
  379.     uint8_t i;
  380.    
  381.     LCD_set_XY(x,y);                   //定位(左上角)
  382.     for (i=0; i<12; i++)               //写字符的上半部分(12列)
  383.     {
  384.         LCD_write_byte(CHAR_12[cid][i],1);
  385.     }
  386.    
  387.     LCD_set_XY(x,y+1);                 //写字符的下半部分
  388.     for (i=12; i<24; i++)
  389.     {
  390.         LCD_write_byte(CHAR_12[cid][i],1);
  391.     }
  392. }

  393. /*********************************************
  394. * 函数名称:LCD_write_value
  395. * 函数功能:显示变量字符5*7(8)或7*12(16)
  396. * 入口参数:x,y,L,val :座标、长度、小数、变量
  397. * 出口参数:无                编号(行号)
  398. * 备注:ASCII码表的数组ASC_5[95][8]来寻址
  399. *********************************************/
  400. void LCD_write_value(uint8_t X,uint8_t Y,uint8_t L,uint8_t D,uint16_t val)
  401. {
  402.     uint8_t i,j,f = 0;              //列循环、字循环、显示标志
  403.     uint16_t n,t,cid;               //当前倍数、余数、当前数字

  404.     t = val;
  405.     n = 1;
  406.     for (j = 0; j < L; j++)
  407.       n = n * 10;
  408.    
  409.     LCD_set_XY(X,Y);                        //定位(左上角)

  410.     for (j = L; j > 0; j--)         //字符循环开始
  411.     {
  412.         n = j < 2 ? 1: n / 10;      //计算当前的倍数
  413.         cid = t / n;                //当前位数字
  414.         t = t - (cid * n);
  415.         if (cid > 0)
  416.                         f = 16;
  417.         for ( i=0; i<5; i++)        //写一个5*7字符
  418.         {
  419.             LCD_write_byte(ASC_5[cid + f][i],1);
  420.         }
  421.         if ( D > 0 & D == (j - 1))
  422.         {
  423.             for ( i=0; i<5; i++)    //写小数点
  424.             {
  425.                 LCD_write_byte(ASC_5[14][i],1);
  426.             }
  427.         }
  428.         else
  429.           if(j>1) LCD_write_byte(0x00,1);//插入空列
  430.     }
  431. }
  432. ……………………

  433. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码


MAX30102_uvision5_stm32f103c8.7z

678.56 KB, 下载次数: 2

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表