1. 程式人生 > >MicroBlaze核的串行接口實驗:SPI UART

MicroBlaze核的串行接口實驗:SPI UART

重新 setoption 錯誤2 done fifo 接收 判斷 c中 juc

reference : https://blog.csdn.net/weixin_42413559/article/details/80720566

串行接口:SPI UART

XPS->SDK(Platform)->新建BSP->新建appproject

問題1:在創建工程的時候沒有像書上那樣,添加了RS232接口,那麽在prots中添加UART端口可以嗎?

經過試驗,在創建工程的時候和在創建完成之後添加RS232都可以用來燒寫程序的

錯誤1:在導出到SDK的時候,導出失敗

不能解決的辦法:新建一個BSB工程,在file->switch workspace裏面把工作目錄改為2的Export(改了之後SDK立即閃退重啟)

能解決的辦法:重新在XPS裏面導出到SDK,第二次還是沒成功,SDK打開的還是上次走馬管的內容,在file那裏更改工作目錄,軟件再次閃退之後就好了。

問題2:不小心把terminal給關了,怎麽調出來?

在左下角星號那裏(showview as a fast view)

錯誤2:<led> is already declared in thisregion.在生成網標的時候。

能解決的辦法:把實例LED改名字為LEDs,分析原因可能是系統默認裏面還定義了LED,導致產生了沖突。

錯誤3:LEDS沒有聲明,在生成比特流的時候。

不能解決的辦法:把LEDS改為LEDs,跟實例名字一樣。

能解決的辦法:把LEDS改為LED,因為external端口的名字是LED而不是LEDs,LEDs是實例的端口。分析錯誤2應該是實例名和外部端口名不能一樣。

錯誤4:IO非用戶可以使用/非IOSTANDARD

不能解決的辦法:把GPIO所有端口從UCF裏面先刪除,結果生成比特流時報錯LED和SPI的連接。重新檢查了UCF中發GPIO每一個引腳的連接發現沒問題。重啟軟件。

能解決的辦法:在console裏面看error情況。結果發現報錯時SPI的引腳連接。我並沒有為SPI分配引腳。

錯誤5:缺少timer和spi相關的頭文件

不能解決的辦法:刪除一次BSP包,Refresh,重啟SDK

能解決的辦法:刪除兩次BSP包,並refresh

錯誤6: XUartLite_Send(&UART,buf,27);報warnning。

不能解決的辦法:原來這個函數傳輸進去的指針應該是*u8,但是buf是個char型變量

錯誤7:把上個走馬管的工程初始化代碼賦值粘貼進去之後,不僅my_ISR報錯,而且bsp的庫文件的interrupt裏面有個函數也報錯:重復定義

不能解決的辦法:刪除BSP重新添加(不報錯),把上個走馬管的.c文件打開復制過去(又報錯)

能解決的辦法:每個函數都自己寫一遍,直到把microblaze_register_handler添加進去的時候,my_ISR才會報錯。應該是void My_ISR(void) __attribute__((interrupt_handler));的註冊方式和microblaze_register_handler的註冊方式是沖突的。將void My_ISR(void)去除,采用中斷的API函數進行中斷控制器和中斷設備的連接。這個時候BSP錯誤再次出現,刪除重新添加後即可。

錯誤8:

不能解決的辦法:重啟軟件,重新打

能解決的辦法:雖然SpiIntrHandler聲明過,但是還沒有定義,定義了之後就不報錯了。Undecleard和undefined是不一樣的

錯誤9:把程序燒寫進去之後,初始化能過,但是10ms定時器中斷進不去不能解決的辦法:

能解決的辦法:從頭到尾檢查TIMER的初始化,發現10ms定時器進不去是因為沒有開始定時器中斷,即XTmrCtr_Start(&TimerCounterInst,0);。

錯誤10:串口發不出來數據

能解決的辦法:串口中斷函數沒有註冊

錯誤11:串口接收不到數據

