【iCore4 雙核心板_FPGA】例程十二:基於UART的ARM與FPGA通訊實驗

XiaomaGee發表於2017-09-14

實驗現象:

1、先燒寫ARM程式,然後燒寫FPGA程式。

2、開啟串列埠精靈,會接收到字元GINGKO。

3、通過串列埠精靈傳送命令可以控制ARM·LED和FPGA·LED。

核心程式碼:

int main(void)
{

  /* USER CODE BEGIN 1 */
    int i;
    char buffer[20];
    char buffer1[20];
    
  /* USER CODE END 1 */

  /* MCU Configuration----------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART6_UART_Init();
  MX_UART4_Init();

  /* USER CODE BEGIN 2 */
    uart4.initialize(115200);
    usart6.initialize(115200);
    usart6.printf("Hello,I am iCore4!\r\n");
    LED_GREEN_ON;
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */
        if(usart6.receive_ok_flag == 1){
            usart6.receive_ok_flag = 0;
            for(i = 0;i < 20;i ++){
                buffer[i] = tolower(usart6.receive_buffer[i]);
            }
            //±È½Ï½ÓÊÕÐÅÏ¢
            if(memcmp(buffer,"ledr",strlen("ledr")) == 0){                //ARMºìµÆÁÁ       
                LED_RED_ON;
                LED_GREEN_OFF;
                LED_BLUE_OFF;
                uart4.printf("LEDR\n");                                    //´®¿Ú2Êä³ö
            }
            if(memcmp(buffer,"ledg",strlen("ledg")) == 0){               //ARMÂ̵ÆÁÁ 
                LED_GREEN_ON;
                LED_RED_OFF;
                LED_BLUE_OFF;
                uart4.printf("LEDG\n");                                    //´®¿Ú2Êä³ö
            }    
            if(memcmp(buffer,"ledb",strlen("ledb")) == 0){               //ARMÀ¶µÆÁÁ
                LED_BLUE_ON;
                LED_GREEN_OFF;
                LED_RED_OFF;
                uart4.printf("LEDB\n");                                    //´®¿Ú2Êä³ö        
            }        
        }
        if (uart4.receive_ok_flag){                                    //´®¿Ú2½ÓÊÕÍê³É
                uart4.receive_ok_flag = 0;
                for(i = 0;i < 20;i++){
                buffer1[i] = uart4.receive_buffer[i];
            }
                usart6.printf(buffer1);                                      //´®¿Ú4Êä³ö
        }        
    }
  /* USER CODE END 3 */

}
module txd_rxd(
    input rst_n,
    input uart_clk,
    input rx,
    output tx,
    output led_red,
    output led_green,
    output led_blue
);
//---------------------------parameter--------------------------//
parameter ledr = 40'b01001100_01000101_01000100_01010010_00001010,
             ledg = 40'b01001100_01000101_01000100_01000111_00001010,
             ledb = 40'b01001100_01000101_01000100_01000010_00001010;

//---------------------------------rx---------------------------//
/* 接收模組 */
reg[3:0]j;
reg[7:0]data_in;
reg [39:0]receive_data,data_inr;

always@(posedge uart_clk or negedge rst_n)
    if(!rst_n)
        begin
            j <= 4'd0;
            data_in <= 8'd0;
            data_inr <= 40'd0;
            receive_data <= 40'd0;
        end
    else case(j)
            4'd0:                                                    //判斷起始標誌
                begin
                    if(!rx)           
                        begin
                            data_in <= 8'd0;
                            j <= j + 1'd1;
                        end
                    else j <= j;
                end
            4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7,4'd8:                //接收資料
                begin
                    j <= j + 1'd1;
                    data_in <= {rx,data_in[7:1]};
                end
            4'd9:                                                   //接收校驗位
                begin
                    receive_data <= {receive_data[31:0],data_in};
                    j <= j + 1'd1;
                end
            4'd10:                                                             //接收停止位
                begin
                    j <= 1'd0;
                    if(receive_data[7:0] == 8'b00001010)
                        begin
                            data_inr <= receive_data;
                        end
                end
            default: j <= 4'd0;
    endcase    

//---------------------------------led---------------------------//
/*對比接收資料 */
reg [2:0]led;        

always@(posedge uart_clk or negedge rst_n)
    if(!rst_n)
        begin
            led <= 3'b101;
        end
    else if (data_inr == ledr)                  
            led <= 3'b011;
    else if (data_inr == ledg)
            led <= 3'b101;
    else if (data_inr == ledb)
            led <= 3'b110;    
    
assign {led_red,led_green,led_blue} = led;

//---------------------------------tx---------------------------//

/*傳送模組,定時傳送GINGKO*/
reg tx_r;                                                                                  //序列傳送資料的暫存器,空閒狀態預設為1
reg[16:0]i;
reg[7:0]data_out;
reg[3:0]cnt;
reg[63:0]GINGKO;

always @(posedge uart_clk or negedge rst_n)
    if (!rst_n)
        begin
            i <= 17'd0;
            tx_r <= 1'd1;                                                                 //空閒狀態為1
            cnt <= 4'd0;
            data_out <= 8'd0;
            GINGKO <= {8'd71,8'd73,8'd78,8'd71,8'd75,8'd79,8'd13,8'd10};
        end
    else                                                                                      //開始傳送DATA
        case(i)
            17'd0: begin                                                                 //先傳送起始位0
                        i <= i + 1'd1;
                        {data_out,GINGKO[63:8]} <= GINGKO;
                        tx_r <= 1'd0;                                                    
                    end
            17'd1,14'd2,14'd3,14'd4,14'd5,14'd6,14'd7,14'd8:                 //tx_r
                    begin
                        i <= i + 1'd1;
                        {data_out[6:0],tx_r} <= data_out;                          //串列埠傳送時,低位在先
                    end                                
            17'd9: begin                                                                 //1位奇偶校驗位和1位停止位
                        i <= i + 1'd1;
                        tx_r <= 1'd1;                                      
                    end
            17'd10: begin                                                                 //1位停止位
                        if(cnt == 4'd7)
                            begin
                                i <= i + 1'd1;
                                cnt <= 4'd0;
                            end
                        else 
                            begin
                                i <= 14'd0;
                                cnt <= cnt + 1'd1;
                            end
                    end
            17'd115200: begin                                                            //定時約為1s                
                            i <= 14'd0;
                            GINGKO <= {8'd71,8'd73,8'd78,8'd71,8'd75,8'd79,8'd13,8'd10};
                    end
            default: i <= i + 1'd1;                                                  //i為其他無效數值時,直接轉到退出TXD模組狀態
        endcase

assign tx = tx_r;    

endmodule

原始碼下載連結:

連結:http://pan.baidu.com/s/1nv836RZ 密碼:iky7

iCore4連結:

相關文章