IO扩展是个好东西, 占用资源少. 适合用在响应要求不高的场合.
PCF8575最大的好处是有个中断反馈引脚, 方便读取状态.
下面直接上代码.
Vivado中的配置.
XDC文件的配置
set_property -dict {PACKAGE_PIN L14 IOSTANDARD LVCMOS33} [get_ports IIC_0_scl_io]
set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS33} [get_ports IIC_0_sda_io]
set_property PULLUP true [get_ports IIC_0_scl_io]
set_property PULLUP true [get_ports IIC_0_sda_io]
SDK中的代码.
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
//#include "sleep.h"
#include "xparameters.h" // 包含设备参数信息
#include "xuartps.h" // 包含UART PS的函数声明
#include "xiicps.h"#include "xil_io.h"///SLCR寄存器,绝对地址,
#define SLCR_UNLOCK_ADDR 0xF8000008
#define SLCR_LOCK_ADDR 0xF8000004//FPGA_RST_CTRL寄存器,绝对地址,#define FPGA_RST_CTRL 0xF8000240
#define UNLOCK_KEY 0xDF0D //解锁码
#define LOCK_KEY 0x767B //加锁码#define PL_RST_MASK 0x01//低四位对应FCLK_RESETN[3:0]
#define PL_CLR_MASK 0x00void PlSoftwareReset(void)
{Xil_Out32(SLCR_UNLOCK_ADDR, UNLOCK_KEY); //解锁Xil_Out32(FPGA_RST_CTRL, PL_RST_MASK); //复位Xil_Out32(FPGA_RST_CTRL, PL_CLR_MASK); //拉起复位Xil_Out32(SLCR_LOCK_ADDR, LOCK_KEY); //加锁
}
// PlSoftwareReset 原文链接:https://blog.csdn.net/qq_21531457/article/details/124581055XUartPs debug_uart; // UART实例int debug_init(void) {int Status;XUartPs_Config *Config;//默认使用uart0 如果要用uart1 请改成 XPAR_XUARTPS_1_DEVICE_IDConfig = XUartPs_LookupConfig(XPAR_XUARTPS_0_DEVICE_ID);if (NULL == Config) {return XST_FAILURE;}Status = XUartPs_CfgInitialize(&debug_uart, Config, Config->BaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}XUartPs_SetBaudRate(&debug_uart, 115200);return XST_SUCCESS;
}#define IIC_DEVICE_ID XPAR_XIICPS_0_DEVICE_ID
#define TEST_BUFFER_SIZE 512#define IIC_SCLK_RATE 200000u8 SendBuffer[2]; /**< Buffer for Transmitting Data */
u8 RecvBuffer[2]; /**< Buffer for Receiving Data */XIicPs Iic;u8 IIC_SLAVE_ADDR= 0x20; //PCF8575 的IC芯片地址, A0,A1,A2地址均连接到了低电平时的地址.int Status;
void iic_init(void ){XIicPs_Config *Config;int Index;/** Initialize the IIC driver so that it's ready to use* Look up the configuration in the config table,* then initialize it.*/Config = XIicPs_LookupConfig(IIC_DEVICE_ID);if (NULL == Config) {return XST_FAILURE;}Status = XIicPs_CfgInitialize(&Iic, Config, Config->BaseAddress);if (Status != XST_SUCCESS) {return XST_FAILURE;}/** Perform a self-test to ensure that the hardware was built correctly.*/Status = XIicPs_SelfTest(&Iic);if (Status != XST_SUCCESS) {return XST_FAILURE;}/** Set the IIC serial clock rate.*/XIicPs_SetSClk(&Iic, IIC_SCLK_RATE);/** Send the buffer using the IIC and ignore the number of bytes sent* as the return value since we are using it in interrupt mode.*/}int main()
{PlSoftwareReset();//重启FPGA的PL部分,debug的时候不需要每次 烧录FPGA了.init_platform();debug_init();iic_init();while(1){xil_printf("Hello\n");SendBuffer[0] = 0x0;//P0.0 到P0.7引脚置低SendBuffer[1] = 0x0;//P1.0 到P1.7引脚置低//写入IO口数据Status = XIicPs_MasterSendPolled(&Iic, SendBuffer, 2, IIC_SLAVE_ADDR);usleep(100);SendBuffer[0] = 0x02;//P0.0 和P0.1引脚置高SendBuffer[1] = 0x02;//P1.0 和P1.1引脚置高//读取IO口数据Status = XIicPs_MasterSendPolled(&Iic, SendBuffer, 2, IIC_SLAVE_ADDR);usleep(100);//读取引脚状态.Status = XIicPs_MasterRecvPolled(&Iic, RecvBuffer, 2, IIC_SLAVE_ADDR);// if (Status != XST_SUCCESS) {// return XST_FAILURE;// }xil_printf("P0=>%d",RecvBuffer[0]);xil_printf("P1=>%d",RecvBuffer[1]);sleep(1);}cleanup_platform();return 0;
}
亲测正常, 注意IIC的地址, 有的从0x20开始的, 有的是0x40开始的.