ZYNQ GPIO应用

来源:互联网 发布:杀破狼 js微盘下载 编辑:程序博客网 时间:2024/06/01 08:23

总结一下zynq的GPIO应用
zynq的GPIO分为PS部分的MIO和PS-PL配合使用的EMIO(用PL端的IO扩展GPIO),由PS调度。这里描述一下这个EMIO的应用。

IP的方式扩展IO
在vivado下配置AXI接口的GPIO
这里写图片描述

这里例化了两组GPIO,一组作为 LED的输出IO,一组作为按键的输入IO,采用中断方式检测电平变化

#include <stdio.h>#include <xgpio.h>#include "platform.h"#include "xil_printf.h"#include "xscugic.h"#include "xscutimer.h"#include "./inc/gpio.h"static XGpio led_out_4b;static XGpio BTNInst; static XScuGic INTCInst; int XGpio_InterruptInitialize(void){    int status;     printf("LED 4bit Init.............\r\n");    status = XGpio_Initialize(&led_out_4b,XPAR_AXI_GPIO_0_DEVICE_ID);   //Init LED GPIO    if(status != XST_SUCCESS)         return XST_FAILURE;     XGpio_SetDataDirection(&led_out_4b,1,0x00);                         //Set GPIO as output    status = XGpio_Initialize(&BTNInst, BTNS_DEVICE_ID);     if(status != XST_SUCCESS)         return XST_FAILURE;     XGpio_SetDataDirection(&BTNInst, 1, 0xFF);     printf("EXIT InterruptInitialize......\r\n");    status = IntcInitFunction(EXIT_INTC_DEVICE_ID, &BTNInst);     if(status != XST_SUCCESS)         return XST_FAILURE;     return XST_SUCCESS; }//---------------------------------------------------- // INTERRUPT SETUP FUNCTIONS //---------------------------------------------------- int IntcInitFunction(u16 DeviceId, XGpio *GpioInstancePtr){     XScuGic_Config *IntcConfig;      int status;     // Interrupt controller initialization     IntcConfig = XScuGic_LookupConfig(DeviceId);     status = XScuGic_CfgInitialize(&INTCInst, IntcConfig,                                     IntcConfig->CpuBaseAddress);     if(status != XST_SUCCESS)         return XST_FAILURE;     // Register GIC interrupt handler     Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,                                   (Xil_ExceptionHandler)XScuGic_InterruptHandler,                                   &INTCInst);     Xil_ExceptionEnable();     // Register GPIO interrupt handler     status = XScuGic_Connect(&INTCInst,                               INTC_GPIO_INTERRUPT_ID,                               (Xil_ExceptionHandler)BTN_Intr_Handler,                               (void *)GpioInstancePtr);     if(status != XST_SUCCESS)         return XST_FAILURE;     // Enable GPIO interrupts     XGpio_InterruptEnable(GpioInstancePtr, 1);     XGpio_InterruptGlobalEnable(GpioInstancePtr);     // Enable GPIO interrupts in the controller     XScuGic_Enable(&INTCInst, INTC_GPIO_INTERRUPT_ID);     return XST_SUCCESS; } void BTN_Intr_Handler(void *InstancePtr) {     u8 btn_value = 0;    unsigned char led_val = 0;     // Ignore additional button presses     if ((XGpio_InterruptGetStatus(&BTNInst) & BTN_INT) != BTN_INT)     {         printf("Other interrupt......\r\n");        return;         // Disable GPIO interrupts         XGpio_InterruptDisable(&BTNInst, BTN_INT);     }     btn_value = ~ XGpio_DiscreteRead(&BTNInst, 1)&0x0f;     printf("key value 0x%x......\r\n",btn_value);    switch (btn_value){         case 0x01: led_val = 0x01; break;         case 0x02: led_val = 0x02; break;         case 0x04: led_val = 0x04; break;         case 0x08: led_val = 0x08; break;         default:break;        }     XGpio_DiscreteWrite(&led_out_4b,1,~led_val);     // Acknowledge GPIO interrupts     (void)XGpio_InterruptClear(&BTNInst, BTN_INT);     // Enable GPIO interrupts     XGpio_InterruptEnable(&BTNInst, BTN_INT); } 

上面代码初始化EMIO和按键中断的初始化和中断处理函数

直接扩展EMIO,由ZYNQ处理器引出到PL端配置IO
硬件连接
这里写图片描述

CPU GPIO定制配置
这里写图片描述

由硬件导入到SDK中会生成相应的驱动API,
使用刚才例化的GPIO做了一个IIC(源码借鉴某位大神,尊重原著,略有修改)
初始化IO和调用API接口如下代码:

#include <stdio.h>#include "platform.h"#include "xil_printf.h"#include "sleep.h"  #include "xgpiops.h"#include "./inc/i2c.h"static XGpioPs psGpioInstancePtr;int EMIO_I2C_init(void)  {      XGpioPs_Config *GpioConfigPtr;      int xStatus;      GpioConfigPtr = XGpioPs_LookupConfig(XPAR_PS7_GPIO_0_DEVICE_ID);    if(GpioConfigPtr == NULL)      return XST_FAILURE;      xStatus = XGpioPs_CfgInitialize(&psGpioInstancePtr,GpioConfigPtr,GpioConfigPtr->BaseAddr);    if(XST_SUCCESS != xStatus)          print("EMIO INIT FAILED \n\r");      XGpioPs_SetDirectionPin(&psGpioInstancePtr, SCL_PIN,DIRECTION_OUTPUT);    XGpioPs_SetDirectionPin(&psGpioInstancePtr, SDA_PIN,DIRECTION_OUTPUT);    XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, SCL_PIN,1);    XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, SDA_PIN,1);    return xStatus;  }  void CLOCK_HIGH(void)  {      XGpioPs_WritePin(&psGpioInstancePtr,SCL_PIN, 1);}  void CLOCK_LOW(void)  {      XGpioPs_WritePin(&psGpioInstancePtr,SCL_PIN, 0);}  int GET_DATA(void)  {      return XGpioPs_ReadPin(&psGpioInstancePtr,SDA_PIN);}  void DATA_INPUT(void)  {      XGpioPs_SetDirectionPin(&psGpioInstancePtr, SDA_PIN,DIRECTION_INPUT);//}  void DATA_OUTPUT(void)  {      XGpioPs_SetDirectionPin(&psGpioInstancePtr, SDA_PIN,DIRECTION_OUTPUT);//}  void DATA_HIGH(void)  {      XGpioPs_WritePin(&psGpioInstancePtr,SDA_PIN, 1);}  void DATA_LOW(void)  {      XGpioPs_WritePin(&psGpioInstancePtr,SDA_PIN,0);}  void I2C_start(void)  {      CLOCK_HIGH();      DATA_HIGH();      I2C_DELAY;      DATA_LOW();      I2C_DELAY;      CLOCK_LOW();      I2C_DELAY;  }  void I2C_end(void)  {      DATA_LOW();      I2C_DELAY;      CLOCK_HIGH();      I2C_DELAY;      DATA_HIGH();      I2C_DELAY;  }  int I2C_sendbyte( unsigned char value )  {      unsigned char tmp = value;      unsigned char  i=0,ack;      for(i=0; i<8; i++)      {          if(tmp & 0x80 )                  DATA_HIGH();          else                  DATA_LOW();           I2C_DELAY;           CLOCK_HIGH();           I2C_DELAY;           CLOCK_LOW();           I2C_DELAY;           tmp<<=1;       }       DATA_HIGH();       DATA_INPUT();       I2C_DELAY;       CLOCK_HIGH();       ack = GET_DATA();       I2C_DELAY;       CLOCK_LOW();       I2C_DELAY;       DATA_OUTPUT();       if(ack==1)       {           return -1;       }       return 0;  }  unsigned char I2C_readbyte( unsigned char addr)  {      unsigned char  i=0,data=0;      DATA_HIGH();      DATA_INPUT();      for(i=0; i<8; i++)      {          CLOCK_HIGH();          I2C_DELAY;          data <<= 1;          if(GET_DATA())              data |= 1;           I2C_DELAY;           CLOCK_LOW();           I2C_DELAY;       }       DATA_OUTPUT();       DATA_HIGH();       I2C_DELAY;       CLOCK_HIGH();       I2C_DELAY;       CLOCK_LOW();       I2C_DELAY;       DATA_HIGH();       return data;  }  int I2C_readdata(unsigned char id, unsigned char addr, unsigned char *value)  {      // 两相写      I2C_start();      if(I2C_sendbyte(id<<1) != 0)      {          goto error;      }      if(I2C_sendbyte(addr) != 0)      {          goto error;      }      // 两相读      I2C_start();      if(I2C_sendbyte((id<<1)|0x1) != 0)      {          goto error;      }      *value = I2C_readbyte(addr);      I2C_end();      return 0;  error:      I2C_end();      return -1;  }  int I2C_writedata(unsigned char id, unsigned char addr,unsigned char value)  {      I2C_start();      if(I2C_sendbyte(id<<1) != 0)      {          goto error;      }      if(I2C_sendbyte(addr) != 0)      {          goto error;      }      if(I2C_sendbyte(value)!= 0)      {          goto error;      }      I2C_end();      return 0;  error:      I2C_end();      return -1;  }  void i2c_test(void){    u8 data = 0xAA;    EMIO_I2C_init();      usleep(500*1000);      if (I2C_writedata(I2C_DEVICE_ADDR,0x00,data) != 0)        printf("IIC write error!!!!!!!!!!!!!\r\n");    else         printf("IIC write addr 0x00 data is 0x%X \r\n",data);    usleep(50000);  //写到读之间延时一段时间    data = 0;    if(I2C_readdata(I2C_DEVICE_ADDR,0x00,&data) != 0)           printf("IIC read error!!!!!!!!!!!!!\r\n");    else         printf("IIC read addr 0x00 data is 0x%X \r\n",data);}

这里可以测试GPIO的应用,包括按键触发中断,根据按键的状态点灯;EMIO模拟IIC接口读写EEPROM测试。

原创粉丝点击