历史上的今天
返回首页

历史上的今天

今天是:2024年09月16日(星期一)

2018年09月16日 | 关于STM32的编码器计数及溢出处理调试总结

2018-09-16 来源:eefocus

错误1、pc6 pc7被用作其他用途,GPIO模式配置错误。导致计数不准确;

错误2、引脚模式设置错误,应该设置为GPIO_Mode_IPD;//GPIO_Mode_IPU GPIO_Mode_IN_FLOATING  都可以;

错误3  引脚重映射没有开启AFIO时钟;

总结

关于编码器的溢出处理:

网上的检测数值突变的方法不可靠,会有漏检的情况。在滴答定时器中检测encoder的值突变

void SysTick_Handler(void)

{// systick中断,1ms一次

 static int encoder[2] = {0 , 0};// 两次编码器读值,用以计算溢出方向

 static int N = 0;// 圈数

 encoder[1] = TIM3->CNT;

  if((encoder[1] - encoder[0] ) > 0x7FFF)

  {

    N--;

  }

 else if( (encoder[0] - encoder[1] ) > 0x7FFF)

  {

   N++;

  }

 EncCnt = N * 0xFFFF + encoder[1];

 encoder[0] = encoder[1];

}

 

我采用了两种方法处理:一种是采用另一个定时器实时的检测溢出标志及方向标志,这种方法是可行的。即使速度很快的时候依然计数准确。但是出现了新的问题,用作定时器的时钟,当定时周期设置的很小的时候才可以计数准确,但是由于中断的优先级高,导致无法进入主循环程序。附上检测代码。这样的处理方法,在速度慢的时候可以检测正确。但是定时周期要设置足够小。CR1的bit4代表计数方向标志,1代表减二代表加;SR的bit0代表溢出中断标志,1代表溢出。该位是硬件置1软件清零。另一种是使用编码器溢出中断。中断的时候对编码器溢出方向进行判断,然后根据方向进行累加。

void TIM2_IRQHandler(void)

{

      

   if ( TIM_GetITStatus(TIM2 , TIM_IT_Update) != RESET )

    {

       TIM_ClearITPendingBit(TIM2 , TIM_FLAG_Update);

                           

              encoder= TIM3->CNT;

          if((TIM3->CR1&0x10) == 0x10)//向下计数

          {          

               if(TIM3->SR&0x01 == 0x01)//tim3计数溢出

                 {

                            TIM3->SR= TIM3->SR&0xFE;//sr的bit0清零

                            N--;

                     }                    

          }

          else if((TIM3->CR1&0x10) == 0x00)//向上计数

          {

               if(TIM3->SR&0x01 == 0x01)//tim3计数溢出

                 {

                            TIM3->SR= TIM3->SR&0xFE;//sr的bit0清零

                            N++;

                     }                   

          }

              EncCnt= N * 65536 + TIM3->CNT;  

          //        encoder[0] = encoder[1];

       }                

      

}

 

最后,我找到了更简单的检测编码器溢出中断并进行累计的方法。

其实当编码器的定时器溢出的时候,会导致进入中断。这样直接用编码器的中断函数即可。但是需要注意的是,需要在编码器的定时器配置的时候,配置中断。如果不配置,就会导致程序一运行就死机。一直停在DMA2_Channel4_5_IRQHandler这一句。

附上最终测试验证完成的代码

编码器初始化配置 ( 注意。如果不适用中断溢出的方法,无需配置

NVIC_InitStructure.NVIC_IRQChannel =TIM3_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

这部分。。。)

并且我适用的是tim3重定义到pc7  pc6的。也可以使用部分重映射和默认引脚。

void EncoderTimInit()

{

//     对TIM_ICInitStructure的配置和对TIM_EncoderInterfaceConfig函数的使用实际上是冲突的,两个语句中的极性的设置是重复的

       //--------------1

       GPIO_InitTypeDefGPIO_InitStructure;

   TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

   TIM_ICInitTypeDef TIM_ICInitStructure;

   NVIC_InitTypeDef NVIC_InitStructure;

      

      

   RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能TIM3时钟

   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//使能GPIOC时钟

       RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);  //AFIO时钟

      

       GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);       //TIM选择全复用功能使能

   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;//PC6 PC7浮空输入

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;//GPIO_Mode_IPU  GPIO_Mode_IN_FLOATING

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_Init(GPIOC,&GPIO_InitStructure);

      

      

       TIM_DeInit(TIM3);       //TIM3初始化

   /* Timer configuration in Encoder mode */

   TIM_TimeBaseStructure.TIM_Prescaler = 0; // 不分频

   TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM3_PERIOD-1;  //计数40000  定时 T = 1/72000000 *40000 S=  1/1.8ms

   TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//设置时钟分频系数:不分频

   TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//向上计数模式

   TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

      

//     //编码配置                        编码模式   

   TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12,TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); //TIM_ICPolarity_Rising上升沿捕获

   TIM_ICStructInit(&TIM_ICInitStructure);       //输入捕获模式配置为硬件默认值

   TIM_ICInitStructure.TIM_ICFilter = 0x06;//ICx_FILTER;  //比较滤波器

   TIM_ICInit(TIM3, &TIM_ICInitStructure);//调用库函数把配置信息填充进去

 

   NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;

   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

   NVIC_Init(&NVIC_InitStructure);

 

//     TIM_ARRPreloadConfig(TIM3,ENABLE);

//     TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Disable);

 

       //Clear all pending interrupts

//     TIM_SetAutoreload(TIM3,0xffff);

       TIM_ClearFlag(TIM3,TIM_FLAG_Update);//清除TIM3的更新标志位

       TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);//使能中断                                                                                                    

 

   //Reset counter  计数初始值

   TIM3->CNT = 0;

   TIM_Cmd(TIM3, ENABLE);

}

 

编码器计数模块

void TIM3_IRQHandler(void)

{     

       if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET)

   {

    TIM_ClearITPendingBit(TIM3 , TIM_FLAG_Update);

          if((TIM3->CR1&0x10) == 0x10)//向下计数

          {          

                     N--;               

          }

          else if((TIM3->CR1&0x10) == 0x00)//向上计数

          {

                     N++;            

          }

              EncCnt= N * 65536 + TIM3->CNT;        

   }           

}

注: N 和EncCnt变量最好定义为volatile


推荐阅读

史海拾趣

AUSTIN公司的发展小趣事

在合并与合作的背景下,奥斯汀汽车开始注重产品创新和多样化。公司不断推出新的车型,以满足不同消费者的需求。例如,奥斯汀A40和A50等车型在市场上取得了不错的销量。同时,奥斯汀汽车还注重技术研发和创新,不断提升产品的性能和品质。

AMD(超微)公司的发展小趣事

随着汽车市场的不断变化和消费者需求的多样化,奥斯汀汽车也在不断调整市场策略和产品布局。公司根据市场需求推出了一系列新的车型,并积极拓展海外市场。虽然奥斯汀汽车在历史长河中经历了许多波折和挑战,但其品牌精神和传统始终得以传承和发扬。如今,奥斯汀汽车已经成为了英国汽车文化的重要组成部分,其经典车型和品牌形象仍然深受消费者喜爱。

这些故事展示了AUSTIN汽车公司在汽车行业中的发展历程,从创始与早期成功,到危机与重生,再到技术合作与国际化发展,以及产品创新与多样化,最终实现了市场调整与品牌传承。这些事实性的描述,旨在呈现AUSTIN汽车公司在历史长河中的真实面貌,而不涉及任何褒贬评价。

Eurosil Electronics Ltd公司的发展小趣事

随着全球对环保问题的日益关注,Eurosil也积极响应这一趋势。公司注重环保和可持续发展,在生产过程中采取了一系列环保措施,如减少废弃物排放、提高能源利用效率等。同时,Eurosil还积极研发环保型电子产品,为客户提供更加绿色、健康的产品选择。

