首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >STM8脉冲计数器

STM8脉冲计数器
EN

Stack Overflow用户
提问于 2021-01-06 05:06:59
回答 3查看 417关注 0票数 0

我正在开发一种直流电机的控制器。这台马达有一个编码器,根据它的运动产生脉冲。

我需要通过监测脉冲数来控制电机轴的圈数。

我在这个应用程序中使用SMT8S103F3。

这个想法是使用Timer1作为脉冲计数器。为此,我将定时器配置为接收外部信号,在本例中为编码器脉冲,并且随着每个脉冲,计数器必须递增。

我遵循了文档ST RM0016的第17.4.3章。但是,应用程序无法正常工作。计数器没有递增。

遵循开发的代码。

代码语言:javascript
复制
void config_counter(){
  TIM1_PSCRH = 0;
  TIM1_PSCRL = 0; //Prescalar 1 division
  TIM1_ARRH = 0;
  TIM1_ARRL = 0;  //Auto counter disabled
  TIM1_CNTRH = 0;
  TIM1_CNTRL = 0; //Reset counter
  TIM1_IER = 0; //Interrupt disabled
  TIM1_SR1 = 0; //Clear Interrupt
  TIM1_CCMR2 |= 1<<0; //External pulse source T1C2
  TIM1_CCER1 |= ~(1<<5); //Rising edge
  TIM1_SMCR |= 3; //T1C2 input
  TIM1_CR1 |= ~(1<<0); //Counter disabled
  
  return;
}

void set_counter_enable(uint8_t enable){
  if(enable==1)
    TIM1_CR1 |= 1<<0;
  else
    TIM1_CR1 |= ~(1<<0);

  return;
}

void set_counter_updown(uint8_t updown){
  if(updown==1)
    TIM1_CR1 |= ~(1<<4);
  else
    TIM1_CR1 |= 1<<4;

  return;
}

uint8_t start_movement_monitor(uint8_t dir){

  while(1){
    if(dir == 1){
      if(((TIM1_CNTRH<<8)+TIM1_CNTRL)>200)
        return 1;
    }else if(dir == 2){
      if(((TIM1_CNTRH<<8)+TIM1_CNTRL)<50)
        return 1;
    }
    else{
      return 1;
    }
  }

  return 1;
}


int main() {

  config_gpio();
  config_counter();
  set_counter_updown(0);
  set_counter_enable(0);

  set_counter_enable(1);
  set_motor_enable(1);
  set_motor_movement(1);

  start_movement_monitor(1);

  set_motor_movement(0);
  set_motor_enable(0);
  set_counter_enable(0);
  return 0;
}

有什么想法吗?

如果定时器不是此应用的最佳选择,如何实现脉冲计数器?

脉冲频率为700 The。

EN

回答 3

Stack Overflow用户

发布于 2021-01-07 03:24:35

解决了。

要在stm8引脚上使用定时器,必须写入选项字节以改变引脚的功能。这是通过编写AFR0实现的。

使用定时器1通道2的定时器配置如下。

代码语言:javascript
复制
void config_counter(){
  TIM1_CNTRH = 0;
  TIM1_CNTRL = 0; //Reset counter
  TIM1_IER = 0; //Interrupt disabled
  TIM1_SR1 = 0; //Clear Interrupt
  TIM1_CCMR2 |= 1<<0; //External pulse source T1C2
  TIM1_CCER1 &= ~(1<<5); //Rising edge
  TIM1_SMCR |= (7<<0); //External Clock Source
  TIM1_SMCR |= (6<<4); //T1C2 Input Source
  TIM1_CR1 &= ~(1<<0); //Counter disabled
  
  return;
}
票数 1
EN

Stack Overflow用户

发布于 2021-01-06 06:36:42

TIM1_CR1 |= ~(1<<0); //Counter disabled不会禁用计数器。它保持CEN不变,并将包括OPM在内的所有其他位设置为1。您需要的是&=set_counter_updown也是如此。

票数 0
EN

Stack Overflow用户

发布于 2021-01-06 09:45:35

这个问题有两种可能的解决方案。

定时器的解决方案要求定时器的时钟输入与电机脉冲关联,这需要一些外部硬件连接,我不知道您是否有可用的外部硬件连接。这样做的好处是,您可以只读取计时器值来了解圈数,并且使用预分频器可以缩放您的输入。缺点是定时器的数量通常是有限的(您只有一个或两个定时器),而且定时器总是配置为计算电机转数,并且您不能将其用于其他事情。

另一种解决方案是为电机脉冲关联一条中断线路,并对中断处理程序进行编程。您需要(通过硬件)将中断关联到电机脉冲,因此当您接收到中断时,中断处理程序会递增一个变量。

一旦你有了这个...你只需要检查变量的值是什么,因为变量的更新只是反映了电机转动了多少次。

代码语言:javascript
复制
volatile long loops = 0;

void motor_pulse_handler()
{
    loops++;
}

int main()
{
    /* this function installs the handler to be called each time the motor starts a new turn. */
    install_handler(MOTOR_PULSE_INTERRUPT, motor_pulse_handler);
    ...
    for (;;) {
        printf("\rloops: %ld", loops);
        usleep(10000);
    }
}     

函数install_handler是强烈依赖于硬件的函数。它通常由开发系统作为库函数提供,因为它需要了解一点处理器体系结构才能实现。在操作与中断相关的控件时,首先需要完全禁用中断。然后,它必须被激活,以便中央处理器在相应的中断线上的一个脉冲上被中断(这就是在参数列表中包括一个MOTOR_PULSE_INTERRUPT的原因,它应该是具有适当值的#defined,以使电机脉冲成为所选信号,而不是其它信号)。最后,它必须再次使能中断。当中断到来时,您的函数将在处理器可以执行的一系列操作的中间被调用。

通常,安装中断处理程序是一个两阶段的过程。实际调用的例程不是传递给install_handler的例程,而是执行一些硬件操作的不同例程。在禁止中断的情况下调用中断处理程序,它应该:

  • 保存所有cpu状态(寄存器、标志等),以便在结束时可以恢复状态。
  • 屏蔽此设备的中断,因此它不会再次中断(中断尚未向设备确认,因此如果启用中断,cpu将再次中断)
  • enable中断,以便从此时起其他更高优先级的中断可以中断cpu。
  • 调用用户中断处理程序,因此计数器可以updated.
  • disable interrupts again.
  • acknowledge the interrupt。这通常意味着读取一些芯片寄存器,以向中断硬件指示该中断已被确认。当你从interrupt.
  • restore寄存器和标志(所有的cpu状态)返回时,这会重置设备,这样它就不会因为同样的原因再次中断,这样我们就可以返回到cpu interrupted.
  • do a return from interrupt的位置。这通常是一个特殊的返回指令(不是用于从正常函数调用返回的指令)

此解决方案的优点是您可以卸载信号处理程序,这将停止计数过程。同样,只有在实现某种机制来路由中断的情况下,才能将中断行重用于其他事情(此问题类似于计时器中的问题,其中脉冲到达所选计时器的输入)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65586571

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档