• 【iCore1S 双核心板_FPGA】例程十五:基于I2C的ARM与FPGA通信实验


    实验现象:

     

    核心代码:

    int main(void)
    {
        int i,n;
        char buffer[20];
        char i2c_buffer[20];
        
      HAL_Init();
      system_clock.initialize();
    
        led.initialize();
      usart1.initialize(115200);
        i2c.initialize();
        
    
        usart1.printf("Hello! I am iCore1S!
    ");        //´®¿Ú1Êä³ö
        while(1)
            {
            if(usart1.receive_ok_flag)
                {                                           //½ÓÊÕÍê³É
                    usart1.receive_ok_flag = 0;
                    for(i = 0;i < 20;i++)
                    {
                        buffer[i] = tolower(usart1.receive_buffer[i]);
                    }
                n = strlen(buffer);
                //±È½Ï½ÓÊÕÐÅÏ¢
                if(memcmp(buffer,"ledr",strlen("ledr")) == 0)
                    {
                        //ºìÉ«LEDµãÁÁ
                        LED_RED_ON;
                        LED_GREEN_OFF;
                        LED_BLUE_OFF;
                    }
                if(memcmp(buffer,"ledg",strlen("ledg")) == 0)
                    {
                        //ÂÌÉ«LEDµãÁÁ
                        LED_RED_OFF;
                        LED_GREEN_ON;
                        LED_BLUE_OFF;
                    }    
                if(memcmp(buffer,"ledb",strlen("ledb")) == 0)
                    {
                        //À¶É«LEDµãÁÁ
                        LED_RED_OFF;
                        LED_GREEN_OFF;
                        LED_BLUE_ON;
                    }    
                buffer[4]=13;//Ìí¼Ó½áÊøλ
                n=strlen(buffer);
                i2c.write_nbyte(0x03,0x8F,buffer,n);        //i2c·¢ËÍÊý¾Ý
                for(i=0;i<100;i++);
                i2c.read_nbyte(0x03,0x0F,i2c_buffer,0x06);
                usart1.printf("%s
    ",i2c_buffer);//´®¿Ú1Êä³ö½ÓÊÕµ½µÄÊý¾Ý
            }
        }
    }
    module I2C(
        input CLK_12M,
        input SCL,
        inout SDA,
        output FPGA_LEDR,
        output FPGA_LEDG,
        output FPGA_LEDB    
    );
    //-------------------------rst_n----------------------------//
        reg rst_n;
        reg [3:0]cnt_rst;
        
        always@(posedge CLK_12M)
            begin
                if(cnt_rst==4'd10)
                    begin
                        rst_n <= 1'd1;
                        cnt_rst <= 4'd10;
                    end
                else cnt_rst <= cnt_rst + 1'd1;
            end
        
    //-------------------------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};
                     
    //---------------------------address------------------------//    
        reg [7:0]device_address,word_address;
        reg [4:0]m;
        
        always@(posedge SCL or negedge rst_n)
            begin
                if(!rst_n)
                    begin
                        device_address <= 8'd0;
                        word_address <= 8'd0;
                        m <= 5'd0;
                        tx_en <= 1'd0;
                        rx_en <= 1'd0;
                    end
                else 
                    begin
                        case(m)
                            5'd0,5'd1,5'd2,5'd3,5'd4,5'd5,5'd6,5'd7:    //接收8位地址
                                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(tx_ack || rx_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;
                                            device_address <= 8'hff;
                                            word_address <= 8'd0;
                                        end
                                    else if(word_address == 8'h0f)//判断发送命令
                                        begin
                                            tx_en <= 1'd1;
                                            word_address <= 8'd0;
                                        end
                                    else if(tx_ack)
                                        begin
                                            tx_en <= 1'd0;
                                            m <= 5'd0;
                                        end
                                    else if(rx_ack)
                                        begin
                                            rx_en <= 1'd0;
                                            m <= 5'd0;
                                        end
                                    else m <= 5'd17;
                                end
                            5'd18:
                                begin
                                    m <= 5'd0;
                                end
                        endcase
                    end            
            end
    //-----------------------------rx---------------------------//
        //接收数据
        reg [63:0]data_in;
        reg [63:0]data;
        reg [4:0]i;
        reg rx_en;
        reg rx_ack;
        
        always@(posedge SCL or negedge rst_n)
            begin
                if(!rst_n)
                    begin
                        data_in <= 64'd0;
                        data <= 64'd0;
                        i <= 5'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://接收8位数据
                                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 i <= 5'd0;
                                end
                            5'd9:
                                begin
                                    i <= 5'd0;
                                    rx_ack <= 1'd0;
                                end
                            default:
                                begin
                                    i <= 5'd0;
                                end
                        endcase
                    end
            end
            
    //----------------------------data--------------------------//
        //对比接收数据
        reg [2:0]led;
        
        always@(posedge CLK_12M or negedge rst_n)
            begin
                if(!rst_n)
                    begin
                        led <= 3'b111;
                    end
                else 
                    begin
                        case(data[39:0])
                            ledr:    led <= 3'b011;//红灯亮
                            ledg: led <= 3'b101;//绿灯亮
                            ledb: led <= 3'b110;//蓝灯亮
                            default:led <= 3'b111;//都不亮    
                        endcase
                    end
            end
        
        assign {FPGA_LEDR,FPGA_LEDG,FPGA_LEDB} = led;
        
    //-----------------------------tx---------------------------//
        //发送数据
        reg [47:0]data_out;
        reg [3:0]j;
        reg [2:0]tx_cnt;
        reg tx_ack;
        reg tx_en;
        reg sda;
        
        always@(posedge SCL or negedge rst_n)
            begin
                if(!rst_n)
                    begin
                        data_out <= GINGKO;
                        j <= 4'd0;
                        tx_ack <= 1'd0;
                        tx_cnt <= 3'd0;
                        sda <= 1'd1;
                    end
                else 
                    begin
                        case(j)
                            4'd0,4'd1,4'd2,4'd3,4'd4,4'd5,4'd6,4'd7://发送8位书籍
                                begin
                                    if(tx_en)
                                        begin
                                            j <= j + 1'd1;
                                            {sda,data_out[47:1]} <= data_out;
                                            tx_ack <= 1'd0;
                                        end
                                end
                            4'd8:
                                begin //发送6次,8位数据(GINGKO)
                                    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_cnt <= tx_cnt + 1'd1;
                                            tx_ack <= 1'd0;
                                        end
                                end
                            4'd9:
                                begin
                                    j <= 4'd0;
                                    tx_ack <= 1'd0;
                                    data_out <= GINGKO;
                                end
                            default:
                                begin
                                    j <= 4'd0;
                                    tx_ack <= 1'd0;
                                    data_out <= GINGKO;
                                end
                        endcase
                    end
            end
            
        assign SDA = (j>=4'd1 && j<=4'd8)? sda : 1'dz;
        
    //--------------------------endmodule-----------------------//
    endmodule 

    实验方法及指导书:

    链接:http://pan.baidu.com/s/1hs8ErAW 密码:wven

  • 相关阅读:
    Crystal Reports基础知识
    Dashboard与中国式报表的区别以及常见的Dashboard控件
    函数总结
    SQL Server 索引使用入门
    Linux+C 开发基础
    vi 开发环境~~转载
    linux mysql 基础操作使用
    sourceinsight 快捷键 转帖
    vi 利器
    fedora 7 英文环境 的汉字显示
  • 原文地址:https://www.cnblogs.com/xiaomagee/p/7590393.html
Copyright © 2020-2023  润新知