能解決的辦法:串口的初始化程序的設備ID有誤,Device_0是DebugMode的,Device_1是RS232的,Device_2才是UART的,而我參考的代碼只有一個串口,是Device_0所以一直是錯的。並且沒有使能UART的中斷

錯誤12:buf裏面的27個char“UART Initialize Success\r\n”總是只打印前16個,後面的打印不出來

不能解決的辦法:把數組容量改大

能解決的辦法:XUartLite_Send只能一次傳輸16個數據

錯誤13:Btn_SW不能觸發中斷產生數據

不能解決的辦法:重啟軟件,把走馬管的代碼復制粘貼修改實例和地址名字,把按鍵的硬件由只有I功能改為IO功能,把LED的硬件由只有O功能改為IO功能,新建.c文件只寫LED部分

能解決的辦法:把export刪掉重新Export,然後就好了!沒錯,為了找這個問題我花了整整一晚上時間加上上午一個半小時!心態都快要崩了

錯誤14:SW的值只能傳輸一半

不能解決的辦法:由於XUartLite_Send(&UART,&SW,1);//只能Send u8類型的,故不能把SW一次傳輸完,所以要把SW的值分兩次傳輸完。但是如何區分兩次信息的傳輸,以及分別接收SW的前一半和後一半解決不了。嘗試了這個方法,發現還是不行。

XUartLite_Send(&UART,&flag,1);

XUartLite_Send(&UART,&flag,1);

XUartLite_Send(&UART,&flag,1);//發送三次代表配對密碼

if(flag_in){flag_in=0;flag_out_first=1;}

if(RX_data==0){flag_ok++;}

if(flag_ok==3)

{

flag_in=1;

}

if(flag_out_sec)

{

flag_out_sec=0;

Xil_Out8(XPAR_LEDS_BASEADDR+0xF,RX_data);

}

if(flag_out_first)

{

flag_out_first=0;

Xil_Out8(XPAR_LEDS_BASEADDR,RX_data);

flag_out_sec=1;

}

能解決的辦法:在驗收的時候,見到有人做成功的。

錯誤15:SPI沒有時鐘輸出

能解決的辦法:檢查SPI的初始化函數發現,connect和setstatus連接的不一樣,connect連接的是庫函數裏面的XSpi_InterruptHandler,而setstatusHandler連接的是用戶自定義的函數SpiIntrHandler

錯誤16:DAC的鋸齒波只有30HZ

不能解決的辦法:把其他函數都不運行,只運行鋸齒波的,提高只有2HZ

能解決的辦法:把+1換成+更大的的數。經過測試T的初始值為0X24的時候頻率為1KHZ,同時為了快速調節,當SW==0X4的時候,會加快T會倍增到5倍(每次加400HZ)。電壓每次變化0.08V。

錯誤17:ADC接收不到數據(一直是0X4CEC,重新燒寫之後會變,但是保持恒定),但是示波器顯示ADC轉換數據正常

不能解決的辦法:單獨把SPI寫到While(1)裏

能解決的辦法:請教同學發現print的時候,直接print ReadBuff的地址了,因為ReadBuff是個數組,代表地址,所以要先拼接之後再輸出。

硬件連接

實驗二硬件框圖

① UART:PMODE,定義JA4(E17),JA10(E18)為RX和TX

② Swtiches&Btns(GPIO):8個按鍵

③ LED(GPIO):8個LED

④ SPI DA&AD:

⑤ timer(用來定時發送數據)

⑥ 中斷控制器

⑦ UCF:

NET "CLK" TNM_NET = sys_clk_pin;

TIMESPEC TS_sys_clk_pin = PERIOD sys_clk_pin 100000 kHz;

NET "CLK" LOC= "E3" | IOSTANDARD ="LVCMOS33";

NET "REST" LOC = "E16" | IOSTANDARD ="LVCMOS33";

NET "RX_232" LOC= "C4" | IOSTANDARD ="LVCMOS33";

NET "TX_232" LOC= "D4" | IOSTANDARD ="LVCMOS33";

NET "RX" LOC= "E17" | IOSTANDARD ="LVCMOS33";

