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中加了三级缓存,来减少出错的可能性。

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
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
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
/*************** 用戶定義參數 *****************************/

#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;
    }
}