實驗現象:
1、先燒寫ARM程式,然後燒寫FPGA程式。
2、開啟串列埠精靈,通過串列埠精靈給ARM傳送資料從而給FPGA傳送資料 ,會接收到字元GINGKO。
3、通過串列埠精靈傳送命令可以控制ARM·LED和FPGA·LED。
命令格式
LEDR\CR\LF ARM·LED、FPGA·LED亮
LEDG\CR\LF ARM·LED、FPGA·LED亮
LEDB\CR\LF 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!\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){ //±È½Ï½ÓÊÕÊý¾Ý 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連結: