首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >中断PIC CCS

中断PIC CCS
EN

Stack Overflow用户
提问于 2017-09-26 21:01:20
回答 3查看 912关注 0票数 0

我有一个在定时器中断(精确时间)中读取AD通道所需的代码。

只要我看一下广告,一切都没问题。但我需要使用数字滤波器,如果我只在中断a中放了一个乘法,就会有一个警告:

这是可以的:

代码语言:javascript
复制
#int_RTCC
void  RTCC_isr(void) 
{
   set_adc_channel(0);      
   delay_us(40);  
   unsigned int16 aD = read_adc();
}

但这会得到警告:

代码语言:javascript
复制
#int_RTCC
void  RTCC_isr(void) 
{
   set_adc_channel(0);      
   delay_us(40);  
   unsigned int16 aD = read_adc();
   aDfilter = aDfilter * 8 + aD * 2;
}

调用期间禁用中断以防止重入(@MUL3232)

我不想禁用计时器,因为我需要精确度。我该如何解决这个问题呢?

EN

回答 3

Stack Overflow用户

发布于 2017-09-26 21:20:05

问题1: PIC通常意味着8位CPU。8位CPU不能自动读取16位值(aDfilter)。如果您的RTC中断触发时,主程序只读取了一半的值,您的程序将崩溃和烧毁。你需要一些可重入性的方法,这是编译器告诉你的。

问题2: PIC通常意味着CPU速度非常慢,具有很大的中断延迟。因此,您不应该在ISR中使用算术运算。这当然涉及到浮点计算。整数的乘法甚至可能已经很糟糕了。

问题3: PIC通常意味着没有FPU的CPU非常慢,这意味着你不应该从一开始就使用浮点数。你最终会调用支持浮动的软件库,这是非常慢的。所显示的代码中没有任何内容表明需要在此程序中使用浮点。

解决方案:使用整数。用同步化的方法来实现可重用性。这在单核微控制器上很容易做到,在单核微控制器中,中断总是阻止进一步的中断,simple example。然后将数字滤波器计算外包给调用者应用程序。只需添加一个标志,告诉它有新数据可用。

票数 0
EN

Stack Overflow用户

发布于 2017-09-26 22:42:50

可以通过移位来避免使用int32乘法,如下所示:

代码语言:javascript
复制
#int_RTCC
void  RTCC_isr(void) 
{
   set_adc_channel(0);      
   delay_us(40);  
   unsigned int16 aD = read_adc();
   aDfilter = aDfilter << 3 + aD * 2;
}
票数 0
EN

Stack Overflow用户

发布于 2017-09-26 22:55:42

在调用期间禁用

(消息)中断,以防止重入(@MUL3232)

我不想禁用计时器,因为我需要精确度。

这是一种错误的担忧。

代码只是在保护自己不受好的设计可以避免的不寻常情况的影响。

当运行定时器中断服务例程(ISR)时,通常仅在以下两种情况下才会发生另一个定时中断的重新进入:

  1. 定时器ISR频率太高。这意味着处理1个定时器ISR的时间太短了,在此完成之前发生了另一个定时器。这不是一个好的设计。要解决的问题是,确保定时器频率不是很高。
  2. 延迟。在处理其他耗时较长的ISR时发生计时器ISR,因此阻塞了此计时器ISR调用。在执行此ISR时,已发生另一个定时器中断。要解决此问题,请确保所有ISR加在一起的时间不会超过计时器周期。

如果设计良好,那么第二个定时器中断将不会发生,并且暂时禁用乘法时间不会阻止定时器中断的发生。

简化代码

需要@MUL3232调用的aDfilter * 8意味着弱优化或不必要地使用带符号的数学运算。通过使用无符号数学使编译器更容易编写代码。

代码语言:javascript
复制
// some_signed_32_bit_type aDfilter
uint32_t aDfilter;

// and if that is not enough change code
// aDfilter = aDfilter * 8 + aD * 2;
aDfilter = (aDfilter << 3) + aD * 2;

潜在的性能改进。根据整体设计,应该能够消除delay_us(40);。如果只使用一个通道,则根据不同的要求,以下情况是可能的。

代码语言:javascript
复制
#int_RTCC
void  RTCC_isr(void) {
  // delay_us(40);  // not needed is timer period >> 40us
  unsigned int16 aD = read_adc();
  set_adc_channel(0);    // select channel now  (also at initialization)
  aDfilter = aDfilter * 8 + aD * 2;
}

潜在的bug。如果read_adc()处于设置最高有效位的模式(例如,10位转换左移6),并且编译器具有16位int/unsigned,则aD*2溢出。在这种情况下,使用:

代码语言:javascript
复制
uint32_t aDfilter;
...
aDfilter = aDfilter*8 + (uint32_t)read_adc()*2;
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46427314

复制
相关文章

相似问题

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