STM32
直播中

李星童

7年用户 992经验值
私信 关注
[问答]

怎样去解决stm32和FPGA串口通信的问题呢

如何去实现STM32f1的串口接收程序呢?
怎样去解决stm32和FPGA串口通信的问题呢?

回帖(2)

郝汉

2021-12-6 14:42:15
最近在做低频数字式相位测量仪,很多人都是卡在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
举报

高敏兰

2021-12-6 14:42:18
//(国赛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("%srn",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];
/*****************************************************************************************************/
举报

更多回帖

发帖
×
20
完善资料,
赚取积分