一、主要步骤
要实现对人体心电数据的采样,在实际情况下主要分为AD转换、采样同步、LCD送显三个步骤:
AD转换包括采集模拟的心电信号、模数转换(包括采样、量化、编码三个步骤的,都交给AD芯片完成就可以);
采样同步包括对AD转化得来的数据进行缓存,再以系统时钟将数据送给LCD送显部分(这是因为一般来说AD的采样速率比系统时钟频率要低得多);
LCD送显部分需要来自采样同步的数据进行相关的量化计算,并缓存,再按照一定的顺序用确定的总线送给LCD显示(具体在LCD显示部分阐述)。
在本次实验中,我们省去了AD转换部分,代之以保存在ROM中的标准心电数据,用与AD采样频率相同的读地址ROM_Addr信号模拟AD采样输入。框图如下(图中只是画出了主要的信号,省略了时钟信号和复位信号):
CTRL是主控模块,管理并控制各个功能模块的时序。
Sample&Syn是采样同步模块。CTRL用与AD采样频率相同的读地址ROM_Addr信号读取ECG_ROM中保存的标准心电数据,输出ROM_out给缓冲区FIFO,模拟AD采样输入;FIFO在CTRL的控制下同步较慢的输入(采样速率)和较快的输出(系统时钟频率)。
Cal&Show是计算送显模块。LCD_CAL根据FIFO_Out确定其对应的LCD点阵中点的位置,以数据LCD_Data和地址LCD_Addr的格式存入LCD_RAM缓存,再在系统时钟的控制下将RAM中的数据按确定顺序以SPI总线串行的传给LCD显示。
二、采样同步
ECG_ROM中存放了MIT-BIH的标准心电图数据库的数据,详见http://physionet.org/physiobank/database/mitdb/,选用标号为100的数据,采样速率为3600Hz。该数据库中数据时带符号的十进制小数,为了便于计算,统一将数据库中的数乘1000,再取补码。
为了模拟AD采样输入,CTRL输出用与AD采样频率相同的读地址ROM_Addr信号控制读取ECG_ROM中的数据。ECG_ROM和FIFO模块的输出数据流和时序如下图所示:
三、计算送显
本次实验中使用的LCD屏是64*128点阵,即每行有128个点,每列有64个点,64个点又可以均分为8页,每页8个点,1个点代表1bit,所以完整的一帧图像需要64*128个点的表示,一帧图像耗时64*128*Ts,其中Ts很短,由于人眼的视觉暂留效应,会使人产生图像连续的错觉,于是人就能从LCD上看到连续变化的运动图像了。
LCD_CAL模块主要负责对输入信号FIFO_Out进行转化运算,并确定其对应的LCD点阵中点的位置。
其中的转化运算包括:截取FIFO_Out的前6位,从补码转换成原码,将+0变成-0并将正数部分整体减1(即将上半页整体下移一行,+0与-0重合)。得到Val_Chg[5:0],前三位用于计算Page,后三位用于计算LCD_Data。
我们自上而下将这8页命名为0-7页,我们用位宽为3的寄存器Page的存储Page信息。
位2表示符号Sign以区分上下屏:0-3页显示的是正值,所以Sign=1,4-7页显示的是负值,所以Sign=0。位1和位0表示绝对值Value,0-3页从大到小,4-7页从小到大。
Page[2:0]拼接上随时钟自增的Colume[7:0]组成地址LCD_Addr[9:0]。
每一页的8个点自上而下对应LCD_Data[7:0]的位0到位7,注意,无论是上半屏还是下半屏都应该遵循每一页自上而下对应0到7的顺序,只不过是Val_Chg[5:0]的后三位与LCD_Data[7:0]为1的位数的对应关系不同,详见下图。
下图展示的是LCD屏幕和数据的映射关系:
经过计算的数据在通过SPI串行总线送给LCD之前就要按照以上的数据-地址的格式保存在缓冲区LCD_RAM(1024个存储单元,每个单元位宽为8)中。与此同时,另一端从LCD_RAM 中逐行逐页地读取8位的数据,再通过SPI的并串转换,每个时钟传输1bit数据给LCD显示。
需要注意:LCD_RAM在最开始需要在CTRL的FIFO_Init信号的指示下进行初始化(一般来说是全部置0),此后每过128个时钟需要用FIFO_Init初始化一次,不然就会残留上一帧的数据了,影响下一帧的显示。
三、改进
为了能让LCD更好地显示心电图波形,我们针对显示的一些问题做了改进,罗列如下:
1、 LCD显示的点不连续。原因是ROM中的标准心电数据库的采样速率太低,一个R波(就是尖峰明显的波)只用了7-8个点表示,如下图所示(这是用matlab以离散点显示的ROM中的数据,这里只显示一个波形)。
为了能让波形连续,我对ROM中的标准心电数据进行了多次插值,每次插值都是在相邻的两个数值之间插入两数值的均值。显示结果表明心电波形连续。
2、 加入中心线。为了使显示更加精确,在LCD显示时加入位于屏幕中心的横线,用来区分正负数值。
具体做法是在修改LCD_RAM模块对于来自CTRL的FIFO_Init信号的响应,将原来的对RAM全部置0改为对RAM中所有列的Page4的置为0x01,参见上图(LCD屏幕和数据的映射关系)。
但是修改之后发现问题,当输入的数据处于Page4时,屏幕上数据所在的列会出现只显示数据点而不显示横线点的问题,发现是LCD_CAL模块对LCD_RAM模块的写操作行为的问题:由于对LCD_RAM的写操作是逐页逐列填写的,根据Page和Col拼接所得的LCD_Addr寻址,填写八位的LCD_Data数据,若LCD_Addr所寻地址位于Page4,一次性填写的八位数据LCD_Data就会覆盖掉初始化的横线数据0x01。因此,做修改:根据LCD_Addr做判断,若LCD_Addr所寻地址位于Page4,LCD_Data与0x01按位相或后再写入RAM。显示结果表明修改正确。
用户271389 2011-10-30 23:12
用户377235 2011-10-30 13:40
用户1614939 2011-10-17 22:13
用户408430 2011-10-17 21:40