当前位置:网站首页>京微齐力:基于HMEP060的心率血氧模块开发(1:FPGA发送多位指令)
京微齐力:基于HMEP060的心率血氧模块开发(1:FPGA发送多位指令)
2022-07-29 05:22:00 【千歌叹尽执夏】
日常·唠嗑:
最近有个项目,朋友需要用京微齐力的HME-P1P060读取MAX30102传感器的血氧数据,在做之前想了几种方案,最开始想用IIC读取传统的血氧模块数据,但是后面有看到优信电子新推出的串口类心率血氧模块,网上资料也基本没有,自己曾经也遇到这个难题,开源资料基本都是串口回环实验,综合类的串口很少开源,于是便想尝试一下。
这个项目为了具有可重构性,我将它拆成主要三个子项目:发送指令,接收指令,完整项目整合。
这样做的目的,为的就是以后这个项目,能移植到各个串口类的传感器项目上(很多时候,这类传感器的应用开发都是用嵌入式来完成,因为嵌入式拥有更成熟的各种库,做开发难度会简单很多),让大家更好的做项目。
实验结果
每按一次按键,发送一条9位的指令。
FPGA发送9位指令
一、硬件解析
1、国产FPGA:HMEP060

2、MAX30102心率传感器模块
MAX30102心率传感器模块使用UART协议进行传输数据,不做开发的时候,可以直接通过CH340插在电脑上看数据,但是如果想应用在项目里,就得对内部封装的协议进行解析。
指令表如下:本项目项要采集血氧数据,所以需要向FPGA 发送AT+SPO2\r\n 9位指令。

