?? 串口中斷_niosii.c
字號:
//www.21control.com
//#include <stdio.h>
#include "system.h"
#include <alt_types.h>
#include "sys/alt_irq.h"
#include "altera_avalon_uart_regs.h"
#include "altera_avalon_uart.h"
//接收\發送緩沖大小
#define TXBUFSIZE 256
#define RXBUFSIZE 256
//全局變量
unsigned char RxBuf[RXBUFSIZE]; //接收緩沖
int RxHead =0; //接收緩沖位置索引 頭
int RxTail =0; //接收緩沖位置索引 尾
unsigned char TxBuf[TXBUFSIZE]; //發送緩沖
int TxHead =0; //發送緩沖位置索引 頭
int TxTail =0; //發送緩沖位置索引 尾
int RevStatus = 0; //接收幀狀態,0空閑,1收到幀頭,2收到命令碼
unsigned char Code = 0; //命令碼,0空閑,'s'字符串,'x'十六進制,'d'切換顯示
unsigned char FrameData[255]; //幀數據
int FrameIndex = 0; //幀位置索引
int ShowHex = 0; //是否顯示十六進制碼
int _putchar(int in_char); //發送一個數據
int _puts(unsigned char* str); //發送一串數據
void serial_ISR(int context); //串口中斷服務子程序
int _bufdone(); //處理接收緩沖區數據流
//main 主程序
int main()
{
int context = 0;
// _putchar('o');
//安裝串口中斷服務子程序
// / nr_installuserisr(na_uart1_irq, serial_ISR, context);
alt_irq_register(UART_0_IRQ,context,serial_ISR);
//使能串口接收中斷
///na_uart1->np_uartcontrol = np_uartcontrol_irrdy_mask;
IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80|0x10);
//循環等待處理串口數據
while(1)
{
//處理串口接收數據
if(!_bufdone())
break;
}
//關閉串口中斷
/// na_uart1->np_uartcontrol = 0;
IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE,0);
//卸載串口中斷服務程序
///nr_installuserisr(na_uart1_irq, 0, 0);
// alt_irq_register(UART_0_IRQ,0,0);
//退出程序,\004即Ctrl-D,表示已結束
printf("\n\004");
}
//_bufdone子程序,處理串口接收緩沖區數據
//返回值0表示接收到退出程序命令,1表示數據處理正常
int _bufdone()
{
//循環檢測緩沖區是否為空
//當RxTail等于RxHead時,表示已處理完接收緩沖區中數據,亦即緩沖區為空
while (RxTail != RxHead)
{
//如果檢測到鍵盤ESC鍵值,函數返回0,提示退出程序
if (RxBuf[RxTail] == 27)
{
_puts("\nExit uart_isr_test.\n");
// nr_delay(10);
return 0;
}
//接收幀狀態處理
switch (RevStatus)
{
default:
case 0://接收幀空閑狀態
if (RxBuf[RxTail] == '-')
RevStatus = 1; //如果照到幀頭字符,進入下一個接收狀態
break;
case 1://已接收到幀頭字符
Code = RxBuf[RxTail];
if (Code != 's' && Code != 'S' &&
Code != 'x' && Code != 'X' &&
Code != 'd' && Code != 'D' )
{
RevStatus = 0; //接收到無效命令字符,返回到初始狀態
_puts("\nInvalid frame.\n");
}
else
RevStatus = 2; //接收命令有效,進入下一個接收狀態
break;
case 2://接收到有效命令字符
//根據不同命令字符,執行相應操作
switch (Code)
{
case 's': case 'S': // -s命令幀
*(unsigned int *)LED_BASE =0x01;
//將接收字符存入FrameData數組
FrameData[FrameIndex++] = RxBuf[RxTail];
if (FrameIndex >= 254 || RxBuf[RxTail] == '\n')
{
//數組已滿或收到回車換行符時,輸出FrameData字符串
FrameData[FrameIndex] = '\0';
_puts(FrameData);
RevStatus = 0; //回到初始狀態,準備接收下一幀
FrameIndex = 0; //FrameData數組索引清零
}
break;
case 'x': case 'X': // -x命令幀
*(unsigned int *)LED_BASE =0x02;
//存入接收字符的ASCII碼表示,例如字符'0'將存入"30"
FrameData[FrameIndex++] = (RxBuf[RxTail]>>4) + '0';
FrameData[FrameIndex++] = (RxBuf[RxTail] & 0x0F) + (((RxBuf[RxTail] & 0x0F) > 9) ? ('A' - 10) : '0');
//每兩個ASCII字符表示間添加空格
FrameData[FrameIndex++] = ' ';
if (FrameIndex >= 252 || RxBuf[RxTail] == '\n')
{
//數組已滿或收到回車換行符時,輸出FrameData字符串
FrameData[FrameIndex] = '\0';
_puts(FrameData);
_puts("\n");
RevStatus = 0; //回到初始狀態,準備接收下一幀
FrameIndex = 0; //FrameData數組索引清零
}
break;
case 'd': case 'D': // -d命令幀
//存入接收字符到FrameData數組
FrameData[FrameIndex++] = RxBuf[RxTail];
if (FrameIndex >= 252 || RxBuf[RxTail] == '\n')
{
//數組已滿或收到回車換行符時,輸出FrameData字符串
FrameData[FrameIndex] = '\0';
_puts(FrameData);
RevStatus = 0; //回到初始狀態,準備接收下一幀
FrameIndex = 0; //FrameData數組索引清零
//切換輸入字符ASCII碼顯示功能
if (ShowHex > 0)
{
ShowHex = 0; //關閉ASCII碼顯示功能
_puts("\n-d OFF\n");
}
else
{
ShowHex = 1; //打開ASCII碼顯示功能
_puts("ON\n");
}
}
break;
default: //無效的命令字符
_puts("\nInvalid command code.\n");
RevStatus = 0; //回到初始狀態
FrameIndex = 0; //FrameData數組索引清零
break;
}
break;
}
//處理下一個接收字符,如果已到達接收緩沖區尾部,返回接收緩沖區頭部
if (++RxTail > (RXBUFSIZE - 1))
RxTail = 0;
}
return 1;
}
//_putchar子程序,向串口發送一個字符數據in_char
//返回值1表示發送成功,-1表示發送失敗
int _putchar(int in_char)
{
//發送緩沖區已用空間大小
int size;
//獲取狀態寄存器的值
///int sr = na_uart1->np_uartstatus;
int sr = IORD_ALTERA_AVALON_UART_STATUS(UART_0_BASE);
//判斷發送緩沖區是否為空并且串口狀態是否已準備好發送
if ((TxHead == TxTail) && sr&0x40)
{
//發送緩沖區為空,直接發送數據in_char
IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE,in_char);
}
else
{
//計算發送緩沖區已用空間大小
if (TxHead >= TxTail)
size = TxHead - TxTail;
else
size = ((TXBUFSIZE - 1) - TxTail) + TxHead; //循環隊列
//如果發送緩沖區已滿,發送失敗,直接返回
if (size > (TXBUFSIZE - 3))
return (-1);
//將待發送數據追加到發送緩沖區中的數據流末尾
TxBuf[TxHead] = in_char;
if (++TxHead >(TXBUFSIZE - 1))
TxHead = 0;
//使能itrdy中斷
IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x40|0x10);//開發送中斷,中斷使能
}
return 1;
}
//_puts子程序,向串口發送一個字符串str
//返回值count表示已發送的字符個數
int _puts(unsigned char *str)
{
//發送字符計數
int count = 0;
//字符指針,指向str字符串中當前發送字符
unsigned char *tmp = str;
//判斷tmp是否已到str字符串結尾
while (*tmp != 0)
{
if (_putchar(*tmp++) >0) //發送當前字符,并且tmp指針指向下一個字符
count++; //成功發送,count計數加1
else
break; //發送失敗,跳出while循環
}
return count;
}
//serial_ISR子程序,串口中斷服務子程序
void serial_ISR(int data)
{
//保存狀態寄存器數值
int sr = IORD_ALTERA_AVALON_UART_STATUS (UART_0_BASE);
int si = IORD_ALTERA_AVALON_UART_CONTROL (UART_0_BASE);
//發送中斷處理
if(sr & ALTERA_AVALON_UART_STATUS_TRDY_MSK)
{
//串口發送端已準備好
///if(na_uart1->np_uartcontrol & np_uartcontrol_itrdy_mask)
if(si & ALTERA_AVALON_UART_CONTROL_TRDY_MSK)
{
//如果itrdy中斷已打開,判斷發送緩沖區是否為空
if (TxTail != TxHead)
{
//如果發送緩沖區中還有發送數據,發送一個字節數據
IOWR_ALTERA_AVALON_UART_TXDATA(UART_0_BASE ,TxBuf[TxTail]);
//如果已到達數組尾部,TxTail索引值返回數組頭部
if (++TxTail > (TXBUFSIZE - 1))
TxTail = 0;
}
else
{ //已經沒有待發送數據,關閉發送中斷,使能接收中斷
///na_uart1->np_uartcontrol = np_uartcontrol_irrdy_mask;
IOWR_ALTERA_AVALON_UART_CONTROL(UART_0_BASE, 0x80|0x10);//開發送中斷,中斷使能
}
}
} //發送中斷處理完成
//接收中斷處理
if(sr & ALTERA_AVALON_UART_STATUS_RRDY_MSK)
{
//串口接收端收到新數據,將其放入接收緩沖區數據流末尾
//RxBuf[RxHead] = na_uart1->np_uartrxdata;
RxBuf[RxHead] = IORD_ALTERA_AVALON_UART_RXDATA(UART_0_BASE);
//接收字符回顯
_putchar(RxBuf[RxHead]);
//顯示接收字符ASCII碼(十六進制)
if (ShowHex)
printf("\n%02X\n" , RxBuf[RxHead]);
if ((++RxHead) > (RXBUFSIZE - 1))
{
//如果RxHead索引值已到數組末尾,返回數組頭部
RxHead = 0;
}
//串口狀態寄存器清零
///na_uart1->np_uartstatus = 0;
IOWR_ALTERA_AVALON_UART_STATUS(UART_0_BASE, 0);
} //接收中斷處理完成
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -