⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 niosii_uart.c

📁 基于NIOSII的UART的原代码
💻 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_AVAL_UART_CONTROL(UART_0_BASE, 0x80|0x10);
  
    //循环等待处理串口数据
    while(1) 
    {
       //处理串口接收数据
       if(!_bufdone())
             break;
    }
  
    //关闭串口中断
   /// na_uart1->np_uartcontrol = 0;
      IOWR_ALTERA_LON_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 !Head)
  {
    //如果检测到键盘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; //如果照到帧头字符,进入下一个接收状态
             bre
      case 1://已接收到帧头字符
    
          Code = RxBuf[RxTail];
          if (Code != 's' && Code != 'S' &&
              Code != 'x' && Code != 'X' &&
              Code != 'd' && Code != 'D' )
          {
            RevStatus = 0;  //接收到无效命令字符,返回到初始状态
          _puts("\nIalid 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 (Framndex >= 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 (FrameInd= 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
                   {
                     Shex = 1;   //打开ASCII码显示功能
                 _puts("ON\n");
                 }
               }
             break;
             default:  //无效的命令字符
                       _puts("\nInvalid command code.\n");
                       RevStatus = 0;     //回到初始状态
               FrameIndex = 0;    //FrameData数组索引清零
             break;
         }
         break;
        }
        
        //处理下一个接收字符,如果已到达接收缓冲区尾部,返回接收缓冲区头部
        if  (++RxTail > (RXBUFSIZE - 1))
             RxTail =
    }

    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 = - 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_AVON_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指针指向下一个字符
        cot++;              //成功发送,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_ALTAVALON_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 ((++) > (RXBUFSIZE - 1))
      {
        //如果RxHead索引值已到数组末尾,返回数组头部
      RxHead = 0;
    }
    
    //串口状态寄存器清零
    ///na_uart1->np_uartstatus = 0;
            IOWR_ALERA_AVALON_UART_STATUS(UART_0_BASE, 0);
     }  //接收中断处理完成
}















⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -