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 0x00
void 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 原文链接:
XUartPs debug_uart; // UART实例
int debug_init(void) {
int Status;
XUartPs_Config *Config;
//默认使用uart0 如果要用uart1 请改成 XPAR_XUARTPS_1_DEVICE_ID
Config = 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 200000
u8 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开始的.