zoukankan      html  css  js  c++  java
  • 【iCore4 双核心板_FPGA】例程十四:基于I2C的ARM与FPGA通信实验

    实验现象:

    1、先烧写ARM程序,然后烧写FPGA程序。

    2、打开串口精灵,通过串口精灵给ARM发送数据从而给FPGA发送数据 ,会接收到字符GINGKO。

    3、通过串口精灵发送命令可以控制ARM·LED和FPGA·LED。

    命令格式
    LEDRCRLF ARM·LED、FPGA·LED亮
    LEDGCRLF ARM·LED、FPGA·LED亮
    LEDBCRLF ARM·LED、FPGA·LED亮

    核心代码:

    int main(void)
    {
    
      /* USER CODE BEGIN 1 */
        int i;
        char buffer[20];
        char i2c_buffer[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();
    
      /* USER CODE BEGIN 2 */
        i2c.initialize();
        usart6.initialize(115200);
        usart6.printf("Hello,I am iCore4!
    ");
        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){        //±È½Ï½ÓÊÕÊý¾Ý
                    LED_RED_ON;
                    LED_GREEN_OFF;
                    LED_BLUE_OFF;
                    i2c.write_nbyte(0x03,0X8F,buffer,strlen(buffer));   //i2c×ÜÏß·¢ËÍÊý¾Ý
                }
                if(memcmp(buffer,"ledg",strlen("ledg")) == 0){
                    LED_RED_OFF;
                    LED_GREEN_ON;
                    LED_BLUE_OFF;
                    i2c.write_nbyte(0x03,0X8F,buffer,strlen(buffer));
                }
                if(memcmp(buffer,"ledb",strlen("ledb")) == 0){
                    LED_RED_OFF;
                    LED_GREEN_OFF;
                    LED_BLUE_ON;
                    i2c.write_nbyte(0x03,0X8F,buffer,strlen(buffer));
                }        
                for(i = 0; i < 1000; i ++);
                i2c.read_nbyte(0x02,0x0F,i2c_buffer,0x06);            //i2c×ÜÏß½ÓÊÕÊý¾Ý
                usart6.printf(i2c_buffer);            
            }
      }
      /* USER CODE END 3 */
    
    }
    module i2c_ctrl(
        input clk_25m,
        input rst_n,
        input scl,
        inout sda,
        output led_red,
        output led_green,
        output led_blue    
    );
    
    //---------------------------parameter--------------------------//
    parameter ledr = {8'd108,8'd101,8'd100,8'd114,8'd13},
                 ledg = {8'd108,8'd101,8'd100,8'd103,8'd13},
                 ledb = {8'd108,8'd101,8'd100,8'd98,8'd13},
                 GINGKO = {8'd71,8'd73,8'd78,8'd71,8'd75,8'd79},
                 wide = 6'd40;
    
    //-----------------------------address--------------------------//                                                                                    
    reg[4:0]m;
    reg[7:0]device_address,word_address;                           //接收地址先传输高位
    
    always@(posedge scl or negedge rst_n)
        if(!rst_n)
            begin
                m <= 5'd0;
                device_address <= 8'd0;
                word_address <= 8'd0;
                tx_en <= 1'd0;
                tx_en <= 1'd0;
            end
        else case(m)
                5'd0,5'd1,5'd2,5'd3,5'd4,5'd5,5'd6,5'd7:                    //接收设备地址
                    begin
                        if(!rx_en || !tx_en)
                            begin
                                m <= m + 1'd1;
                                device_address <= {device_address[6:0],sda};
                            end
                        else m <= 5'd0;
                    end
                5'd8:
                    begin
                        if(device_address == 8'd3 || device_address == 8'd2)
                            begin
                                m <= 5'd9;
                                device_address <= 8'd0;
                            end
                        else if(rx_ack || tx_ack)
                            begin
                                m <= 5'd18;
                                device_address <= 8'd0;
                            end
                        else
                            begin
                                m <= 5'd0;
                            end
                    end
                5'd9,5'd10,5'd11,5'd12,5'd13,5'd14,5'd15,5'd16:            //接收寄存器地址,以寄存器地址区分读写操作
                    begin
                        m <= m + 1'd1;
                        word_address <= {word_address[6:0],sda};
                    end
                5'd17:
                    begin
                        if(word_address == 8'h8f)                                //使能接收数据
                            begin
                                rx_en <= 1'd1;
                                word_address <= 8'd0;
                            end
                        else if(word_address == 8'h0f)                         //使能发送数据
                            begin
                                tx_en <= 1'd1;
                                word_address <= 8'd0;
                            end
                        else if(rx_ack)
                            begin
                                rx_en <= 1'd0;
                                m <= 5'd0;
                            end
                        else if(tx_ack)
                            begin
                                tx_en <= 1'd0;
                                m <= 5'd18;
                            end
                        else m <= 5'd17;
                    end
                5'd18:begin
                            m <= 5'd0;
                        end
                endcase        
        
    //-------------------------------rx---------------------------//        
    /*接收数据*/
    reg[63:0]data_in;
    reg[63:0]data;
    reg[4:0]i;
    reg tx_en,rx_en;
    reg rx_ack;
    
    always@(posedge scl or negedge rst_n)
        if(!rst_n)
            begin
                i <= 5'd0;
                data <= 64'd0;
                data_in <= 64'd0;
                rx_ack <= 1'd0;
            end
        else if(rx_en)
            begin
                case(i)
                    5'd0,5'd1,5'd2,5'd3,5'd4,5'd5,5'd6,5'd7:        //移位完成数据接收
                        begin
                            i <= i + 1'd1;
                            rx_ack <= 1'd0;
                            data_in <= {data_in[62:0],sda};
                        end
                    5'd8:
                        begin
                            if(data_in[7:0] == 8'h0d)
                                begin
                                    i <= 5'd9;
                                    rx_ack <= 1'd1;
                                    data <= data_in;
                                end
                            else
                                begin
                                    i <= 5'd0;
                                end
                        end
                    5'd9:begin
                            rx_ack <= 1'd0;
                            i <= 5'd0;
                          end
                    default:i <= 5'd0;
                endcase
            end    
        
    //-----------------------------data-------------------------//        
    /*比较接收数据*/
    reg [2:0]led;    
    always@(posedge clk_25m or negedge rst_n)
        if(!rst_n)
            begin
                led <= 3'b101;
            end
        else if (data[wide-1:0] == ledr)
                led <= 3'b011;
        else if (data[wide-1:0] == ledg)
                led <= 3'b101;
        else if (data[wide-1:0] == ledb)
                led <= 3'b110;    
                
    assign {led_red,led_green,led_blue} = led;    
        
    //----------------------------tx--------------------------//        //发送数据   先传输高位
    reg[47:0]data_out;
    reg[3:0]j;
    reg send_data;
    reg tx_ack;
    reg[2:0]tx_cnt;
    always@(negedge scl or negedge rst_n)
        if(!rst_n)
            begin
                j <= 4'd0;
                send_data <= 1'd1;
                tx_ack <= 1'd0;
                tx_cnt <= 3'd0;
                data_out <= GINGKO;
            end
        else case(j)
                    4'd0,4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7:        //移位输出数据
                        begin
                            if(tx_en)
                                begin
                                    j <= j + 1'd1;
                                    {send_data,data_out[47:1]} <= data_out;
                                    tx_ack <= 1'd0;
                                end
                        end
                    4'd8:begin
                            if(tx_cnt == 3'd5)                            //判断最后一个字节,停止发送
                                begin
                                    j <= j + 1'd1;
                                    tx_ack <= 1'd1;
                                    tx_cnt <= 3'd0;
                                end
                            else 
                                begin
                                    j <= 4'd0;
                                    tx_ack <= 1'd0;    
                                    tx_cnt <= tx_cnt + 1'd1;
                                end
                        end 
                    4'd9:begin
                                j <= 4'd0;
                                tx_ack <= 1'd0;
                                data_out <= GINGKO;
                        end
                    4'd10:begin
                                j <= 4'd0;
                                tx_ack <= 1'd0;
                            end
                endcase    
    
    assign sda = (j >= 4'd1 && j <= 4'd8) ? send_data : 1'dz;
                
    endmodule

    源代码下载链接:

    链接:http://pan.baidu.com/s/1geWgggF 密码:an3s

    iCore4链接:

  • 相关阅读:
    字符串拼接练习
    java数字字符的全半角转化
    mysql 的group by 满足的规则要求:
    从指定字符串获取n个随机数
    jQuery去除空格的$.trim()
    mysql里的位运算小结
    sql的case 用法
    泛型之元组示例
    jQuery里的replaceAll和replaceWith
    根据索引条件查询结果与原表关联的查询
  • 原文地址:https://www.cnblogs.com/xiaomagee/p/7524408.html
Copyright © 2011-2022 走看看