• MCU与FPGA串口通信


    FPGA以9600的波特率向单片机发送32位数据,然后单片机对数据进行解析,显示在显示屏上面

    波特率的产生 : 9600bps是指每秒钟发送9600个bit,即1bit的时间为1/9600,fpga板子自带50M晶振,那么一bit的时间时1/9600/1/50M

            在没有检验位的情况下,每一帧数据是10位 第一位起始位 0 2-9位 数据(低位在前,高位在后),第十位 终止位 1

    FPGA程序思路       : 首先由fpga计数,每隔一段时间产生一个bps_clk,也就是波特率的驱动时钟,发送状态机共分为7个状态

            IDLE : 发送起始标志为   TX_1  : 发送32数据的高八位,其中低位在前,高位在后  ......  STOP  : 终止标志位  STOP_1 : 是专门用来延时的,刚开始没有延时状态

            的情况下,FPGA向单片机发送数据过快,非常占用单片机的中断资源,所以加了一个延时模块 stop ,作用是:每发完一次数据等待100ms然后再发第二次数据,这样的

            单片机就有时间干别的事情了。

    MCU程序思路      :  首先在中断函数里面将FPGA发送过来的数据存到一个数组里面来处理,detect-uart()函数是用来分析数组的,首先检测数组里面的起始标志 ‘t’,如果没有检测到

              终止标志位‘x’的话,对中间数据进行移位处理,还原以前的32位宽的数据,由于在数据传送时有误码的情况,所以在display中加了三级缓存,来减少出错的可能性。

    module    uart_tx(
            //global clock
            input            clk,
            input            rst_n,
            //uart    interface
            output    reg        uart_tx,
            //user    interface
            input    [31:0]    pinlv,
            input            pinlv_value
    );
    
    parameter    BPS_9600 = 5208;
    //parameter    BPS_9600 = 10;
    //count for bps_clk
    reg        [14:0]        cnt_bps_clk;
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_bps_clk <= 1'b0;
        else if(pinlv_value == 0)
            cnt_bps_clk <= 1'b0;
        else if(cnt_bps_clk == BPS_9600 - 1)
            cnt_bps_clk <= 1'b0;
        else
            cnt_bps_clk <= cnt_bps_clk + 1;
    end
    
    reg        [31:0]        cnt_bps_stop;
    wire                stop_done;
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            cnt_bps_stop <= 0;
        else if(state == STOP)
            cnt_bps_stop <= 0;
        else if(cnt_bps_stop > 50_000_00)
            cnt_bps_stop <= 0;
        else
            cnt_bps_stop <= cnt_bps_stop + 1;
    
    end
    assign    stop_done = (cnt_bps_stop == 49_000_00)? 1 : 0;
    //clk for bps
    reg                    bps_clk;
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            bps_clk <= 1'b0;
        else if(cnt_bps_clk == 1)
            bps_clk <= 1'b1;
        else
            bps_clk <= 1'b0;
    end
    //cnt for bps
    reg        [14:0]        bps_cnt;
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            bps_cnt <= 1'b0;
        else if(bps_cnt == 10)
            bps_cnt <= 0;
        else if(bps_clk)
            bps_cnt <= bps_cnt + 1'b1;
        else
            bps_cnt <= bps_cnt;
    end
    
    //tx state
    localparam    IDLE        =    4'd0;
    localparam    TX_1        =    4'd1;
    localparam    TX_2        =    4'd2;
    localparam    TX_3        =    4'd3;
    localparam    TX_4        =    4'd4;
    localparam    STOP        =    4'd5;
    localparam    STOP_1        =    4'd6;
    //cnt state
    reg        [3:0]        state;
    always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            state <= IDLE;
        else if(state == STOP_1 && stop_done)
            state <= IDLE;
        else if(bps_cnt == 10 && (state != STOP_1))
            state <= state + 1;
    end
    
    
    // state
    always @(posedge clk )
    begin
        if(bps_clk)
        begin
            case(state)
            IDLE :   // 't'  di -- gao
            begin
                case(bps_cnt)
                4'd0     : uart_tx <= 0; //begin
                
                4'd1     : uart_tx <= 0;//data
                4'd2     : uart_tx <= 0;
                4'd3     : uart_tx <= 1;
                4'd4     : uart_tx <= 0;
                4'd5     : uart_tx <= 1;
                4'd6    : uart_tx <= 1;
                4'd7     : uart_tx <= 1;
                4'd8     : uart_tx <= 0;
                
                4'd9     : uart_tx <= 1; //stop
                default : uart_tx <= 1;
                endcase
            end
            
            TX_1 : //tx_1byte
            begin
                case(bps_cnt)
                4'd0 : uart_tx <= 0; //begin
                
                4'd1     : uart_tx <= pinlv[24];//data
                4'd2     : uart_tx <= pinlv[25];
                4'd3     : uart_tx <= pinlv[26];
                4'd4     : uart_tx <= pinlv[27];
                4'd5     : uart_tx <= pinlv[28];
                4'd6    : uart_tx <= pinlv[29];
                4'd7     : uart_tx <= pinlv[30];
                4'd8     : uart_tx <= pinlv[31];
                
                4'd9     : uart_tx <= 1; //stop
                default : uart_tx <= 1;
                endcase        
            end
            
            TX_2 : //tx_1byte
            begin
                case(bps_cnt)
                4'd0 : uart_tx <= 0; //begin
                
                4'd1     : uart_tx <= pinlv[16];//data
                4'd2     : uart_tx <= pinlv[17];
                4'd3     : uart_tx <= pinlv[18];
                4'd4     : uart_tx <= pinlv[19];
                4'd5     : uart_tx <= pinlv[20];
                4'd6    : uart_tx <= pinlv[21];
                4'd7     : uart_tx <= pinlv[22];
                4'd8     : uart_tx <= pinlv[23];
                
                4'd9     : uart_tx <= 1; //stop
                default : uart_tx <= 1;
                endcase        
            end    
    
    
            TX_3 : //tx_1byte
            begin
                case(bps_cnt)
                4'd0 : uart_tx <= 0; //begin
                
                4'd1     : uart_tx <= pinlv[8];//data
                4'd2     : uart_tx <= pinlv[9];
                4'd3     : uart_tx <= pinlv[10];
                4'd4     : uart_tx <= pinlv[11];
                4'd5     : uart_tx <= pinlv[12];
                4'd6    : uart_tx <= pinlv[13];
                4'd7     : uart_tx <= pinlv[14];
                4'd8     : uart_tx <= pinlv[15];
                
                4'd9     : uart_tx <= 1; //stop
                default : uart_tx <= 1;
                endcase                
            end    
    
            TX_4 : //tx_1byte
            begin
                case(bps_cnt)
                4'd0 : uart_tx <= 0; //begin
                
                4'd1     : uart_tx <= pinlv[0];//data
                4'd2     : uart_tx <= pinlv[1];
                4'd3     : uart_tx <= pinlv[2];
                4'd4     : uart_tx <= pinlv[3];
                4'd5     : uart_tx <= pinlv[4];
                4'd6    : uart_tx <= pinlv[5];
                4'd7     : uart_tx <= pinlv[6];
                4'd8     : uart_tx <= pinlv[7];
                
                4'd9     : uart_tx <= 1; //stop
                default : uart_tx <= 1;
                endcase                    
            end
            
            STOP :   // 'x'  di -- gao
            begin
                case(bps_cnt)
                4'd0 : uart_tx <= 0; //begin
                
                4'd1     : uart_tx <= 0;//data
                4'd2     : uart_tx <= 0;
                4'd3     : uart_tx <= 0;
                4'd4     : uart_tx <= 1;
                4'd5     : uart_tx <= 1;
                4'd6    : uart_tx <= 1;
                4'd7     : uart_tx <= 1;
                4'd8     : uart_tx <= 0;
                
                4'd9     : uart_tx <= 1; //stop
                default : uart_tx <= 1;
                endcase
            end
            
            STOP_1 :
            begin
                uart_tx <= 1;
            end
            
            default :
                uart_tx <= 1;
            endcase
        end
        else
            uart_tx <= uart_tx;
    
    end
    
    
    
    
    endmodule
    /*************** 用户定义参数 *****************************/
    
    #define MAIN_Fosc        11059200L    //define main clock
    
    #define Baudrate1        9600        //define the baudrate, 如果使用BRT做波特率发生器,则波特率跟串口2一样
                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ
    
    #define Baudrate2        19200        //define the baudrate2,
                                        //12T mode: 600~115200 for 22.1184MHZ, 300~57600 for 11.0592MHZ
    
    #define        BUF_LENTH    20        //定义串口接收缓冲长度
    
    /**********************************************************/
    
    #include    <reg51.h>
    
    sfr AUXR1 = 0xA2;
    sfr    AUXR = 0x8E;
    sfr S2CON = 0x9A;    //12C5A60S2双串口系列
    sfr S2BUF = 0x9B;    //12C5A60S2双串口系列
    sfr IE2   = 0xAF;    //STC12C5A60S2系列
    sfr BRT   = 0x9C;
    
    unsigned char     uart1_wr;        //写指针
    unsigned char     uart1_rd;        //读指针
    unsigned char     xdata RX1_Buffer[BUF_LENTH];
    bit        B_TI;
    
    unsigned char     uart2_wr;        //写指针
    unsigned char     uart2_rd;        //读指针
    unsigned char     xdata RX2_Buffer[BUF_LENTH];
    bit        B_TI2;
    long    temp1 = 0;
    long    temp2 = 0;
    long    temp_buf1 = 0;
    long    temp_buf2 = 0;
    long    temp_buf3 = 0;
    long    temp_buf  = 0;
    long    ce = 9999;
    /****************** 编译器自动生成,用户请勿修改 ************************************/
    
    #define T1_TimerReload    (256 - MAIN_Fosc / 192 / Baudrate1)            //Calculate the timer1 reload value    at 12T mode
    #define BRT_Reload        (256 - MAIN_Fosc / 12 / 16 / Baudrate2)        //Calculate BRT reload value
    
    #define    TimeOut1        (28800 / (unsigned long)Baudrate1 + 2)
    #define    TimeOut2        (28800 / (unsigned long)Baudrate2 + 2)
    
    #define    TI2                (S2CON & 0x02) != 0
    #define    RI2                (S2CON & 0x01) != 0
    #define    CLR_TI2()        S2CON &= ~0x02
    #define    CLR_RI2()        S2CON &= ~0x01
    
    /**********************************************************/
    
    /******************** 本地函数声明 ***************/
    void    uart1_init(void);
    
    void    UART1_TxByte(unsigned char dat);
    
    void    PrintString1(unsigned char code *puts);
    
    void delay(char x)
    {
        char i = 0;
        char t= 0;
        for(i = 0;i<110;i++)
        {
            for(t = 0;t < x;t++);
        }
    }
    
    void detect_uart()
    {
        char i = 0;
        char flag = 0;
        temp1 = 0;
        for(i = 0;i <= uart1_wr ; i++)
        {
        //    UART1_TxByte(RX1_Buffer[i]);    
            if(flag)
            {
                if(RX1_Buffer[i] != 'x' )
                {
                    temp1 = temp1 << 8 ;
                    temp1 = temp1 + RX1_Buffer[i];
        //            UART1_TxByte(RX1_Buffer[i]);
                }     
                else
                    temp2 = temp1;
            }
            if(RX1_Buffer[i] == 't')
            {
                flag = 1;
            }
        }
    }
    
    //void ceshi()
    //{
    //    ce = 0;
    //    ce = ce << 8 ;
    //    ce = ce + 0xff;
    //    ce = ce    << 8 ;
    //    ce = ce + 0x0c;
    //    ce = ce << 8 ;
    //    ce = ce + 0xcc;
    //    ce = ce    << 8 ;
    //    ce = ce + 0xcc;
    ////    ce = 9999;
    //}
    
    void display()
    {
        char flag = 0;
        temp_buf3 = temp_buf2;
        temp_buf2 = temp_buf1;
         temp_buf1 = temp2;
        if(temp_buf3 == temp2)
        {
            temp_buf = temp2;
        }
        else
        {
            temp_buf = temp_buf;
        }
        UART1_TxByte('S');UART1_TxByte(' ');UART1_TxByte(' ');UART1_TxByte(' ');UART1_TxByte(' ');
        if(temp_buf/100000000 == 0) //bai M
        {
            UART1_TxByte(' ');        
        }
        else
        {
            UART1_TxByte(temp_buf/100000000 + 0x30);
            flag  = 1;    
        }
    
        if(temp_buf/10000000%10 == 0 )    //shi M
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }    
        }    
        else
        {
             UART1_TxByte(temp_buf/10000000%10 + 0x30);
            flag = 1;
        }
    
        if(temp_buf/1000000%10 == 0 )  //M
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }        
        }
        else
        {
             UART1_TxByte(temp_buf/1000000%10 + 0x30);
            flag = 1;    
        }
    
        if(temp_buf/100000%10 == 0 )  //bai K
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }        
        }
        else
        {
             UART1_TxByte(temp_buf/100000%10 + 0x30);
            flag = 1;    
        }
    
        if(temp_buf/10000%10 == 0 )  //shi k
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }        
        }
        else
        {
             UART1_TxByte(temp_buf/10000%10 + 0x30);
            flag = 1;    
        }
    
        if(temp_buf/1000%10 == 0 )  // K
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }        
        }
        else
        {
             UART1_TxByte(temp_buf/1000%10 + 0x30);
            flag = 1;    
        }
    
        if(temp_buf/100%10 == 0 )  //bai 
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }        
        }
        else
        {
             UART1_TxByte(temp_buf/100%10 + 0x30);
            flag = 1;    
        }
    
        if(temp_buf/10%10 == 0 )  //shi
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }        
        }
        else
        {
             UART1_TxByte(temp_buf/10%10 + 0x30);
            flag = 1;    
        }
    
        if(temp_buf%10 == 0 )  //ge
        {
            if(!flag)
            {
                UART1_TxByte(' ');
            }
            else
            {
                 UART1_TxByte(0x30);
            }        
        }
        else
        {
             UART1_TxByte(temp_buf%10 + 0x30);
            flag = 1;    
        }
    
    }
    
    
    void    main(void)
    {
        char i = 0;
        uart1_rd = 0;
        uart1_wr = 0;
        uart2_rd = 0;
        uart2_wr = 0;
    
    //    AUXR |=  0x01;        //串口1使用独立波特率发生器, 波特率跟串口2一样
        AUXR1 |= (1<<4);    //将UART2从P1口切换到 RXD2--P1.2切换到P4.2   TXD2---P1.3切换到P4.3
        
        uart1_init();
    
        PrintString1("串口1测试程序");
        
        while(1)
        {
            display();
            detect_uart();
        }
    }
    
    void    UART1_TxByte(unsigned char dat)
    {
        B_TI = 0;
        SBUF = dat;
        while(!B_TI);
        B_TI = 0;
        delay(10);
    }
    
    
    void PrintString1(unsigned char code *puts)        //发送一串字符串
    {
        for (; *puts != 0;    puts++)  UART1_TxByte(*puts);     //遇到停止符0结束
    }
    
    
    
    
    void    uart1_init(void)
    {
        PCON |= 0x80;        //UART0 Double Rate Enable
        SCON = 0x50;        //UART0 set as 10bit , UART0 RX enable
        TMOD &= ~(1<<6);        //Timer1 Set as Timer, 12T
        TMOD = (TMOD & ~0x30) | 0x20;    //Timer1 set as 8 bits auto relaod
        TH1 = T1_TimerReload;        //Load the timer
        TR1  = 1;
        ES  = 1;
        EA = 1;
    }
    
    
    
    /**********************************************/
    void UART0_RCV (void) interrupt 4
    {
    
        if(RI)
        {
            RI = 0;
            RX1_Buffer[uart1_wr] = SBUF;
            if(++uart1_wr >= BUF_LENTH)    uart1_wr = 0;
        }
    
        if(TI)
        {
            TI = 0;
            B_TI = 1;
        }
    }
  • 相关阅读:
    用Tinkercad学arduino之 LCD电压电流表
    用Tinkercad学arduino之 L293D电机驱动器驱动直流电机
    用Tinkercad学arduino之 74HC595 寄存器控制1位7段数码管
    用Tinkercad学arduino之 74HC595寄存器控制8个led跑马灯
    用Tinkercad学arduino之 红外遥控器
    用Tinkercad学arduino之 人体红外检测报警 LCD显示
    用Tinkercad学arduino之 人体红外检测报警 蜂鸣器+LED
    用Tinkercad学arduino之 电位器控制伺服电机转向
    用Tinkercad学arduino之 光线控制彩灯
    用Tinkercad学arduino之 温度LED报警
  • 原文地址:https://www.cnblogs.com/bixiaopengblog/p/6878909.html
Copyright © 2020-2023  润新知