ZYNQ GPIO应用

总结一下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测试。

猜你喜欢

转载自blog.csdn.net/u012442565/article/details/78160987