NET "TX" LOC= "E18" | IOSTANDARD ="LVCMOS33";

NET "Btn<0>" LOC = "T16" | IOSTANDARD= "LVCMOS33";#左

NET "Btn<1>" LOC = "V10" | IOSTANDARD= "LVCMOS33";#下

NET "Btn<2>" LOC = "R10" | IOSTANDARD= "LVCMOS33";#右

NET "Btn<3>" LOC = "F15" | IOSTANDARD= "LVCMOS33";#上

NET "SW<0>" LOC = "U9" | IOSTANDARD ="LVCMOS33";

NET "SW<1>" LOC = "U8" | IOSTANDARD ="LVCMOS33";

NET "SW<2>" LOC = "R7" | IOSTANDARD ="LVCMOS33";

NET "SW<3>" LOC = "R6" | IOSTANDARD ="LVCMOS33";

NET "SW<4>" LOC = "R5" | IOSTANDARD ="LVCMOS33";

NET "SW<5>" LOC = "V7" | IOSTANDARD ="LVCMOS33";

NET "SW<6>" LOC = "V6" | IOSTANDARD ="LVCMOS33";

NET "SW<7>" LOC = "V5" | IOSTANDARD ="LVCMOS33";

NET "SW<8>" LOC = "U4" | IOSTANDARD ="LVCMOS33";

NET "SW<9>" LOC = "V2" | IOSTANDARD ="LVCMOS33";

NET "SW<10>" LOC = "U2" | IOSTANDARD= "LVCMOS33";

NET "SW<11>" LOC = "T3" | IOSTANDARD= "LVCMOS33";

NET "SW<12>" LOC = "T1" | IOSTANDARD= "LVCMOS33";

NET "SW<13>" LOC = "R3" | IOSTANDARD= "LVCMOS33";

NET "SW<14>" LOC = "P3" | IOSTANDARD= "LVCMOS33";

NET "SW<15>" LOC = "P4" | IOSTANDARD= "LVCMOS33";

NET "LED<0>" LOC = "T8" | IOSTANDARD= "LVCMOS33";

NET "LED<1>" LOC = "V9" | IOSTANDARD= "LVCMOS33";

NET "LED<2>" LOC = "R8" | IOSTANDARD= "LVCMOS33";

NET "LED<3>" LOC = "T6" | IOSTANDARD= "LVCMOS33";

NET "LED<4>" LOC = "T5" | IOSTANDARD= "LVCMOS33";

NET "LED<5>" LOC = "T4" | IOSTANDARD= "LVCMOS33";

NET "LED<6>" LOC = "U7" | IOSTANDARD= "LVCMOS33";

NET "LED<7>" LOC = "U6" | IOSTANDARD= "LVCMOS33";

NET "LED<8>" LOC = "V4" | IOSTANDARD= "LVCMOS33";

NET "LED<9>" LOC = "U3" | IOSTANDARD= "LVCMOS33";

NET "LED<10>" LOC = "V1" | IOSTANDARD= "LVCMOS33";

NET "LED<11>" LOC = "R1" | IOSTANDARD= "LVCMOS33";

NET "LED<12>" LOC = "P5" | IOSTANDARD= "LVCMOS33";

NET "LED<13>" LOC = "U1" | IOSTANDARD= "LVCMOS33";

NET "LED<14>" LOC = "R2" | IOSTANDARD= "LVCMOS33";

NET "LED<15>" LOC = "P2" | IOSTANDARD= "LVCMOS33";

NET "SPI_MOSI" LOC = "B13" | IOSTANDARD ="LVCMOS33";

NET "SPI_MISO" LOC = "G13" | IOSTANDARD ="LVCMOS33";

NET "SPI_CLK" LOC = "F14" | IOSTANDARD = "LVCMOS33";

NET "SPI_SS" LOC = "C17" | IOSTANDARD = "LVCMOS33";

軟件編寫

軟件流程圖

xil_printf("0x%X\n\r",x) (只能打印整數)

1).頭文件:

#include"xparameters.h"

#include"platform.h"

#include"xil_io.h"

