实验现象:
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链接: