【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!\r\n"); //´®¿Ú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\n",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