#include"xgpio.h"

#include"xtmrctr.h"

#include"xspi.h"

#include"xintc.h"

#include"xintc_i.h"

#include"xil_exception.h"//(硬件異常和軟件異常處理)

#include"stdio.h"

#include"xuartlite.h"

#include"xuartlite_l.h"

2).定義函數:

voidprint(char *str);

voidInitialize(void);

voidUart_Handler(void);

voidTimerCounterHandler(void* CallBackRef , u8 TmrCtrNumber);

voidBtn_SWHandler(void*CallBackRef);

void SpiIntrHandler(void *CallBackRef ,u32 StatusEvent ,u32ByteCount);

//voidMy_ISR(void) __attribute__((interrupt_handler));

voidJuChiBo(int T,int Amplitude);

voidADC(void);

3).聲明實例,定義變量:

XIntcInterruptController;

XTmrCtrTimerCounterInst;

XUartLiteUART;

XSpiSPiInstance;

volatile int TransferProgress;(volatile是代表被不同進程訪問和修改的變量的修飾符)

u8 ReadBuffer[2];

u8 WriteBuffer[2];(存放SPI的數據)

char buf[27]="UART Initialize Success\r\n";

short flag_RX=0x00;

unsigned char RX_data=0x00;

int count=0;

XGpio Btn_SW,LED;

int Btn=0 , SW_pre=0 , SW=0;//按鍵和開關的值

int flag_SW=0 , flag_Btn=0;//按鍵和開關的觸發標誌位

int time_10ms=0;//10ms計時

4).初始化函數:

a.初始化串口:

XUartLite_Initialize(&UART,XPAR_UARTLITE_0_DEVICE_ID);

XUartLite_ResetFifos(&UART);

while(XUartLite_IsTransmitFull(XPAR_UARTLITE_0_BASEADDR));

XUartLite_Send(&UART,buf,27);

b.初始化SPI

初始化:XSpi_Initialize(&SPiInstance,XPAR_SPI_0_DEVICE_ID);

掛載到中斷控制器上:XIntc_Connect()

設置中斷:XSpi_SetStatusHandler(&SpiInstance , &SPiInstance, (XSpi_StatusHandler) SpiIntrHandler);

使能中斷:XIntc_Enable(&IntCtrl,3);//SPI

設置模式:

XSpi_SetOptions(&SpiInstance ,XSP_MASTER_OPTION|XSP_CLK_PHASE_1_OPTION);

設置從設備選擇信號:XSpi_SetSlaveSelect(&SPiInstance,1);

使能:XSpi_Start(&SPiInstance);

c.初始化中斷控制器:

XIntc_Initialize(&IntCtrl, XPAR_INTC_DEVICE_ID);

INTC中斷源使能

XIntc_Enable(&IntCtrl,0);//Timer

XIntc_Enable(&IntCtrl,1);//Btn_SW

XIntc_Enable(&IntCtrl,2);//UART

XIntc_Enable(&IntCtrl,3);//SPI

啟動

XIntc_Start(&IntCtrl,XIN_REAL_MODE);

d.初始化定時器:

XTmrCtr_Initialize(&TimerCounterInst,XPAR_TMRCTR_0_DEVICE_ID);//XPAR_TMRCTR_0_DEVICE_ID

XTmrCtr_SetHandler(&TimerCounterInst,TimerCounterHandler , &TimerCounterInst);

XTmrCtr_SetOptions(&TimerCounterInst,0,XTC_INT_MODE_OPTION|XTC_AUTO_RELOAD_OPTION| XTC_DOWN_COUNT_OPTION);

XTmrCtr_SetResetValue(&TimerCounterInst, 0, 0x00f4240);//0xf4240是1000 000

XIntc_Enable(&IntCtrl, XPAR_INTC_0_TMRCTR_0_VEC_ID);//TMRCTR_Interruppt_ID

XIntc_Connect(&IntCtrl,XPAR_INTC_0_TMRCTR_0_VEC_ID,(XInterruptHandler)XTmrCtr_InterruptHandler,(void*)&TimerCounterInst);

