英创信息技术用GPIO实现多路外部中断及脉冲计数简介

描述

英创工控主板都给用户提供了丰富的GPIO资源,在ESMARC系列的板卡上配置了32位GPIO,GPIO(General-purpose input/output)即通用输入输出,在实际使用中有多种用途,而作为外部中断输入便是较常用的功能,通过对外部输入中断的响应,可以满足多种应用需求,脉冲计数就是一种典型的应用。英创主板已经给用户提供了两路中断功能,是采用异步IO的方式,电平上升沿触发中断,通过信号量SIGIO通知应用程序,关于详细的资料可以参考网站:《ESM335x外部中断输入应用》。

为了让用户能够使用到更多外部输入中断,英创公司进一步在驱动中增加了相应的功能和接口,利用IO多路复用的技术让所有GPIO都能够作为外部中断输入,通过程序设置使能,一旦管脚电平发生变化,内核就会通知应用程序,这时使用select或者poll函数就可以接收到内核发出的消息。通过这种方式,用户可以将主板的32位GPIO全部作为外部中断输入,而原来提供的采用异步IO方式的两路中断我们原则上就不再做更新和维护,建议客户使用我们最新提供的方法。下面就以两路GPIO的脉冲计数功能为例,介绍如何通过select或者poll函数实现外部中断响应。

首先要启用中断输入功能,这一步需要调用英创公司提供的设置GPIO为输入状态的API函数来实现。也就是在程序中调用一次函数,设置GPIO为输入状态,就能把对应的GPIO管脚设置为外部中断输入功能,如设置GPIO0和GPIO23为中断输入,代码如下:

int GPIO_OutDisable(fd, GPIO0 | GPIO23)

当设置完成后,GPIO作为输入状态,同时会监测外部输入电平变化,并通过内核驱动通知应用层。应用程序使用select或者poll函数来监听GPIO的句柄的读事件就能够获取到通知,用户可以通过多线程的方式来实现,通过select函数实现代码如下:

  while( 1 )
{
//设置读事件
FD_ZERO(&fdRead);
FD_SET(fd,&fdRead);
//设置超时时间
aTime.tv_sec = 0;
aTime.tv_usec = 20000;
ret = select(fd+1,&fdRead,NULL,NULL,&aTime);
              if (ret < 0 )
              {
                     printf("error!\n");
                     break;
              }
              if (ret > 0)
              {
                     //判断是否读事件
                     if (FD_ISSET(fd,&fdRead))
                     {
                            dwPinState = GPIO0 | GPIO23;
                            rc = GPIO_PinState(fds.fd, &dwPinState);
                            if(rc< 0)
                            {
                                   printf("GPIO_PinState::failed %d\n", rc);
                                   returnrc;
                            }
//根据上升沿对脉冲计数
                            if(dwPinState& GPIO0)
                                   pulse1_num++;
                            if(dwPinState& GPIO23)
                                   pulse2_num++;
//计数到500就退出
                            if(pulse1_num == 500 && pulse2_num == 500)
                            {
                                   printf("the pules number is 500\n");
                                   break;
                            }
                     }
             }
      }
     close(fd);
      return 0;

使用poll函数也是类似的,同样的需要先使能GPIO的外部中断输入功能,即调用一次设置GPIO为输入状态的函数,然后使用poll函数来监听GPIO的句柄的读事件就能够获取到通知,具体代码如下:

  while(1)
       {
              structpollfdfds;
              int timeout;
//设置监听句柄
              fds.fd = fd;
//设置读事件
              fds.events = POLLIN;
//设置超时时间
              timeout = 20000;
              ret = poll(&fds, 1, timeout);
              if (ret < 0 )
              {
                     printf("error!\n");
                     break;
              }
              if (ret > 0)
              {
                     //判断是否读事件
                     if (fds.revents == POLLIN)
                     {
                            dwPinState = GPIO0 | GPIO23;
                            rc = GPIO_PinState(fds.fd, &dwPinState);
                            if(rc< 0)
                            {
                                   printf("GPIO_PinState::failed %d\n", rc);
                                   returnrc;
                            }
//根据上升沿对脉冲计数
                            if(dwPinState& GPIO0)
                                   pulse1_num++;
                            if(dwPinState& GPIO23)
                                   pulse2_num++;
//计数到500就退出
                            if(pulse1_num == 500 && pulse2_num == 500)
                            {
                                   printf("the pules number is 500\n");
                                   break;
                            }
                     }
              }
      }
     close(fd);
      return 0;

当输入电平发生变化,select和poll函数侦测到读事件,就可以进行相应的操作,示例代码通过判断上升沿来计数脉冲数,经过测试,上述代码能对两路2KHz的脉冲实现可靠计数。用户还可以根据实际的应用需求,把上述代码修改为支持多路脉冲计数功能。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分