Allied Wire & Cable Inc公司的发展小趣事

为了保持市场竞争力,Allied公司始终注重技术升级和品质提升。公司投入大量资金引进先进的生产设备和技术,不断提高产品的技术含量和附加值。同时,公司还建立了严格的质量管理体系,从原材料采购到产品出厂的每一个环节都进行严格把控,确保产品的品质和性能达到最高标准。

Belden Wire & Cable公司的发展小趣事

随着市场的不断变化和客户需求的多样化,Belden公司开始实施产品多元化战略。除了传统的电线电缆产品外,公司还开发了一系列新型电缆产品,如光纤电缆、数据电缆等。这些新产品不仅拓宽了公司的产品线,还为公司带来了新的增长点。同时,Belden还加大了市场拓展力度,积极参与各类行业展会和论坛,提升品牌影响力。

Asia Pacific Microsystems Inc公司的发展小趣事

APM深知在电子行业中,单打独斗很难取得长远的发展。因此,公司开始积极寻求与上下游企业的合作,共同构建完整的产业链。通过与原材料供应商、代工厂商以及终端客户的紧密合作,APM实现了产业链的整合与协同发展。这不仅降低了公司的运营成本,还提高了产品的质量和生产效率,为公司的持续发展奠定了坚实基础。

问答坊 | AI 解惑

综合布线相关术语

综合布线相关术语 术语或符号 英文名 中文名或解释 ACR Attenuation to Crosstalk Ratio 衷减—串音衰减比率 ADU Asynchronous Data Unit 异步数据单元 ATM Asynchronous Transfer Mode 异步传输模式 BA Building Autom ...…

查看全部问答>

各路高手进来看看

在测运放的失调电流时,接下面的电路很稳定,但是此时在第一个运放的同相或反相端接根导线就自激了,不懂。。。。求救…

查看全部问答>

打破现实与虚幻隔阂的神奇第六感装置

虽然这个视频已经在网上流传已久,但是以截图的方式展示出来还是第一次,来秀秀 想像一下,不用掏出相机,只需用手摆出照相的POSE,就会有咔嚓一声将照片拍下来。然后随意找一面墙,浏览刚刚拍下的照片,还能对照片进行拖拽、缩放等编辑处理。伸 ...…

查看全部问答>

求助HT单片机uart的问题

请问大家有没有用过HT单片机的UART口,有什么例程或者源代码吗?  麻烦发我邮箱fjchen_ok@126.com 现在在做用HT单片机UART口控制GPRS模块发送短信的,用51单片机作的已经是可以的了,但是改为HT出现了问题,GPRS返回的值总是00H,不知道 ...…

查看全部问答>

protel dxp信号层管理问题

在使用Protel DXP管理PCB层时,发现,在使用向导或模板生成的PCB中,除了top和buttom两个层外,不管怎么设置,总是至少会出现8个MidLayer层,而且删除不掉,总是说在使用中,不能删除,但是internalplane层就不会出现这种情况,不知道问题出在什么 ...…

查看全部问答>

ReadProcessMemory读内内存失败

我用OpenProcess 获得了all 的权限 为什么还是失败呢。我用同样的方法换成计算器进程就会成功。 是不是那个进程里面动了什么手脚。.…

查看全部问答>

交流基础器知识普及

交流接触器利用主接点来开闭电路,用辅助接点来执行控制指令。 主接点一般只有color=#0000ff>常开接点,而辅助接点常有两对具有常开和常闭功能的接点,小型的接触器也经常作为中间继电器配合主电路使用。交流接触器的接点,由银钨合金制成,具有良 ...…

查看全部问答>

我用ADS导入PADS9生成的GERBER文件B,NCDRILL导入数据格式老不对

来自:电子工程师技术交流(12425841) 我设置是2:4,ADS导入自动设为2:3,也不能修改,这个问题怎么解决? …

查看全部问答>