e.初始化GPIO:

用API函數來初始化:

XGpio_Initialize(&Btn, XPAR_BTN_SW_DEVICE_ID);

XGpio_SetDataDirection(&Btn,1,0xff);(實例,通道,輸入/出)

GPIO中斷使能:(兩個Enable)

XGpio_InterruptEnable(&Btn_SW,1);

XGpio_InterruptEnable(&Btn_SW,2);

XGpio_InterruptGlobalEnable(&Btn_SW);

f.註冊和使能microblaze的中斷:

microblaze_enable_interrupts();

microblaze_register_handler((XInterruptHandler)XIntc_InterruptHandler,(void*)&IntCtrl);

5).中斷控制器處理函數

void My_ISR(void)。

判斷中斷源並進入相應的實例中斷處理函數。

清除中斷標誌位。

SPI,UART,Btn_SW,Timer的中斷優先級為3,4,5,6。

6).各實例中斷處理函數

UART:判斷狀態寄存器第8位奇偶校驗位,錯就返回1(跳過讀數據)。判斷是否接收到有效數據,如果是就取出數據。

最後在控制寄存器中清除(復位)FIFO,使能UART的硬件中斷。

SPI:修改傳輸標誌位

Btn_SW:

voidBtn_SWHandler(void*CallBackRef)//chinnel1是SW。2是Btn

{

Btn=XGpio_DiscreteRead(&Btn_SW,2);

flag_Btn=1;

XGpio_InterruptDisable(&Btn_SW,2);

if(time_10ms==5)//忽略按鍵彈起再次觸發的中斷

{

XGpio_InterruptClear(&Btn_SW,2);

XGpio_InterruptEnable(&Btn_SW,2);

}

SW_pre=SW;

SW=XGpio_DiscreteRead(&Btn_SW,1);

if(SW_pre==SW){flag_SW=0;}//如果這次的開關值跟上次一樣,就不立flag,防止因為Btn的觸發導致SW的誤觸發

else

{

flag_SW=1;

XGpio_InterruptClear(&Btn_SW,1);

XGpio_InterruptEnable(&Btn_SW,1);

}

}

Timer:

voidTimerCounterHandler(void* CallBackRef , u8 TmrCtrNumber)

{

time_10ms++;

if(time_10ms>100)

{

time_10ms=0;

print("1s");

}

}//10ms進一次中斷,100次(1s)從terminal輸出一次

7).輸出鋸齒波的函數

將count的低8位為buf[0],低9~12位通過平移、篩選之後送給buf[1]。

8).采集電壓的函數

讀取電壓量存進ReadBuffer

9).主函數:

a.初始化

b.判斷UART是否接收到數據

c.判斷Btn是否接收到數據

d.判斷SW是否接收到數據

e.輸出鋸齒波

f.讀取ADC的值

#include "xparameters.h"
#include "platform.h"
#include "xil_io.h"
#include "xgpio.h"
#include "xtmrctr.h"
#include "xspi.h"
#include "xintc.h"
#include "xintc_i.h"
#include "xil_exception.h"//(硬件異常和軟件異常處理)
#include "stdio.h"
#include "xuartlite.h"
#include "xuartlite_l.h"
 
void print(char *str);
void Initialize(void);
void Uart_Handler(void);
void TimerCounterHandler(void* CallBackRef , u8 TmrCtrNumber);
void Btn_SWHandler(void*CallBackRef);
void SpiIntrHandler(void *CallBackRef ,u32 StatusEvent ,u32 ByteCount);
//void My_ISR(void) __attribute__((interrupt_handler));
void JuChiBo(int T,int Amplitude);
void ADC(void);
void delay_ms(u32 t);
 
