打印
[CW32F003系列]

GTIM编码器扩展位数,但中断似乎有问题

[复制链接]
517|11
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhanan|  楼主 | 2023-6-30 10:29 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
GTIM有编码器模式,并且还有上溢与下溢中断,两者结合似乎可以扩展编码器位数到32位,
用一个有符号的RAM变量表示高16位,即:上溢时,变量+1,下溢时,变量-1,合在一起为一个32位编码器。

关键代码:
编码器设置程序:
  GTIM->CR0 = 0x018001; // 编码器模式3,启动计数器
  GTIM->ICR = 0x00; //写0清0
  GTIM->IER = 0x05; //开下溢UD、上溢OV中断
  NVIC->ISER[0] = 0x010000; //开NVIC_GTIM中断
中断处理程序:
void GTIM_IRQHandler(void) // GTIM编码器上溢下溢中断处理
{
   if(GTIM->ISR & 0x0001) mgw++; // 上溢
   if(GTIM->ISR & 0x0004) mgw--; // 下溢
   GTIM->ICR = 0x00; // 中断标志写0清0
   mzdcs++; // 观察进入中断情况
}

然而想法没有实现,观察到的现象有3点:

1. CR0.EN 在编码器模式无效,为0时,编码器仍然可以计数。

2. CNT在65535,死在中断上(反复进入中断),中断似乎不是计数值跳变触发的。在调试中,将CNT设置为65535也这样,不是信号抖动造成的。

3. CR0.EN 对中断有影响,为1时,UD与OV同时产生。

哪里有问题呢?

使用特权

评论回复
沙发
yuyy1989| | 2023-6-30 11:28 | 只看该作者
你打开cw32F003_gtim.h这个库文件看看,找到IS_GTIM_IT(IT)这个宏定义,看看是不是这样的

如果是的话尝试改成
#define IS_GTIM_IT(IT)     ((((IT) & 0xFFFFFD80) == 0x0UL) && ((IT) != 0x0UL))
看看能不能解决问题,之前有人用F030时发现GTIM调不好,官方更新了一次F030的库修改了这个地方,其它型号的可能还没改

使用特权

评论回复
板凳
zhanan|  楼主 | 2023-6-30 16:35 | 只看该作者
yuyy1989 发表于 2023-6-30 11:28
你打开cw32F003_gtim.h这个库文件看看,找到IS_GTIM_IT(IT)这个宏定义,看看是不是这样的

如果是的话尝试 ...

谢谢,没用库,直接寄存器操作的。

使用特权

评论回复
地板
zhanan|  楼主 | 2023-6-30 16:48 | 只看该作者
在ATIM上成功实现了编码器位数扩展

  ATIM->ARR=0xFFFF;      // GTIM上电默认为FFFF,所以没写这一句
  ATIM->MSCR = 0x0600; // 编码器
  ATIM->CR = 0x30003009; // ATIM开,及中断使能,注意MODE不能是0和1
  ATIM->ICR = 0x00; // 中断标志写0清0
  NVIC->ISER[0] = 0x2000; //ATIM中断

中断处理程序:
void ATIM_IRQHandler(void) // ATIM编码器上溢下溢中断处理
{
   if(ATIM->ISR & 0x010000) mgw++; // 上溢
   if(ATIM->ISR & 0x020000) mgw--; // 下溢
   ATIM->ICR = 0; // 中断标志写0清0
   mcscs++; // 观察进入中断情况
}


将ATIM-CNT设成FFFF,也没有乱入中断,死机。

GTIM是单向加计数,下溢中断只有编码器能用到,显然是有意设计了这个功能,但为什么用不成呢?
是否还有参数没有公开,麻烦厂家技术释法。

使用特权

评论回复
5
zhanan|  楼主 | 2023-7-1 10:30 | 只看该作者
今天继续捣鼓GTIM,既然在65535上反复进入中断,在中断中跳过这个数,就不会死在中断上了。
另外到底发生的什么中断,在进入中断时记录一下,这样中断程序改成如下的样子:

void GTIM_IRQHandler(void) // GTIM编码器上溢下溢中断处理
{
  mzdcs = GTIM->CNT; // 记录中断时的 CNT
  mzdcs|= GTIM->ISR<<16; // 和 ISR
  if((GTIM->ISR & 0x0401)==0x0001) {mgw++; GTIM->CNT++;} // 上溢,跳过上溢数
  if((GTIM->ISR & 0x0404)==0x0404) {mgw--; GTIM->CNT--;} // 下溢,跳过下溢数
  GTIM->ICR = 0x00; // 中断标志写0清0
}

由于中断标志 UD 和 OV 同时产生,靠这两个标志分不出来是上溢还是下溢,幸好还有一个 DIR,加计数DIR=0,减计数DIR=1。

试验报告如下:
1.CR0.EN 对中断有影响,为1时,UD与OV同时产生,为0时,只有UD

2.上溢和下溢点都是65535

编码器模式上溢和下溢为什么不是数的跳变触发,而是类似电平中断,电平不变中断不已?


使用特权

评论回复
6
zhanan|  楼主 | 2023-7-1 15:20 | 只看该作者
本帖最后由 zhanan 于 2023-7-1 15:24 编辑

又有新发现

在编码器模式下,OV 对应 CNT==ARR, UD 对应 CNT==FFFF,当 ARR 也等于FFFF时, 两个中断就凑一起了!
ARR 可变,所以 OV 点可变,而 UD 点是固定不变的,两个匹配值而已。

这样,UD 和 OV 只用一个即可,DIR 用于判断是上溢还是下溢。

  GTIM->CR0 = 0x018001; //编码器
  GTIM->ICR = 0x00; // 中断写0清0
  GTIM->IER = 0x04; // 只开UD中断
  NVIC->ISER[0] = 0x010000; //GTIM中断