二、程序设计
1、波特率计算(25MHz时钟)
要做串口通信,绕不开的就是波特率计算,这里对于UART协议就不做介绍了,网上的文章或者视频解说很多,自己搜一下看看。
所谓波特率生成,就是用一个定时器来定时,产生频率与对应波特率时钟频率相同的时钟信号。例如,我们使用波特率为 115200bps,则我们需要产生一个频率为 115200Hz 的时钟信号。
那么如何产生这样一个 115200Hz 的时钟信号呢?
这里,我们首先将115200Hz 时钟信号的周期计算出来,1 秒钟为 1000_000_000ns,因此波特率时钟的周期为:Tb=1000000000/115200=8680.6ns。
即 115200 信号的一个周期为 8680.6ns,那么,我们只需要设定我们的定时器定时时间为 8680.6ns,每当定时时间到,产生一个系统时钟周期长度的高脉冲信号即可。
HMEP060系统时钟频率为25MHz,即周期为 40ns(1÷25000000=0.00000004秒=40ns) ,那么,我们只需要计数 8680/40 个系统时钟,就可获得 8680ns 的定时,bps115200=Tb/Tclk - 1=Tb*fclk - 1=fclk/115200-1。相应的,其它波特率定时值的计算与此相同。具体如下:
bps_DR = 1000000000/9600/40;
2、顶层模块
讲解,我写在代码里面,直接看代码, 这里发送的是9位数据,代码具有很强的一移植性,需要发送多位的,直接在发送数据那里增加字符,然后再状态机增加状态就行。同时代码仍在优化中,写的比较简陋,有心得的朋友,可以优化分享。
完整顶层模块代码:
//**************************************** Message ***********************************//
//技术交流:[email protected]
//关注CSDN博主:“千歌叹尽执夏”
//Author: 千歌叹尽执夏
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: uart_tx_data
// Last modified Date: 2022年5月22日14:31:09
// Last Version: V1.1
// Descriptions: uart发送9位指令
//----------------------------------------------------------------------------------------
//****************************************************************************************//
module uart_tx_data(
Clk,
Reset_n,
Tx_Go,
uart_tx,
Trans_Done
);
input Clk;
input Reset_n;
input Tx_Go; //添加一个KEY,每按一次,发送一次,因为很多传感器都是只接一次指令,就会回传数据,不用一直发
output uart_tx;
output reg Trans_Done;
//Trans_Done的作用是增加代码的可构性,发送完指令后,对Trans_Done拉高,这个接口主要用来给大家做扩展设计的。
reg [7:0]Data;
reg Send_Go;
wire Tx_done;
wire Trans_Go;
reg [71:0]Data72;
reg test_en_dly1;
reg test_en_dly2;
//按键信号打拍
[email protected](posedge Clk)
begin
test_en_dly1 <= Tx_Go;
test_en_dly2 <= test_en_dly1;
end
//控制发送使能
assign Trans_Go = test_en_dly1 & !test_en_dly2;
//需要发送的指令字符,读取血氧的指令为AT+SPO2\r\n
//需要增加字符的,可以增加Data的位宽
[email protected](*)
begin
// Data72 <= "n\r\2OPS+TA";
Data72[7:0] <= "A";
Data72[15:8] <= "T";
Data72[23:16]<= "+";
Data72[31:24]<= "S";
Data72[39:32]<= "P";
Data72[47:40]<= "O";
Data72[55:48]<= "2";
Data72[63:56]<= "\r";
Data72[71:64]<= "\n";
end
//通过状态机的方式,将数据发送出去,每次发8位,总共9个数据
reg [3:0]state;
[email protected](posedge Clk or negedge Reset_n)
if(!Reset_n)begin
state <= 0;
Data <= 0;
Send_Go <= 0;
Trans_Done <= 0;
end
else begin
case(state)
0:
begin
Trans_Done <= 0;
if(Trans_Go)begin
Data <= Data72[7:0];
Send_Go <= 1;
state <= 1;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 0;
end
end
1:
begin
if(Tx_done)begin
Data <= Data72[15:8];
Send_Go <= 1;
state <= 2;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 1;
end
end
2:
begin
if(Tx_done)begin
Data <= Data72[23:16];
Send_Go <= 1;
state <= 3;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 2;
end
end
3:
begin
if(Tx_done)begin
Data <= Data72[31:24];
Send_Go <= 1;
state <= 4;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 3;
end
end
4:
begin
if(Tx_done)begin
Data <= Data72[39:32];
Send_Go <= 1;
state <= 5;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 4;
end
end
5:
begin
if(Tx_done)begin
Data <= Data72[47:40];
Send_Go <= 1;
state <= 6;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 5;
end
end
6:
begin
if(Tx_done)begin
Data <= Data72[55:48];
Send_Go <= 1;
state <= 7;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 6;
end
end
7:
begin
if(Tx_done)begin
Data <= Data72[63:56];
Send_Go <= 1;
state <= 8;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 7;
end
end
8:
begin
if(Tx_done)begin
Data <= Data72[71:64];
Send_Go <= 1;
state <= 9;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 8;
end
end
9:
begin
if(Tx_done)begin
Send_Go <= 0;
Trans_Done <= 1;
state <= 0;
end
else begin
Data <= Data;
Send_Go <= 0;
state <= 9;
end
end
default:
begin
Data <= Data;
Send_Go <= 0;
state <= 0;
end
endcase
end
//例化子模块
uart_byte_tx uart_byte_tx(
.Clk(Clk),
.Reset_n(Reset_n),
.Data(Data),
.Send_Go(Send_Go),
.Baud_set(0),
.uart_tx(uart_tx),
.Tx_done(Tx_done)
);
endmodule
3、子模块
//**************************************** Message ***********************************//
//技术交流:[email protected]
//关注CSDN博主:“千歌叹尽执夏”
//Author: 千歌叹尽执夏
//All rights reserved
//----------------------------------------------------------------------------------------
// File name: uart_byte_tx
// Last modified Date: 2022年5月22日15:20:10
// Last Version: V1.1
// Descriptions: uart协议
//----------------------------------------------------------------------------------------
//****************************************************************************************//
module uart_byte_tx(
Clk,
Reset_n,
Data,
Send_Go,
Baud_set,
uart_tx,
Tx_done
);
input Clk;
input Reset_n;
input [7:0]Data;
input Send_Go;
input [2:0]Baud_set;
output reg uart_tx;
output reg Tx_done;
//系统时钟25MHZ
//Baud_set = 0 就让波特率 = 9600;
//Baud_set = 1 就让波特率 = 19200
//Baud_set = 2 就让波特率 = 38400;
//Baud_set = 3 就让波特率 = 57600;
//Baud_set = 4 就让波特率 = 115200;
reg [17:0]bps_DR;
[email protected](*)
case(Baud_set)
0:bps_DR = 1000000000/9600/40;
1:bps_DR = 1000000000/19200/40;
2:bps_DR = 1000000000/38400/40;
3:bps_DR = 1000000000/57600/40;
4:bps_DR = 1000000000/115200/40;
default:bps_DR = 1000000000/9600/40;
endcase
reg Send_en;
[email protected](posedge Clk or negedge Reset_n)
if(!Reset_n)
Send_en <= 0;
else if(Send_Go)
Send_en <= 1;
else if(Tx_done)
Send_en <= 0;
reg [7:0]r_Data;
[email protected](posedge Clk)
if(Send_Go)
r_Data <= Data;
else
r_Data <= r_Data;
wire bps_clk;
assign bps_clk = (div_cnt == 1);
reg [17:0]div_cnt;
[email protected](posedge Clk or negedge Reset_n)
if(!Reset_n)
div_cnt <= 0;
else if(Send_en)begin
if(div_cnt == bps_DR - 1)
div_cnt <= 0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 0;
reg [3:0]bps_cnt;
[email protected](posedge Clk or negedge Reset_n)
if(!Reset_n)
bps_cnt <= 0;
else if(Send_en)begin
if(bps_clk)begin
if(bps_cnt == 11)
bps_cnt <= 0;
else
bps_cnt <= bps_cnt + 1'b1;
end
end
else
bps_cnt <= 0;
//并转串,每算一个波特率时钟,就发送一位数据
[email protected](posedge Clk or negedge Reset_n)
if(!Reset_n) begin
uart_tx <= 1'b1;
end
else begin
case(bps_cnt)
1:uart_tx <= 0;
2:uart_tx <= r_Data[0];
3:uart_tx <= r_Data[1];
4:uart_tx <= r_Data[2];
5:uart_tx <= r_Data[3];
6:uart_tx <= r_Data[4];
7:uart_tx <= r_Data[5];
8:uart_tx <= r_Data[6];
9:uart_tx <= r_Data[7];
10:uart_tx <= 1;
11:begin uart_tx <= 1;end
default:uart_tx <= 1;
endcase
end
//发送完成后,对Tx_done进行拉高
[email protected](posedge Clk or negedge Reset_n)
if(!Reset_n)
Tx_done <= 0;
else if((bps_clk == 1) && (bps_cnt == 10))
Tx_done <= 1;
else
Tx_done <= 0;
endmodule
三、工程获取
等项目完成了,会上传项目工程,暂时没时间整理。读者也可以自己建立工程,把这两个模块放进去就能看到代码。
边栏推荐
- 五、图像像素统计
- 迁移学习——Robust Visual Domain Adaptation with Low-Rank Reconstruction
- 一、Focal Loss理论及代码实现
- 1、 Combine multiple txt files into one TXT file
- Technology that deeply understands the principle of MMAP and makes big manufacturers love it
- 虚假新闻检测论文阅读(五):A Semi-supervised Learning Method for Fake News Detection in Social Media
- CNOOC, desktop cloud & network disk storage system application case
- 虚假新闻检测论文阅读(三):Semi-supervised Content-based Detection of Misinformation via Tensor Embeddings
- ABSA1: Attentional Encoder Network for Targeted Sentiment Classification
- 虚假新闻检测论文阅读(四):A novel self-learning semi-supervised deep learning network to detect fake news on...
猜你喜欢