XIntc IntCtrl;
XTmrCtr TimerCounterInst;
XUartLite UART;
XSpi SPiInstance;
volatile int TransferProgress;
u8 ReadBuffer[2]={0,0};
u8 WriteBuffer[2];
u8 buf[32]="UART Init Suc\r\n";
short flag_RX=0x00;
unsigned char RX_data=0x00;
int count=0;
XGpio Btn_SW;
XGpio LED;
u8 Btn=0 , Btn_pre = 0 , SW8_1=0 , SW8_2=0;
u16 SW_pre=0 , SW=0;
int flag_SW=0 , flag_Btn=0;
volatile int time_10ms1=0,time_10ms2=0,time_10ms3=0,time_10ms_ADC=0,time_10ms_DAC=0;
u32 Amplitude = 4096;
u8 T=0x24 ;
char c;
u16 temp=0;
u16 Error=0;
u16 Voltage=0;
 
int main()
{
     print("program start\r\n");
     Initialize();
     XUartLite_Send(&UART,buf,32);//u8變為char,so warnning
     XGpio_DiscreteWrite(&LED,1,0xffff);
while(1)
{
    if(time_10ms1>1000){time_10ms1=0;print("10s\r\n");}//10s
    if(time_10ms2>100)
    {time_10ms2=0;print("1s\r\n");}//1s XUartLite_Send(&UART,buf,32);XUartLite_SendByte(XPAR_UARTLITE_2_BASEADDR,0);
////UART///////////////////////////////////////////////////////////////////////////////////////////////////////////
    if(flag_RX)
    {
 
        flag_RX=0;
        RX_data = Xil_In32(XPAR_UART_BASEADDR+0X00);//數據寄存器的偏移地址是0X00
        Xil_Out32(XPAR_UART_BASEADDR+0x0c,0X13);//clear fifo,0x0c是控制寄存器的偏移地址c=12,0x13=0001 0011
        xil_printf("UART received data  0x%X\r\n",RX_data);
        //XUartLite_Send(&UART,&RX_data,1);
        Xil_Out8(XPAR_LEDS_BASEADDR,RX_data);
        //XGpio_DiscreteWrite(&LED,1,RX_data);
        //XUartLite_SendByte(XPAR_UARTLITE_2_BASEADDR,RX_data);
    }
////Btn////////////////////////////////////////////////////////////////////
    if(flag_Btn)
    {
        flag_Btn=0;
        xil_printf("Btn data is 0x%X\r\n",Btn);
        //Btn=Btn+0x41;
        XUartLite_Send(&UART,&Btn,1);
        switch (Btn){
        case 0x01:{T=T-5;break;}
        case 0x02:{Amplitude=Amplitude-100;break;}
        case 0x04:{T=T+5;break;}
        case 0x08:{Amplitude=Amplitude+100;break;}
        }
        xil_printf("T is 0x%X\r\n",T);
        xil_printf("Amplitude is 0x%X\r\n",Amplitude);
 
    }
////SW////////////////////////////////////////////////////////////////////
    if(flag_SW)
    {
        flag_SW=0;
        xil_printf("SW data is 0x%X\r\n",SW);
        SW8_1=(u8)SW;
        temp=SW;
        temp=temp>>8;
        SW8_2=(u8)(temp);
        //xil_printf("temp data is 0x%X\r\n",temp);
        xil_printf("SW8_1 data is 0x%X\r\n",SW8_1);
        xil_printf("SW8_2 data is 0x%X\r\n",SW8_2);
        //SW8_1=SW8_1+0x41;
        //SW8_2=SW8_2+0x41;
 
        XUartLite_Send(&UART,&SW8_1,1);//只能Send u8類型的,故不能把SW一次傳輸完
        //XUartLite_Send(&UART,&SW8_2,1);
        //Xil_Out8(0X40040000+0X8,SW8_2);//LEDS  :  0X40040000~0x4004FFFF
    }
////DA///////////////////////////////////////////////////////////////////
    if(SW==0x1||SW==0x4) JuChiBo(T,Amplitude);
////AD///////////////////////////////////////////////////////////////////
     if(SW==0x2) ADC();
}
 
    return 0;
}
 
