从0开始学Zedboard(4)利用AXI_Timer 实现OLED自动播放
0赞
发表于 2015/1/6 19:58:09
阅读(5955)
在上一篇文章中,讲到用按键控制OLED显示切换,这一章我们要利用Timer和中断实现OLED显示自动播放。思路就是利用Timer倒计时之后通过中断执行一个特定的函数,SDK中我们用到了xscugic.h(PS内通用中断控制器驱动函数),xtmrctr.h(AXI_Timer驱动函数)。这两个模块配置初始化比较复杂,附件中会有Word详细讲解如何使用。
建立VIVADO工程,我在这里不详细描述,不会可以去先试试官方的demo,那里会有很多一步一步的教程,如图所示:
建立好工程后,产生bitstream,进入SDK,同样建立hellowworld,工程,将helloworld.c改为如下代码:
#include <stdio.h> #include "platform.h" #include "xil_types.h" #include "xparameters.h" #include "xgpiops.h" #include "xil_io.h" #include "oled.h" #include "xil_exception.h" #include "xscugic.h" #include "xtmrctr.h" #define XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR 61 static int InterruptFlag; XGpioPs_Config*GpioConfigPtr; /* The configuration parameters of the PS GPIO */ XScuGic InterruptController; /* Instance of the Interrupt Controller */ XTmrCtr TimerInstancePtr; /* Instance of the AXI Timer */ static XScuGic_Config *GicConfig; /* The configuration parameters of the Interrupt controller */ static XGpioPs psGpioInstancePtr; /* Instance of the PS GPIO */ //计时器中断执行函数 void Timer_InterruptHandler(void *data, u8 TmrCtrNumber) { print("\r\n"); print("\r\n"); print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n"); print(" Inside Timer ISR \n \r "); XTmrCtr_Stop(data,TmrCtrNumber); XTmrCtr_Reset(data,TmrCtrNumber); print(" Timer ISR Exit\n \n \r"); print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\r\n"); print("\r\n"); print("\r\n"); InterruptFlag = 1; } //GIC设置函数 int SetUpInterruptSystem(XScuGic *XScuGicInstancePtr) { /* * Connect the interrupt controller interrupt handler to the hardware * interrupt handling logic in the ARM processor. */ Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler) XScuGic_InterruptHandler, XScuGicInstancePtr); /* * Enable interrupts in the ARM * Enable the IRQ exception */ Xil_ExceptionEnable(); return XST_SUCCESS; } //////////////////定义初始化中断控制器函数//////////////////////////////////// ///////中断设置查找->GIC初始化->设置中断系统->中断服务程序入口地址设置->GIC允许////// int ScuGicInterrupt_Init(u16 DeviceId,XTmrCtr *TimerInstancePtr) { int Status; /* * Initialize the interrupt controller driver so that it is ready to * use. */ GicConfig = XScuGic_LookupConfig(DeviceId); if (NULL == GicConfig) { return XST_FAILURE; } Status = XScuGic_CfgInitialize(&InterruptController, GicConfig, GicConfig->CpuBaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Setup the Interrupt System */ Status = SetUpInterruptSystem(&InterruptController); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Connect a device driver handler that will be called when an * interrupt for the device occurs, the device driver handler performs * the specific interrupt processing for the device */ Status = XScuGic_Connect(&InterruptController, XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR, (Xil_ExceptionHandler)XTmrCtr_InterruptHandler, (void *)TimerInstancePtr); if (Status != XST_SUCCESS) { return XST_FAILURE; } /* * Enable the interrupt for the device and then cause (simulate) an * interrupt so the handlers will be called */ XScuGic_Enable(&InterruptController, XPAR_FABRIC_AXI_TIMER_0_INTERRUPT_INTR); return XST_SUCCESS; } extern XGpioPs_Config XGpioPs_ConfigTable[XPAR_XGPIOPS_NUM_INSTANCES]; int main() { int xStatus,start,end; u32 Readstatus1,Readstatus2; int iPinNumberld9 = 7; /*Ld9 is connected to MIO pin 7*/ int iPinNumberbtn8 = 50;/*Btn8 is connected to MIO pin 50*/ int iPinNumberbtn9 = 51;/*Btn9 is connected to MIO pin 51*/ init_platform(); print("##### Application Starts #####\n\r"); print("\r\n"); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-1 :PS GPIO Intialization //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 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(" PS GPIO INIT FAILED \n\r"); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-2 :PS GPIO pin setting to Output //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumberld9,1); XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumberld9,1); XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumberbtn8,0); XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumberbtn8,1); XGpioPs_SetDirectionPin(&psGpioInstancePtr, iPinNumberbtn9,0); XGpioPs_SetOutputEnablePin(&psGpioInstancePtr, iPinNumberbtn9,1); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-3 :AXI_Timer Intialization //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ xStatus = XTmrCtr_Initialize(&TimerInstancePtr,XPAR_AXI_TIMER_0_DEVICE_ID); if(XST_SUCCESS != xStatus) print("TIMER INIT FAILED \n\r"); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-4 :Set Timer Handler //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ XTmrCtr_SetHandler(&TimerInstancePtr, Timer_InterruptHandler, &TimerInstancePtr); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-5 :Setting timer Reset Value //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ XTmrCtr_SetResetValue(&TimerInstancePtr, 0, //Change with generic value 0xfffff000);//6s //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-6 :Setting timer Option (Interrupt Mode And Auto Reload ) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ XTmrCtr_SetOptions(&TimerInstancePtr, XPAR_AXI_TIMER_0_DEVICE_ID, (XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION )); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-7 : SCUGIC interrupt controller Initialization //Registration of the Timer ISR //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ xStatus= ScuGicInterrupt_Init(XPAR_PS7_SCUGIC_0_DEVICE_ID,&TimerInstancePtr); if(XST_SUCCESS != xStatus) print(" :( SCUGIC INIT FAILED \n\r"); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-8 :OLED Intialization //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ OLED_Init(); OLED_ShowString(0,0, "BTN8 to start"); OLED_Refresh_Gram(); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-9 :press btn8 to start //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while (1){ start=XGpioPs_ReadPin(&psGpioInstancePtr, iPinNumberbtn8); if(start){ XGpioPs_WritePin(&psGpioInstancePtr,iPinNumberld9,1); OLED_Clear(); OLED_ShowString(0,0, "PIG"); OLED_Refresh_Gram(); print("###################### Demo Starts ########################\r\n"); break; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //Step-10 :press btn9 to end Demo //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ while(1){ int high=16; int lenth=80; int i,j; for(i=0,j=0;i<lenth,j<high;i+=5,j++){ if(i<lenth&&j<high){ XTmrCtr_Start(&TimerInstancePtr,0); print("timer start \n\r"); //Wait For interrupt; print(" \r\n"); while(InterruptFlag != 1); InterruptFlag = 0; OLED_Clear(); OLED_ShowString(i,j, "PIG"); OLED_Refresh_Gram(); } } for(i=lenth,j=high;i>0,j>0;i-=5,j--){ if(i>0&&j>0){ XTmrCtr_Start(&TimerInstancePtr,0); print("timer start \n\r"); //Wait For interrupt; print(" \r\n"); while(InterruptFlag != 1); InterruptFlag = 0; OLED_Clear(); OLED_ShowString(i,j, "PIG"); OLED_Refresh_Gram(); } } end=XGpioPs_ReadPin(&psGpioInstancePtr, iPinNumberbtn9); if(end){ XGpioPs_WritePin(&psGpioInstancePtr,iPinNumberld9,0); OLED_Clear(); break; } } print("\r\n"); print("***********\r\n"); print("BYE \r\n"); print("***********\r\n"); cleanup_platform(); return 0; }跟上一章一样,在工程里插入oled.h、oled.c、font.h。上zedboard跑的结果就是,一个PIG字符在oled屏幕里对角线不停的来回撞,知道按下BTN9结束Demo。