最近在做低频数字式相位测量仪,很多人都是卡在stm32和fpga串口通信上,还有相位差的测量,下面讲讲通信的解决办法!fpga部分用了某位大神的串口通信模块进行参考(module tx_module,module tx_control_module,module tx_bps_module,module uartsent),然后自己写了stm32f1精英版的串口接收程序。
*************************************************************************************************************************************************特别注意Do_sig 和start_sig,Done_sig。Do_sig是 发送信号,每当监测到时钟上升沿时开始发送数据;start_sig是开始进行测量信号,由stm32f1引脚提供(低电平有效)无此信号fpga不进行测量;Done_sig是计数完成信号,不需要也没事。
*************************************************************************************************************************************************
1、fpga部分
module uartsent
(
input CLK_25M, //PLL CLK 25M
input RSTn, //系统复位低电平有效 SYS Reset
input Do_sig, //开始发送信号
input [31:0] fxCnt, //输入信号计数寄存器
input [31:0] fBaseCnt,
input [31:0] DutyCnt,
input [31:0] o_data, //相位差测量数据
output TX_Pin_Out // 连接STM32串口;
);
wire isDone; //tx_module发出了信号
reg rEN = 1'b0; //发送使能
reg [7:0] Data[15:0]; //发送数据缓冲区
reg [5:0] i=6'd0; //Send state声明
reg [7:0] data; //发送给txmodule的数据
tx_module U0_tx
(
.CLK_25M (CLK_25M ),
.RSTn (RSTn ),
.TX_Data (data ),
.TX_En_Sig (rEN ),
.TX_Done_Sig (isDone ),
.TX_Pin_Out (TX_Pin_Out )
);
// 调用txmodule发送测量数据
always@(posedge CLK_25M or posedge Do_sig) //只要25M时钟或者开始发送信号上升沿时
begin
if(Do_sig) //Do_sig等于1时开始执行
begin //将数据全部转移数据到临时表
Data[15] <= DutyCnt [31:24]; //转移数据到临时表
Data[14] <= DutyCnt [23:16]; //Data[15:12] 占空比数据
Data[13] <= DutyCnt [15:8 ];
Data[12] <= DutyCnt [7 :0 ];
Data[11] <= o_data [31:24]; //Data[11: 8]delay data时间间隔数据
Data[10] <= o_data [23:16];
Data[9] <= o_data [15:8 ];
Data[8] <= o_data [7 :0 ];
Data[7] <= fxCnt [31:24]; //Data[7:4]
Data[6] <= fxCnt [23:16];
Data[5] <= fxCnt [15:8 ];
Data[4] <= fxCnt [7 :0 ];
Data[3] <= fBaseCnt [31:24]; //Data[7:4]
Data[2] <= fBaseCnt [23:16];
Data[1] <= fBaseCnt [15:8 ];
Data[0] <= fBaseCnt [7 :0 ]; //8位2进制数
i <= 1'b1; //状态更改发送状态 ,转移完,i=1
end
else
begin
if(rEN == 1'b0 && i>= 1'b1) //当不使能时且i=1时 即将数据全部转移数据到临时表完成后
begin
case(i)//:txmodule启动信号 状态是发送状态
6'd 1 : begin data <= Data[15]; rEN <= 1'b1; i <= i +1'b1; end //
6'd 2 : begin data <= Data[14]; rEN <= 1'b1; i <= i +1'b1; end
6'd 3 : begin data <= Data[13]; rEN <= 1'b1; i <= i +1'b1; end
6'd 4 : begin data <= Data[12]; rEN <= 1'b1; i <= i +1'b1; end
6'd 5 : begin data <= Data[11]; rEN <= 1'b1; i <= i +1'b1; end
6'd 6 : begin data <= Data[10]; rEN <= 1'b1; i <= i +1'b1; end
6'd 7 : begin data <= Data[9 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd 8 : begin data <= Data[8 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd 9 : begin data <= Data[7 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd10 : begin data <= Data[6 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd11 : begin data <= Data[5 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd12 : begin data <= Data[4 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd13 : begin data <= Data[3 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd14 : begin data <= Data[2 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd15 : begin data <= Data[1 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd16 : begin data <= Data[0 ]; rEN <= 1'b1; i <= i +1'b1; end
6'd17 : begin data <= 8'hf ; rEN <= 1'b1; i <= i +1'b1; end
//发送模式验证码,等于测试freq,MCU(stm32)
6'd18 : begin data <= 8'hd ; rEN <= 1'b1; i <= i +1'b1; end
6'd19 : begin data <= 8'ha ; rEN <= 1'b1; i <= i +1'b1; end
6'd20 : i <= 1'b0; //发送完i=0
endcase
end
if(isDone == 1'b1)
begin
rEN <=1'b0; //:确定txmodule启动信号只有一个clk脉冲
end
end
end
endmodule
//Found from the internet, verify OK
module tx_module
(
CLK_25M,
RSTn,
TX_Data,
TX_En_Sig,
TX_Done_Sig,
TX_Pin_Out
);
input CLK_25M;
input RSTn;
input [7:0]TX_Data;//来自top_uartsent
input TX_En_Sig;
output TX_Done_Sig;
output TX_Pin_Out;
/********************************/
wire BPS_CLK;
tx_bps_module U1
(
.CLK_25M( CLK_25M ),
.RSTn( RSTn ),
.Count_Sig( TX_En_Sig ), // input - from U2
.BPS_CLK( BPS_CLK ) // output - to U2
);
/*********************************/
tx_control_module U2
(
.CLK_25M( CLK_25M ),
.RSTn( RSTn ),
.TX_En_Sig( TX_En_Sig ), // input - from top
.TX_Data( TX_Data ), // input - from top
.BPS_CLK( BPS_CLK ), // input - from U2
.TX_Done_Sig( TX_Done_Sig ), // output - to top
.TX_Pin_Out( TX_Pin_Out ) // output - to top
);
/***********************************/
endmodule
//Found from the internet, verify OK
module tx_control_module
(
CLK_25M,
RSTn,
TX_En_Sig, //发送使能信号
TX_Data,
BPS_CLK,
TX_Done_Sig,
TX_Pin_Out
);
input CLK_25M;
input RSTn;
input TX_En_Sig; //发送使能信号
input [7:0]TX_Data;
input BPS_CLK; //时钟 bps-每秒传送位数(bits per second);字节/秒(bytes per second)
output TX_Done_Sig; //发送完成信号
output TX_Pin_Out; //发送引脚
/********************************************************/
reg [3:0]i;
reg rTX;
reg isDone;
always @ ( posedge CLK_25M or negedge RSTn )
begin
if( !RSTn )
begin
i <= 4'd0; //0000
rTX <= 1'b1; //1
isDone <= 1'b0;//0
end
else if( TX_En_Sig ) //发送使能信号
case ( i ) //四位二进制数
4'd0 :
if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b0; end
4'd1, 4'd2, 4'd3, 4'd4, 4'd5, 4'd6, 4'd7, 4'd8 :
if( BPS_CLK ) begin i <= i + 1'b1; rTX <= TX_Data[ i - 1 ]; end
4'd9 :
if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end
4'd10 :
if( BPS_CLK ) begin i <= i + 1'b1; rTX <= 1'b1; end
4'd11 :
if( BPS_CLK ) begin i <= i + 1'b1; isDone <= 1'b1; end
4'd12 :
begin i <= 1'b0; isDone <= 1'b0; end
endcase
end
/********************************************************/
assign TX_Pin_Out = rTX;
assign TX_Done_Sig = isDone;
/*********************************************************/
endmodule
//(国赛fpga)
//时钟 bps-每秒传送位数(bits per second);字节/秒(bytes per second)
//Found from the internet, verify OK
module tx_bps_module
(
CLK_25M,
RSTn,
Count_Sig,
BPS_CLK
);
input CLK_25M;
input RSTn;
input Count_Sig;
output BPS_CLK;
/*************Count_BPS = CLK / wish bps************* */
reg [11:0]Count_BPS; //12位
always @ ( posedge CLK_25M or negedge RSTn )//当25M上升沿到来或者复位
begin
if( !RSTn )
Count_BPS <= 12'd0;
else if( Count_BPS == 12'd2604 ) //25M/2604=9600波特率
//测试暂用
// else if( Count_BPS == 12'd80 ) //25M/2604=9600波特率
Count_BPS <= 12'd0;
else if( Count_Sig) // Count_BPS <= 12'd2604
Count_BPS <= Count_BPS + 1'b1;
else
Count_BPS <= 12'd0;
end
/********************************/
assign BPS_CLK = ( Count_BPS == 12'd1302 ) ? 1'b1 : 1'b0;
/*********************************/
endmodule
顶层文件
//频率测量模块 实例化
mesureFreq U1_mesure_things
(
.CLK_25M (CLK_25M ), //系统时钟,默认25M
.fxA (fxA ), //被测信号--- 来自顶层
.fxB (fxB ), //基准信号--- 来自顶层
.CLK_200M (CLK_200M ), //200M时钟
.Start_sig (Start_sig ), //测量开始信号
.fxCnt (fxCnt ), //被测信号计数个数
.fBaseCnt (fBaseCnt ), //基准信号计数个数
.DutyCnt (DutyCnt ), //占空比计数个数
.DelayCnt (DelayCnt ), //时间间隔计数个数
.Done_sig (Cnt_done_sig), //计数完成信号
.LED (LED ) //LED 到顶层
);
2、STM32部分
串口接收
//串口1中断处理函数
void USART1_IRQHandler(void)
{
unsigned char res;
if(USART1->SR&(1<<5))//接收到数据
{
res=USART1->DR;
if((USART_RX_STA&0x80)==0)//接收未完成
{
if(USART_RX_STA&0x40)//接收到了0x0d
{
if(res!=0x0a)
USART_RX_STA=0;//接收错误,重新开始
else
{
USART_RX_STA|=0x80; //接收完成了
// showhz32str(0,600,"接收完成",BLACK,GREEN);
// printf("%s\r\n",USART_RX_BUF);
}
}
else //还没收到0X0D
{
if(res==0x0d)
{
USART_RX_BUF[USART_RX_STA]=0;
USART_RX_STA|=0x40;
}
else
{
USART_RX_BUF[USART_RX_STA]=res;
USART_RX_STA++;
if(USART_RX_STA>63)
{
USART_RX_STA=0;//接收数据错误,重新开始接收
// showhz32str(0,600,"接收数据错误",BLACK,GREEN);
}
}
}
}
}
}
下图此代码写在main()函数里面
usart.h头文件里面包含 extern char USART_RX_BUF[64]; //接收缓冲,最大64个字节. extern unsigned char USART_RX_STA; //接收状态标记 bit7,接收完成标志 bit6,接收到0x0d bit5~0,接收到的有效字节数目
//进行串口通信接收数据
if(USART_RX_STA & 0x80) //USART_RX_STA=0x80;//接收状态标记 bit7,接收完成标志 bit6,接收到0x0d bit5~0,接收到的有效字节数目
{
count=0;
/****************************************************************************************************/
x=(USART_RX_BUF[8]<<24)+(USART_RX_BUF[9]<<16)+(USART_RX_BUF[10]<<8)+USART_RX_BUF[11];
y=(USART_RX_BUF[12]<<24)+(USART_RX_BUF[13]<<16)+(USART_RX_BUF[14]<<8)+USART_RX_BUF[15];
duty=(USART_RX_BUF[0]<<24)+(USART_RX_BUF[1]<<16)+(USART_RX_BUF[2]<<8)+USART_RX_BUF[3];
/*相位差计数时间*/ delay=(USART_RX_BUF[4]<<24)+(USART_RX_BUF[5]<<16)+(USART_RX_BUF[6]<<8)+USART_RX_BUF[7];
/*****************************************************************************************************/
stm32f103vet6代码
数字式相位测量仪(2)stm32f1工程.zip_stm32与FPGA如何通信,收发数-C代码类资源-CSDN下载