void Initialize(void)
{
    init_platform();
    XIntc_Initialize(&IntCtrl , XPAR_INTC_DEVICE_ID);
////TIMER////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    XTmrCtr_Initialize(&TimerCounterInst, XPAR_TMRCTR_0_DEVICE_ID);//XPAR_TMRCTR_0_DEVICE_ID
    XTmrCtr_SetHandler(&TimerCounterInst, TimerCounterHandler , &TimerCounterInst);
    XTmrCtr_SetOptions(&TimerCounterInst, 0,XTC_INT_MODE_OPTION|XTC_AUTO_RELOAD_OPTION| XTC_DOWN_COUNT_OPTION);
    XTmrCtr_SetResetValue(&TimerCounterInst , 0, 0x00f4240);//0xf4240是1000 000
    XIntc_Enable(&IntCtrl , XPAR_INTC_0_TMRCTR_0_VEC_ID);//TMRCTR_Interruppt_ID
    XIntc_Connect (&IntCtrl,XPAR_INTC_0_TMRCTR_0_VEC_ID,(XInterruptHandler)XTmrCtr_InterruptHandler ,(void*)&TimerCounterInst);
 
////UART////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    XUartLite_Initialize(&UART,XPAR_UART_DEVICE_ID);
    XUartLite_ResetFifos(&UART);
    while(XUartLite_IsTransmitFull(XPAR_UART_DEVICE_ID));
    XUartLite_Send(&UART,buf,27);
    XUartLite_EnableInterrupt(&UART);
    XIntc_Connect (&IntCtrl,XPAR_INTC_0_UARTLITE_2_VEC_ID,(XInterruptHandler)Uart_Handler,(void*)&UART);
 
////SPI/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    XSpi_Initialize(&SPiInstance,XPAR_SPI_0_DEVICE_ID);
    XIntc_Connect (&IntCtrl,XPAR_INTC_0_SPI_0_VEC_ID,(XInterruptHandler)XSpi_InterruptHandler,(void*)&SPiInstance);
    XSpi_SetStatusHandler(&SPiInstance,&SPiInstance,(XSpi_StatusHandler)SpiIntrHandler);
    XSpi_SetOptions(&SPiInstance,XSP_MASTER_OPTION|XSP_CLK_PHASE_1_OPTION);
    XSpi_SetSlaveSelect(&SPiInstance,1);
 
////Btn_SW////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    XGpio_Initialize(&Btn_SW , XPAR_BTN_SW_DEVICE_ID);
    XGpio_SetDataDirection(&Btn_SW,1,0xffff);//通道1
    XGpio_SetDataDirection(&Btn_SW,2,0xf);//通道2
    XGpio_InterruptEnable(&Btn_SW,1);
    XGpio_InterruptEnable(&Btn_SW,2);
    XGpio_InterruptGlobalEnable(&Btn_SW);
    XIntc_Connect (&IntCtrl,XPAR_INTC_0_GPIO_0_VEC_ID,(XInterruptHandler)Btn_SWHandler,(void*)&Btn_SW);
 
////LED///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    XGpio_Initialize(&LED ,  XPAR_LEDS_DEVICE_ID);
    XGpio_SetDataDirection(&LED,1,0x0000);//通道
 
////INTC//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    XIntc_Enable(&IntCtrl,0);//Timer
    XIntc_Enable(&IntCtrl,1);//Btn_SW
    XIntc_Enable(&IntCtrl,2);//UART
    XIntc_Enable(&IntCtrl,3);//SPI
    microblaze_enable_interrupts();
    microblaze_register_handler((XInterruptHandler)XIntc_InterruptHandler,(void*)&IntCtrl);
 
    XIntc_Start(&IntCtrl,XIN_REAL_MODE);
    XTmrCtr_Start(&TimerCounterInst,0);
    XSpi_Start(&SPiInstance);
}
 
