//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_UA