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