首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从中断服务例程访问类的虚拟方法?

如何从中断服务例程访问类的虚拟方法?
EN

Stack Overflow用户
提问于 2022-01-09 13:31:13
回答 2查看 97关注 0票数 0

我试图用Timer0实现Atmega328P在C++中的脉宽调制。事实上,我已经做到了这一点。但是,我还有另外一个相关的问题。

我有一个PWM抽象基类,它为PWM实现提供了一个接口。

代码语言:javascript
复制
// mcal_pwm_base.h
#ifndef MCAL_PWM_BASE_H_
#define MCAL_PWM_BASE_H_

namespace mcal
{
    namespace pwm
    {
        class pwm_base
        {
        public:
            ~pwm_base() = default;
        
            virtual bool init() noexcept = 0;
        
            virtual void set_duty(const uint16_t duty_cycle) = 0;
        
            virtual void pwm_ISR() noexcept = 0;
        
            uint16_t get_duty() const noexcept { return pwm_duty_cycle; }
    
        protected:
            uint16_t pwm_duty_cycle;
        
            pwm_base() : pwm_duty_cycle(0U) { }
            
            pwm_base(const pwm_base&) = delete;
            const pwm_base& operator=(const pwm_base&) = delete;
        };
    }
}

#endif /* MCAL_PWM_BASE_H_ */

我想实现PWM与计时器(8位定时器)。因此,我创建了另一个从pwm_base类派生的类。

代码语言:javascript
复制
// mcal_pwm_8.h
#ifndef MCAL_PWM_8_H_
#define MCAL_PWM_8_H_

#include "mcal_pwm_base.h"
#include "mcal_reg_access_dynamic.h"
#include <avr/interrupt.h>

namespace mcal
{
    namespace pwm
    {
        template<const uint8_t prescalar_val = UINT8_C(0U)>
        class pwm_8 : public mcal::pwm::pwm_base
        {
        public:
            ~pwm_8() = default;
            
            virtual bool init() noexcept
            {
                // set pwm related things
            
                return true;
            }
        
            virtual void set_duty(const uint16_t duty_cycle)
            {
                pwm_duty_cycle = duty_cycle;
            }
        
            virtual void pwm_ISR() noexcept
            {
                uint8_t compare_value =  (pwm_duty_cycle / 100) * 255;
                mcal::reg::reg_access_dynamic<uint8_t, uint8_t>::reg_set(mcal::reg::ocr0a, compare_value);
            }
        };
    }
}

ISR(TIMER0_OVF_vect)
{
    // pwm_ISR();
}


#endif /* MCAL_PWM_8_H_ */

如您所见,我想在ISR (中断服务例程)中调用pwm_ISR()成员函数。但是,我不知道怎么做。在本书中,我们编写了pwm_8类的ISR朋友函数。即使我这样做了,我将如何到达pwm_duty_cycle中的私有成员变量?现在我需要你的帮助。

最后,这是我的主要功能。

代码语言:javascript
复制
// main.h
#define F_CPU   16000000ULL

#include <avr/io.h>
#include <util/delay.h>

#include "mcal_reg.h"
#include "mcal_reg_access_static.h"
#include "mcal_port.h"
#include "mcal_led_port.h"
#include "mcal_pwm_8.h"

int main(void)
{       
    mcal::pwm::pwm_8<UINT8_C(5U)> myPwm;

    myPwm.init();

    myPwm.set_duty(250); // This will be applied when ISR called

    for(;;) 
    {
    }

    return 0;

}

事先非常感谢。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-01-09 13:51:46

似乎不可能将用户数据(如void*)提供给ISR例程,从而使myPwm成为一个全局变量:

示例:

头文件:

代码语言:javascript
复制
extern mcal::pwm::pwm_8<UINT8_C(5U)> myPwm;

ISR(TIMER0_OVF_vect)
{
    myPwm.pwm_ISR();
}

..。在.cpp文件中:

代码语言:javascript
复制
mcal::pwm::pwm_8<UINT8_C(5U)> myPwm;

还可以将全局变量隐藏在函数中以获得延迟初始化

头文件:

代码语言:javascript
复制
mcal::pwm::pwm_8<UINT8_C(5U)>& myPwm();  // now a function

ISR(TIMER0_OVF_vect)
{
    myPwm().pwm_ISR(); // calling function to get the instance
}

..。在.cpp文件中:

代码语言:javascript
复制
mcal::pwm::pwm_8<UINT8_C(5U)>& myPwm() {
    static mcal::pwm::pwm_8<UINT8_C(5U)> instance;
    // that returns a reference to the one instance you'll use:
    return instance;
}
票数 1
EN

Stack Overflow用户

发布于 2022-01-09 13:51:44

您可以创建全局回调对象(ISR可见),该对象应该注册要采取的实际操作。通常,可调用的需要对ISR可见,也就是说,它需要在int的范围内生存。

noexcept建议你在C++11或更高的地方。如果不行的话,你就得后退一步或者再打几下.

代码语言:javascript
复制
volatile std::function<void()> pwmCallback; //even better: make it static for the PWM class
//can also by a function object...depends what you need.

ISR(TIMER0_OVF_vect)
{
    if (pwmCallback) {
        pwmCallback();
    }

}

int main()
{
    mcal::pwm::pwm_8<UINT8_C(5U)> myPwm;
    pwmCallback = [&myPwm](){myPwm.pwm_ISR();}

    myPwm.init();

    myPwm.set_duty(250); // This will be applied when ISR called

    for(;;) 
    {
    }

    return 0;
}

此外,确保回调不超过pwm对象(此处未讨论)。另一种选择是使您的pwm成为全局对象。

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

https://stackoverflow.com/questions/70641776

复制
相关文章

相似问题

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