UART串口收发协议以及时序分析
0赞UART串口收发协议以及时序分析
/**************************************************************************
.......IDLE.Start................................UART DATA..................................End...IDLE...
________ ______________
|____< D0 >< D1 >< D2 >< D3 >< D4 >< D5 >< D6 >< D7 >
Bit0 Bit1 Bit2 Bit3 Bit4 Bit5 Bit6 Bit7 Bit08 Bit9
**************************************************************************/
1. 任意分频实现精确波特率
详见:http://blog.chinaaet.com/detail/21535.html
\发送&接收数据时序图
2. 串口数据接收时序分析:
(1)状态机:R_IDLE; R_START; R_SAMPLE; R_STOP
//--------------------------------------- //parameter of uart transfer localparam R_IDLE = 2'd0; //detect if the uart data is begin localparam R_START = 2'd1; //uart transfert start mark bit localparam R_SAMPLE = 2'd2; //uart 8 bit data receive localparam R_STOP = 2'd3; //uart transfer stop mark bit reg [1:0] rxd_state;
(2)数据采样在smp_cnt==7即数据中点!
//---------------------------------- //uart data receive in center point reg [7:0] rxd_data_r; always@(posedge clk or negedge rst_n) begin if(!rst_n) rxd_data_r <= 0; else if(rxd_state == R_SAMPLE) begin if(clken_16bps == 1 && smp_cnt == 4'd7) //sample center point case(rxd_cnt) 4'd1: rxd_data_r[0] <= rxd_sync; 4'd2: rxd_data_r[1] <= rxd_sync; 4'd3: rxd_data_r[2] <= rxd_sync; 4'd4: rxd_data_r[3] <= rxd_sync; 4'd5: rxd_data_r[4] <= rxd_sync; 4'd6: rxd_data_r[5] <= rxd_sync; 4'd7: rxd_data_r[6] <= rxd_sync; 4'd8: rxd_data_r[7] <= rxd_sync; default:; endcase else rxd_data_r <= rxd_data_r; end else if(rxd_state == R_STOP) rxd_data_r <= rxd_data_r; else rxd_data_r <= 0; end
(3)接收完停止标志位后:rxd_flag有效,以及rxd_data更新!
//---------------------------------- //update uart receive data and receive flag signal always@(posedge clk or negedge rst_n) begin if(!rst_n) rxd_data <= 0; else if(clken_16bps == 1 && rxd_cnt == 4'd9 && smp_cnt == 4'd15) //Start + 8 Bit + Stop Bit rxd_data <= rxd_data_r; else rxd_data <= rxd_data; end always@(posedge clk or negedge rst_n) begin if(!rst_n) rxd_flag <= 0; else if(clken_16bps == 1 && rxd_cnt == 4'd9 && smp_cnt == 4'd15) //Start + 8 Bit + Stop Bit rxd_flag <= 1; else rxd_flag <= 0; end
3. 串口数据发送时序分析:
(1)状态机:R_IDLE; R_SEND(R_SEND发送起始位,数据位,结束位)
//--------------------------------------- //parameter of uart transfer localparam T_IDLE = 2'b0; //test the flag to transfer data localparam T_SEND = 2'b1; //uart transfer data reg [1:0] txd_state;
(2)数据与rxd_cnt:0-9完全对齐,因此采用了组合逻辑输出,如下:
//-------------------------------------- //uart 8 bit data transfer always@(*) begin if(txd_state == T_SEND) case(txd_cnt) 4'd0: txd = 0; 4'd1: txd = txd_data[0]; 4'd2: txd = txd_data[1]; 4'd3: txd = txd_data[2]; 4'd4: txd = txd_data[3]; 4'd5: txd = txd_data[4]; 4'd6: txd = txd_data[5]; 4'd7: txd = txd_data[6]; 4'd8: txd = txd_data[7]; 4'd9: txd = 1; default:txd = 1; endcase else txd = 1'b1; //default state end
(3)在发送完停止位后:txd_flag有效!
//------------------------------------- //Capture the falling of data transfer over always@(posedge clk or negedge rst_n) begin if(!rst_n) txd_flag <= 0; else if(clken_16bps == 1 && txd_cnt == 4'd9 && smp_cnt == 4'd15) //Totally 8 data is done txd_flag <= 1; else txd_flag <= 0; end
4. 其他
(1)串口收发海量测试:
(2)收发同步时序绝对对齐,即第二个数据接受完毕的同时,第一个数据发送完毕,保持完全的滞后同步!
(3)串口软件问题:
在发送字符串或者HEX长度太长的时候会出现错误,尤其是自动发送10ms,10ms时候的错误很明显,纯属软件问题!
后期可以通过自行设计软件来完善,目前手动发送调试即可!
(4)很神奇的是115200的波特率但是9600竟然可以发送成功!