Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C STM8脉冲计数器_C_Encoder_Stm8 - Fatal编程技术网

C STM8脉冲计数器

C STM8脉冲计数器,c,encoder,stm8,C,Encoder,Stm8,我正在为直流电机开发一个控制器。该电机有一个编码器,根据其运动产生脉冲 我需要通过监测脉冲数来控制电机轴的转动次数 我将SMT8S103F3用于此应用程序 其想法是使用定时器1作为脉冲计数器。为此,我将定时器配置为接收外部信号,在这种情况下,编码器脉冲,每个脉冲都必须增加计数器 我遵循文件ST RM0016第17.4.3章。但是,该应用程序不起作用。计数器没有递增 遵循开发的代码 void config_counter(){ TIM1_PSCRH = 0; TIM1_PSCRL = 0;

我正在为直流电机开发一个控制器。该电机有一个编码器,根据其运动产生脉冲

我需要通过监测脉冲数来控制电机轴的转动次数

我将SMT8S103F3用于此应用程序

其想法是使用定时器1作为脉冲计数器。为此,我将定时器配置为接收外部信号,在这种情况下,编码器脉冲,每个脉冲都必须增加计数器

我遵循文件ST RM0016第17.4.3章。但是,该应用程序不起作用。计数器没有递增

遵循开发的代码

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;
}

void配置_计数器(){
TIM1_PSCRH=0;
TIM1_PSCRL=0;//预分频器1除法
TIM1_ARRH=0;
TIM1_ARRL=0;//自动计数器已禁用
TIM1_CNTRH=0;
TIM1_CNTRL=0;//重置计数器
TIM1_IER=0;//中断已禁用
TIM1_SR1=0;//清除中断

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

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

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

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

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\u handler
是一个强烈依赖于硬件的函数。它通常由开发系统作为库函数提供,因为它需要了解一点处理器体系结构才能实现。在操作中断相关的c时,首先需要完全禁用中断控制。然后它必须激活,cpu才能在相应中断行中的脉冲上被中断(这是在参数列表中包括
电机脉冲中断的原因,这应该是
#使用适当的值定义
d,使电机脉冲成为所选信号,而不是其他信号)最后,它再次启用中断。当一个中断进来时,你的函数将被调用在处理器可以做的事情的中间。
通常,安装中断处理程序是一个两阶段的过程。实际调用的例程不是传递给
install\u handler
的例程,而是执行某些硬件操作的不同例程。在中断被禁止的情况下调用中断处理程序,它应该:

  • 保存所有cpu状态(寄存器、标志等),以便在结束时恢复状态
  • 屏蔽此设备的中断,因此不会再次中断(中断尚未被设备确认,因此如果启用中断,cpu将再次中断)
  • 启用中断,以便其他更高优先级的中断可以从此点开始中断cpu
  • 调用用户中断处理程序,以便更新计数器
  • 再次禁用中断
  • 确认中断。这通常意味着读取一些芯片寄存器,以向中断硬件指示该中断已被确认。这将重置设备,以便当您从中断返回时,设备不会因相同原因再次中断
  • 恢复寄存器和标志(所有cpu状态),以便我们可以返回到cpu中断的点
  • 从中断返回。这通常是一个特殊的返回指令(不是用于从正常函数调用返回的指令)
此解决方案的优点是,您可以卸载信号处理程序,这将停止计数过程。同样,只有在实现某种机制来路由中断时,才有可能将中断线用于其他用途(此问题类似于计时器中的问题,其中脉冲到达所选计时器的输入)

已解决

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

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

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;
}

void配置_计数器(){
TIM1_CNTRH=0;
TIM1_CNTRL=0;//重置计数器
TIM1_IER=0;//中断已禁用
TIM1_SR1=0;//清除中断

TIM1_CCMR2 |=1我对STM8s不太熟悉,因为我刚刚从袋子里取出了第一块STM硅(stm32).我注意到16mhz设备上的700khz约为每22个时钟运行一次,不禁怀疑更改中断是否会更好。你是对的。但它仍然不起作用。计时器配置中还有另一个错误。TIM1_SMCR |=(7)TIM1_SMCR中存在配置错误。但更改不起作用。是否应写入选项字节AFR0以启用输入计时器?我使用中断对脉冲进行计数,但效果不好。计数返回错误。我怀疑这是由于脉冲的速度。因此,我尝试使用计时器。