第三周周报 ResNet+ResNext

预训练语言模型的使用方法

Error in installing pyspider under Windows: Please specify --curl dir=/path/to/build/libcurl solution

Typical cases of xdfs & China Daily Online Collaborative Editing Platform

1、 Focal loss theory and code implementation

备份谷歌或其他浏览器插件

ML10自学笔记-SVM
![[target detection] KL loss: bounding box progression with uncertainty for accurate object detection](/img/8c/1a561fab040730ae29901a04b70ac4.png)
[target detection] KL loss: bounding box progression with uncertainty for accurate object detection

【Transformer】SOFT: Softmax-free Transformer with Linear Complexity

Configuration and use of Nacos external database
随机推荐
These process knowledge you must know
【Transformer】SOFT: Softmax-free Transformer with Linear Complexity
Typical cases of xdfs & China Daily Online Collaborative Editing Platform
Chongqing Avenue cloud bank, as a representative of the software industry, was invited to participate in the signing ceremony of key projects in Yuzhong District
2、 Multi concurrent interface pressure test
Jianzhi core taocloud full flash SDS helps build high-performance cloud services
pip安装后仍有解决ImportError: No module named XX
研究生新生培训第三周:ResNet+ResNeXt
【bug】XLRDError: Excel xlsx file; not supported
Change! Change! Change!
1、 What is the difference between transfer learning and fine tuning?
[target detection] generalized focal loss v1
【Transformer】AdaViT: Adaptive Tokens for Efficient Vision Transformer
【Transformer】AdaViT: Adaptive Tokens for Efficient Vision Transformer
一、常见损失函数的用法
How to perform POC in depth with full flash distribution?
ABSA1: Attentional Encoder Network for Targeted Sentiment Classification
GA-RPN:引导锚点的建议区域网络
Ffmpeg creation GIF expression pack tutorial is coming! Say thank you, brother black fly?
Spring, summer, autumn and winter with Miss Zhang (5)