摘要:ADS1292R是TI公司早在2012年就出产的一款医用级ADC芯片,它主要应用在医疗仪器(心电图ECG),能够监护患者以及和人护理和健身监视器。ADS1292R具备两个低噪声可编程增益放大器(PGA)和和两个高分别率模数转换器器(ADC),集成了心电采集所须要的部件,方便设备小型化。它的功耗极低,使得能够做为长时间监控成为可能。并且输入参考噪音低,共模抑制比高。足以进行心电采集。电赛极可能会让你们利用这款芯片作一个心电图检测仪,显示模块极可能就是你们所熟知的RGB大屏幕,同时这道题应该是信号题了。前端
心电信号和呼吸信号是人体的重要生物电信号。尤为是心电信号,它比其余生物电信号更直观,更具备规律性,它是反映心脏健康情况的重要依据。心电图是诊断和分析治疗心血管疾病的一个重要手段,在临床治疗中心电图获得普遍应用。可是常规心电图通常须要经过大型医疗场所,如医院、疗养院的心电图机采集数据得到,其得到途径较难、价格较高、耗时长等弊端阻碍了心电图机的进一步应用。今年你们经历了新冠疫情,因此出这种题目也是情理当中,毕竟学以至用,学了不能用,那学了又有何用?对吧。编程
一、引脚功能及配置
这可芯片的引脚还很多,一共有32个引脚。固然作电赛你们确定都是买的几百块钱的模块,确定不会本身亲自动手焊接,并且买的模块只会把芯片所须要的通讯引脚和电源引脚引出来。因此作硬件的也就节省了不少时间。固然节省的时间不是让你去休息的。你须要花大量的时间来研究数据手册,把外围电路优化好才能让软件更好地去写代码。
性能
这里我简单的看一下数据手册,可能分析的不对,须要各位大显身手去开动大家聪明的大脑了。咱们从1号到32号引脚讲讲它的引脚功能:优化
- 1号和2号引脚PGA1N/PGA1P是PGA的输出引脚。
- 3号和4号引脚IN1N/IN1P这是一对模拟输入,这里用的是差分输入以减少共模干扰,在它们输入到MUX以前,还通过了EMI滤波器。
- 5号和6号引脚 IN2P/IN2N和3号和4号引脚一样是一对模拟输入,差分输入以减少共模干扰。
- 7号和8号引脚PGA2N/PGA2P和上面的1号和2号引脚对应,是PGA的输出引脚。
- 9号和10号引脚VREFP和VREFN分别是同相和反相反馈电压。
- 11号和27号引脚VCAP1和VCAP2是旁路电容,做用是吸取器件的交流成分(纹波经常被认为是交流成分)
- 12号AVDD是模拟电源.
- 13号AVSS是模拟地。
- 14号CLKSEL引脚和寄存器中时钟管理的部分共同控制了外部或者内部时钟的选择,以及时钟是否从17号引脚CLK引脚输出。
- 15号PWDN/RESET是低有效的复位功能。
- 16号START使能引脚。
- 18号到21号四个引脚CS SCLK DIN DOUT 是标准的SPI通讯协议。
- 22号引脚DRDY低有效的数据传输准备完成标志信号。
- 23号引脚DVDD数字电源。
- 24号引脚DGND数字地。
- 25号和26号引脚GPIO1和GPIO2是配置寄存器的引脚。
- 28号和引脚RLDINV是右腿驱动的反向输入端,不用的时候连到模拟地上。
- 29号和引脚RLDIN/RLDREF是右腿驱动电路对MUX的输入,或者右腿驱动电路的非逆变输入,不用的时候必须接到模拟地AVSS上。
- 30号和引脚RLDOUT 右腿驱动输出。
- 31号和32号引脚RESP_MODP/IN3P RESP_MODN/IN3N 这一对引脚有两个功能:第一是做为呼吸的激励信号(模拟输出);第二个做用是辅助的模拟差分输入,能够被MUX复用到任何一路PGA上。
注意:ui
- RLD 开头的引脚,RLD是“右腿驱动电路”,是医疗电子中一个常见的概念。由于医疗电子其实是采集人体固定位置间的生物电压,在它的量级,人体自己做为天线接收的家庭用电电器等的辐射产生的电压就是一个不可忽略的噪声了,因此这时候咱们须要想办法抑制这个共模电压:
- 什么是PGA? PGA是“可编程增益放大器” ,能够做为前端减少高速ADC的噪声,其原理就是使用PGA提供的高增益下,信噪比提高,这样就总的下降了噪声。
二、信号采集的硬件要求
心电及呼吸信号采集前端是整个监护系统的核心部分,若是前端信号采集部分的电路出现问题,即便你的模块板子再好也不能获得你想要的输入信号,天然就GG。ECG 属于微弱的小信号,其幅值在 10μ V~5mV 之间,极易受到干扰,致使有用信号淹没在诸多噪声中。为了能有效地提取出有用信号,对信号采集硬件提出以下要求:spa
- (1)高输入阻抗
人体阻抗高达几 KΩ 至几十 KΩ,能够将人体当作是高阻抗的弱信号输出源。人体自己、衣着和环境等的不一样会引发人体阻抗很大的变化,为了防止人体阻抗的波动引发监护系统信号的不稳定,信号采集硬件应具备较高的输入阻抗。同时,硬件采集电路的输入阻抗也不宜太高,不然会引入较强的外界干扰。那这时你的硬件手就应该好好利用运算放大器来设计电路。 - (2)高共模抑制比CMRR
心电信号受到的最大干扰是 50Hz 的工频干扰,它以共模的形式加载到每个电极上,造成共模干扰。所以心电采集电路应具备很高的共模抑制比,通常要求在 60~80dB。
这两点是前端设计电路最重要的两点。设计
三、电极片的选择
极片也是传感器的一种,其做用是将人体内的离子导电的位移电流转化为检测电路中的电子导电的传导电流,电极片做为检测电路输入前端,其性能也影响着检测电路的噪声、共模抑制比等,因此选择合适的电极片对整个系统的信号质量尤其重要。既然是比赛那就用学校的钱买最好的点电极片了,战术后仰!!!
3d
四、测量的电路
下图1是官方数据手册中截取的,图二是对应的中文内部框图,图三是在网上屡次看到的原理图。有些图用的人多了天然有他的道理,这个没必要纠结。设计电路首先要听从数据手册而后再在此电路的基础上进行修改。
注意:因为人体阻抗高达几KΩ 至几十KΩ,在心电信号采集时经常遇到信号偏差大或者失真现象。心电信号除了易受外界干扰之外,人体内部器官之间、表皮之间都存在相互影响,甚至是人的情绪变化也会引发心电信号不稳定。
调试
五、信号输入电路和右腿驱动电路设计
ADS1292R 能够实现双通道信号采集和模数转换,通道 1(IN1N 和 IN1P)为呼吸信号采集通道,IN3N 和 IN3P 为 ADS1292R 内部产生的32kHz 正弦电流信号的输出端。在正弦电流信号的输出电路中,能够在31号和32号引脚外加保护电阻,限制从 ADS1292R 流向人体的电流,同时还能够在电阻后加电容起到隔离流回人体的直流的做用(电阻和电容是串联)。在呼吸信号输入电路中,C2和 C7起到抑制流回人体的直流电流的做用。C1和 C6起到人体免受电路突发故障所引发的大电流伤害的做用。code
心电信号极易受到 50Hz 工频干扰,这种干扰常以共模的形式出现。通常在生物电信号检测电路中,须要对消驱动电路即右腿驱动电路来消除这种共模干扰,从而提升系统的共模抑制比。
ADS1292R 片内集成了右腿驱动电路,这样有利于减少监护设备的体积,下降功耗。右腿信号由 RLDINV 端口输入至片内右腿驱动电路,设置 ADS1292R内部 RLD_SENS 寄存器,使片内右腿驱动电路的输出连至通道 2 以减小心电信号中共模干扰。官方公开的资料中并未给出片内右腿驱动电路的反相放大器中电阻阻值,其放大倍数未知,为保证整个电路的信号稳定、可靠,右腿驱动电路须要各位大佬根据系统须要外搭。
六、心电及呼吸信号降噪
心电信号很是微弱,典型值仅为 1mV 左右。正常的心电信号大部分为 0.5~ 40Hz 的低频信号,而心电信号的整体范围为 0.05~100Hz。心电信号极易受到来自外界、人体自身以及电路的干扰,如基线漂移、工频干扰、肌电噪声等。干扰信号混杂于心电及呼吸信号中,致使有用信号畸变,有时有用信号会彻底淹没在噪声里,故有用信号的特征值很难被提取。因此相应的滤波去噪处理是必要的。
经常使用的心电信号去噪方法有硬件降噪和软件滤波这两种。硬件降噪主要是经过搭建相应的电路来实现滤波功能,但这种硬件滤波电路不只搭建调试难度大,并且增长了成本、体积和功耗。建议你们经过软件滤波,这对参加电赛的软件手来讲确定不难,智能车都搞过这点滤波的问题还能难道你这个大佬吗?对吧!
七、主控芯片
TI杯固然是建议用TI提供的板子—MSP430。若是你前期没有用过MSP430的板子也没有问题,用STM32也不是不能够。另外芯片也单片机通讯的方式是SPI通讯,我相信SPI通讯你们都会,由于有的7针的OLED显示屏就是用的SPI通讯,这点就不用多说了。
八、驱动代码
代码初始化须要配置寄存器,具体程序中已经注释的很是清楚,仅供参考啊!
void ads_Init(void) { uint8_t send_data[20], read_data[20]; ads_Reset(1); // 复位引脚置一,正常工做 osDelay(1000); osDelay(100); //指令:中止连续读数据模式 send_data[0]=ADS1292R_CMD_SDATAC; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,1,1000)); osDelay(10); //写配置寄存器2=0xa0,内部参考电压为2.42V send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_CONFIG2); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0xa0; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); //写配置寄存器1=0x01,连续转换模式,采样率为250 send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_CONFIG1); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0x01; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); //写导联脱落检测寄存器=0xF0,正负极分别为70%和30%,该功能实际未使用 send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_LOFF); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0xF0; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); //写通道1设置寄存器=0x30,设置增益为3,正常节点输入 send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_CH1SET); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0x30; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); //写右腿驱动寄存器=0xEF,PGA的斩波频率为4分频,使能右腿驱动,关闭右腿驱动的脱落检测,通道2的右腿驱动负极和正极分别链接到通道2输入的负极和正极,通道1的右腿驱动负极和正极分别链接到通道1的负极和正极 send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_RLD_SENS); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0xEF; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); //写脱落检测寄存器=0x0F,关闭通道1和2的电流方向检测,使能通道1和2的正负极脱落检测 //其实只使用了通道1,并且脱落检测实际上没有使用 send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_LOFF_SENS); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0x0F; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); //写呼吸控制寄存器1=0xF2,使能呼吸调制解调电路,呼吸解调相位为135°,时钟为32KHz,内部时钟 send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_RESP1); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0xF2; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); //写呼吸控制寄存器2=0x83,关闭偏置校准,呼吸控制频率为32KHz,右腿驱动参考信号为外部信号 send_data[0] = ADS1292R_CMD_WREG_1(ADS1292R_REG_RESP2); send_data[1] = ADS1292R_CMD_WREG_2(1); send_data[2] = 0x83; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,3,1000)); osDelay(10); ads_Start(1); //启动转换 osDelay(10); //指令:连续读模式 send_data[0]=ADS1292R_CMD_RDATAC; while(HAL_OK!= HAL_SPI_TransmitReceive(&hspi1,send_data,read_data,1,1000)); osDelay(10); } void ads_Get_Data(uint8_t* raw_data) { static uint8_t sendBuf[9]={ 0,0,0,0,0,0,0,0,0}; HAL_SPI_TransmitReceive_DMA(&hspi1,sendBuf,raw_data,9); }