void GTIM_IRQHandler(void) // GTIM编码器上溢下溢中断处理
{
  mzdcs = GTIM->CNT;
  mzdcs|= GTIM->ISR<<16;
  if((GTIM->ISR & 0x0404)==0x0004) {mgw++; GTIM->CNT++;}// 上溢
  if((GTIM->ISR & 0x0404)==0x0404) {mgw--; GTIM->CNT--;}// 下溢
  GTIM->ICR = 0x00; //写0清0
}

CNT跳过一个数,岂不是少计了一个数?
如果是触发式的,UD和OV就是真正的下溢和上溢了,为什么不呢?

使用特权

评论回复
7
zhanan|  楼主 | 2023-7-3 09:08 | 只看该作者
在编码器模式下,GTIM的匹配中断也是 CNT=CCR,CNT不变,中断不停。

使用特权

评论回复
8
zhanan|  楼主 | 2023-7-3 15:56 | 只看该作者
又想到一个办法,GTIM扩展编码器位数终于成功啦!土法**制啦,凑合用,还是寄**芯源解决问题,和ATIM那样,编码器中断靠CNT值跳变触发,没理由死等啊。

6楼的办法是用改变CNT来避免死在中断上,由于ARR可变,把ARR调到0000,可把两个中断分开。
响应一个中断时,关掉本中断,打开另一个中断,这样就避免死在本中断,CNT仍然是连续计数,没有计数损失。

UD是固定的FFFF,CNT减计数从0000到FFFF正好是下溢,向扩展位借位。关闭UD中断,打开OV中断。
               如果从FFFE加计数到FFFF,由于UD中断已经关闭,所以不再响应UD中断。
ARR调到0000,CNT在0000上产生OV中断,CNT加计数从FFFF到0000正好是上溢,向扩展位进位。关闭OV中断,打开UD中断。
             如果从0001减计数到0000,由于OV中断已经关闭,所以不再响应OV中断。
这里UD和OV是一对互斥开关,总是只开一个,所以漏不掉真正的上溢点和下溢点。

  GTIM->ARR = 0x00; // 上溢点,默认是FFFF,必须和下溢点错开
  GTIM->CR0 = 0x018001; //编码器
  GTIM->ICR = 0x00; // 中断写0清0
  GTIM->IER = 0x04; // 开UD中断,只开一个中断,此时CNT是默认值0000
  NVIC->ISER[0] = 0x010000; //GTIM中断

中断处理:
void GTIM_IRQHandler(void) // GTIM编码器上溢下溢中断处理
{
  mzdcs = GTIM->CNT;
  mzdcs|= GTIM->ISR<<16;  // 观察变量,
  if(GTIM->IER & 0x01) // 到上溢点0000
  {
    if((GTIM->ISR & 0x0400)==0) mgw++; // 加计数(DIR=0)进位
    GTIM->IER = 0x04; // 等下溢点中断
  }
  else // 到下溢点FFFF
  {
    if(GTIM->ISR & 0x0400) mgw--; // 减计数(DIR=1)借位
    GTIM->IER = 0x01; // 等上溢点中断
  }
  GTIM->ICR = 0x00; //写0清0
}

使用特权

评论回复
9
pssyx| | 2023-7-6 17:30 | 只看该作者
本帖最后由 pssyx 于 2023-7-10 09:53 编辑

      实测CW32L083的GTIM1的编码计数模式3,针对你观察的现象答复如下:
      1、CR0.EN = 0时, 的确可以计数,这是编码计数模式独有的功能。如果想停止计数,需要控制计数器输入通道CH1或者CH2的脉冲电平。
      2、编码计数模式3时,只要保持向上或者向下计数脉冲,CNT值一定会循环变化,GTIM1的ISR也可以正常退出。请检查CH1/CH2的电平,是否在CNT等于65535时,不停地进行加1、减1操作?
      3、因为ARR=0xFFFF,所以UD与OV会同时产生,MCU使用手册明确指出OV标志,“当计数器值从 ARR 变为 0 时产生该标志”。
      附件图片显示了不同计数方向时CH1/CH2的脉冲波形,请参考!

scope_30.png (31.24 KB )

scope_30.png

scope_29.png (31.35 KB )

scope_29.png

使用特权

评论回复
10
zhanan|  楼主 | 2023-7-7 15:37 | 只看该作者
pssyx 发表于 2023-7-6 17:30
实测CW32L083的GTIM1的编码计数模式3,针对你观察的现象答复如下:
      1、CR0.EN = 0时, 的确可 ...

谢谢,我手里只有CW32F003,主要问题是在编码器模式下,引起中断的条件是CNT==ARR,或CNT==0xFFFF,除非关闭中断或者改变CNT的值,类似于电平中断。比较中断也是这样,CNT==比较值,就一直中断。

你如果有空,可设成编码器模式,不用外接信号,直接在调试器中改变CNT就能模拟出来。

ATIM的编码器模式就没有这些问题,是靠CNT的值跳变触发的,跳变后即使CNT==ARR 或 FFFF,也不会再中断。

如果L083没有这个问题,那就是芯片有差异。

使用特权

评论回复
11
zhanan|  楼主 | 2023-7-7 15:51 | 只看该作者
不是数值跳变中断,这样的中断用处不大,不应该设计成这样,是否有隐藏的寄存器没有公开?
F003的GTIM和ATIM在编码器模式上中断触发的不同是什么原因呢?

使用特权

评论回复
12
zhanan|  楼主 | 2023-7-7 16:28 | 只看该作者
假如我在编码器模式,用比较匹配中断来捕捉一些特定的位置,跳变触发就很有用。而==中断就会死在中断上。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

9

主题

173

帖子

0

粉丝