//void My_ISR(void)
//{
//    int status;
//    status = Xil_In32(XPAR_INTC_BASEADDR+0x00);//終端控制器中斷狀態寄存器偏移地址
//    if(status&0x8)
//    {
//        Uart_Handler();
//    }
//    Xil_Out32(XPAR_INTC_BASEADDR+0X0C,status);//清除INTC中斷
//}
void Uart_Handler(void)
{
    int flag_UART;
    flag_UART=Xil_In32(XPAR_UART_BASEADDR+0X08);//狀態寄存器的偏移地址是0X08第8位是奇偶校驗,錯就返回1
    if(flag_UART&0X01)
    {
        flag_RX = 1;
        //RX_data = Xil_In32(XPAR_UART_BASEADDR+0X00);//數據寄存器的偏移地址是0X00
        //print("in the intr\r\n");
        //Xil_Out8(XPAR_GPIO_1_BASEADDR,RX_data);
    }
    //Xil_Out32(XPAR_UART_BASEADDR+0x0c,0X13);//clear fifo,0x0c是控制寄存器的偏移地址c=12,0x13=0001 0011
}
 
void SpiIntrHandler(void *CallBackRef ,u32 StatusEvent ,u32 ByteCount)
{
    TransferProgress=FALSE;
    //print("in spi intr\r\n");
    if(StatusEvent != XST_SPI_TRANSFER_DONE)
    Error++;
}
 
void JuChiBo(int T,int Amplitude)
{
     WriteBuffer[0]=(u8)(count);
     WriteBuffer[1]=(u8)(count>>8)&0xf;
     if(SW==0X4)
     {
         count=count+T*3;
     }
     else count=count+T;
     if(count>Amplitude) count = 0;
     TransferProgress = TRUE;
     XSpi_Transfer(&SPiInstance , WriteBuffer,ReadBuffer , 2);
     Voltage=ReadBuffer[1];
     Voltage=Voltage<<8;
     Voltage=Voltage+ReadBuffer[0];
     Voltage=Voltage<<4;
     Voltage=Voltage>>4;
     while(TransferProgress);
     if(time_10ms_DAC>100){time_10ms_DAC=0; xil_printf("DAC\r\n");xil_printf("ADC data is 0x%X\r\n",Voltage);}
}
void ADC(void)
{
     TransferProgress = TRUE;
     XSpi_Transfer(&SPiInstance , WriteBuffer , ReadBuffer , 2);
     while(TransferProgress);
     Voltage=ReadBuffer[1];
     Voltage=Voltage<<8;
     Voltage=Voltage+ReadBuffer[0];
     Voltage=Voltage<<4;
     Voltage=Voltage>>4;
     if(time_10ms_ADC>100){ time_10ms_ADC=0; xil_printf("ADC data is 0x%X\r\n",Voltage);     xil_printf("ADC\r\n");}
}
void Btn_SWHandler(void*CallBackRef)//chinnel1是SW。2是Btn
{
//////////////Btn//////////////////////////////////////////////////////////////////////
///
    Btn_pre=Btn;
    Btn=XGpio_DiscreteRead(&Btn_SW,2);
    if(Btn_pre==Btn){flag_Btn=0;}
    else{
    flag_Btn=1;
    XGpio_InterruptDisable(&Btn_SW,2);
    delay_ms(30);
    }
//    xil_printf("In the INTC of GPIO\r\n");
/////////////SW////////////////////////////////////////////////////////////////////////////
////                                                                                //////
    SW_pre=SW;
    SW=XGpio_DiscreteRead(&Btn_SW,1);
    if(SW_pre==SW){flag_SW=0;}//如果這次的開關值跟上次一樣,就不立flag,防止因為Btn的觸發導致SW的誤觸發
    else
    {
    flag_SW=1;
    }
    XGpio_InterruptClear(&Btn_SW,2);
    XGpio_InterruptClear(&Btn_SW,1);
    XGpio_InterruptEnable(&Btn_SW,2);
 
}
void TimerCounterHandler(void* CallBackRef , u8 TmrCtrNumber)
{
    time_10ms1++;
    time_10ms2++;
    time_10ms3++;
    time_10ms_ADC++;
    time_10ms_DAC++;
}
void delay_ms(u32 t)
{
    int i;
    for(i=0;i<100000*t;i++);
}

MicroBlaze核的串行接口實驗:SPI UART