编辑:为了使内容更清晰,我进行了一些较小的文书编辑。如果您不赞成我的问题,可以请您解释原因吗?
我看了几个看起来与我的代码非常相似的示例,但无法了解它们在做什么。
当单独使用PWM
和LED
对象时,它们同时起作用,但是当我将它们组合在一起时,PWM
对象将停止全部起作用。我最初尝试在构造函数之后的PWM
文件中创建led.cpp
对象(如下面的代码所示)。在这种配置下,代码编译没有错误,但是PWM
不起作用(LED保持熄灭),并且在遇到pwm.start
和pwm.stop
函数中的while循环时,整个程序冻结。 ,大概是因为未创建对象,因此while循环正在等待的事件永远不会发生。如果我注释掉这些while循环,它将不会挂起,但是pwm仍然无法运行。在全亮度下使用LED
会绕过pwm
功能,因此只要不首先以部分亮度打开led,这部分代码就可以正常工作。
正如我所阅读的,我看到在大多数情况下,第二个对象包含在头文件中,并与其他私有变量一起声明。尝试执行此操作(如下面的代码所示),该代码将不再编译,并为包含pwm。*指令的led.cpp中的每一行提供以下错误。
无效使用成员函数'PWM LED :: pwm(pwmModule,bool,bool, int,prescaler)”(您忘了'()'吗?)
我的主要目标是能够创建一个LED对象,该对象创建一个PWM对象以调节亮度,同时保留我想将其用于电动机速度控制等时单独调用PWM对象的选项/功能。>
led.h
#ifndef rav_nrf52840_led_h
#define rav_nrf52840_led_h
#include "rav_nrf52840_macros.h"
#include "rav_nrf52840_pwm.h"
typedef enum {RED = 1,GREEN = 2,YELLOW = 3,BLUE = 4,MAGENTA = 5,CYAN = 6,WHITE = 7} ledState;
class LED {
private:
PWM pwm(pwmModule module, bool looping, bool mode, int count, prescaler scale); // Without this line the code compiles with no errors but the PWM does not function. With this line I get the error invalid use of member function.
bool pwm_setup_flag;
bool pwm_sequence_started_flag;
bool LED_activeLow_flag;
bool LED_RGB_flag;
int LED_portNumber[3];
int LED_pinNumber[3];
int LED_color;
int LED_intensity;
bool setupPWM(void);
public:
LED (bool activeLow,int portNumber[3],int pinNumber[3]); // Use this format for RGB LEDs. Port and pin numbers must be listed in order: red, green, then blue.
LED (bool activeLow,int portNumber,int pinNumber); // Use this format for single color LEDs
void on (ledState color, int brightness); // Do not use this format with single color LEDs. Valid options for brightness are 0 - 100(%)
void off (void);
};
#endif
led.cpp
#include "rav_nrf52840_led.h"
LED::LED (bool activeLow,int portNumber[3],int pinNumber[3]){
LED_RGB_flag = true;
LED_activeLow_flag = activeLow;
LED_portNumber[0] = portNumber[0];
LED_portNumber[1] = portNumber[1];
LED_portNumber[2] = portNumber[2];
LED_pinNumber[0] = pinNumber[0];
LED_pinNumber[1] = pinNumber[1];
LED_pinNumber[2] = pinNumber[2];
}
LED::LED (bool activeLow,int portNumber,int pinNumber){
LED_RGB_flag = false;
LED_activeLow_flag = activeLow;
LED_portNumber[0] = portNumber;
LED_pinNumber[0] = pinNumber;
}
// PRIVATE
PWM pwm(PWM0,true,0,0x7FFF,DIV4);
bool pwm_setup_flag;
bool pwm_sequence_started_flag;
bool LED_activeLow_flag;
bool LED_RGB_flag;
int LED_portNumber[3];
int LED_pinNumber[3];
int LED_color = RED; // Default value is RED.
int LED_intensity = 0xFFFF; // Default value is 0xFFFF.
unsigned int sequence_0[4];
bool LED::setupPWM(void){
if (!pwm_setup_flag){
pwm_setup_flag = true;
pwm.init(INDIVIDUAL,0,0xFFFF);
pwm.sequence(0,sequence_0,4,0,0);
pwm.pinSelect(0,LED_portNumber[0],LED_pinNumber[0],false);
// if (LED_RGB_flag){
// pwm.pinSelect(1,LED_portNumber[1],LED_pinNumber[1],false);
// pwm.pinSelect(2,LED_portNumber[2],LED_pinNumber[2],false);
// }
pwm.enable();
return 1;
}
else{
return 0;
}
}
// PUBLIC
void LED::on (ledState color, int brightness){
setupPWM();
LED_intensity = brightness;//(scale(brightness,0,100,0x8000,0xFFFF));
if (LED_RGB_flag){
LED_color = color;
if (brightness >= 0xFFFF){//100){
LED_activeLow_flag ? writePin(LED_portNumber[0],LED_pinNumber[0],readBit(LED_color,0) ? 0:1) : writePin(LED_portNumber[0],LED_pinNumber[0],readBit(LED_color,0) ? 1:0);
LED_activeLow_flag ? writePin(LED_portNumber[1],LED_pinNumber[1],readBit(LED_color,1) ? 0:1) : writePin(LED_portNumber[1],LED_pinNumber[1],readBit(LED_color,1) ? 1:0);
LED_activeLow_flag ? writePin(LED_portNumber[2],LED_pinNumber[2],readBit(LED_color,2) ? 0:1) : writePin(LED_portNumber[2],LED_pinNumber[2],readBit(LED_color,2) ? 1:0);
}
else{
if (pwm_sequence_started_flag){
pwm.stop();
pwm_sequence_started_flag = false;
}
sequence_0[0] = LED_intensity;
// sequence_0[1] = LED_intensity;
// sequence_0[2] = LED_intensity;
pwm_sequence_started_flag = pwm.start();
}
}
else{
if (brightness >= 100){
LED_activeLow_flag ? writePin(LED_portNumber[0],LED_pinNumber[0],readBit(LED_color,0) ? 0:1) : writePin(LED_portNumber[0],LED_pinNumber[0],readBit(LED_color,0) ? 1:0);
}
else{
if (pwm_sequence_started_flag){
pwm.stop();
pwm_sequence_started_flag = false;
}
sequence_0[0] = LED_intensity;
pwm_sequence_started_flag = pwm.start();
}
}
}
void LED::off (void){
setupPWM();
if (pwm_sequence_started_flag){
pwm.stop();
pwm_sequence_started_flag = false;
}
if (LED_RGB_flag){
LED_activeLow_flag ? writePin(LED_portNumber[1],LED_pinNumber[1],1) : writePin(LED_portNumber[1],LED_pinNumber[1],0);
LED_activeLow_flag ? writePin(LED_portNumber[2],LED_pinNumber[2],1) : writePin(LED_portNumber[2],LED_pinNumber[2],0);
}
LED_activeLow_flag ? writePin(LED_portNumber[0],LED_pinNumber[0],1) : writePin(LED_portNumber[0],LED_pinNumber[0],0);
}
pwm.h
#ifndef rav_nrf52840_pwm_h
#define rav_nrf52840_pwm_h
#include "rav_nrf52840_baseConst.h"
typedef enum {DIV1,DIV2,DIV4,DIV8,DIV16,DIV32,DIV64,DIV128} prescaler;
typedef enum {PWM0,PWM1,PWM2,PWM3} pwmModule;
typedef enum {COMMON,GROUPED,INDIVIDUAL,WAVEFORM} decoderLoad;
class PWM {
private:
unsigned int base_address;
void enable_pwm (bool en);
bool start_pwm (void);
void stop_pwm (void);
public:
PWM (pwmModule module, bool looping, bool mode, int count, prescaler scale);
void init (decoderLoad load, bool decoder_mode, int loop_count);
void sequence (int seq_number, unsigned int *pointer, int count, int refresh, int enddelay);
void pinSelect (int channel, int port, int pin, bool disconnect);
void enable (void);
void disable (void);
bool start (void);
void stop (void);
};
#endif
pwm.cpp
#include "rav_nrf52840_pwm.h"
#include <cstdint>
PWM::PWM (pwmModule module, bool looping, bool mode, int count, prescaler scale){
switch (module){
default:
;
break;
case PWM0:
base_address = BASE_ADDRESS_PWM0;
break;
case PWM1:
base_address = BASE_ADDRESS_PWM1;
break;
case PWM2:
base_address = BASE_ADDRESS_PWM2;
break;
case PWM3:
base_address = BASE_ADDRESS_PWM3;
break;
}
unsigned int * pwm_mode_reg = (unsigned int *)(base_address + REGISTER_OFFSET_PWM_MODE);
unsigned int * countertop_reg = (unsigned int *)(base_address + REGISTER_OFFSET_COUNTERTOP);
unsigned int * prescaler_reg = (unsigned int *)(base_address + REGISTER_OFFSET_PRESCALER);
unsigned int * shortcut_reg = (unsigned int *)(base_address + REGISTER_OFFSET_SHORTS);
*pwm_mode_reg = mode;
*countertop_reg = count;
*prescaler_reg = scale;
if (looping){
*shortcut_reg = 0x04; // Enable looping
}
}
// PRIVATE
unsigned int base_address;
void PWM::enable_pwm (bool en){
unsigned int * pwm_enable_reg = (unsigned int *)(base_address + REGISTER_OFFSET_ENABLE);
*pwm_enable_reg = en;
}
bool PWM::start_pwm (void){
unsigned int * start_seq0_task = (unsigned int *)(base_address + TASK_OFFSET_SEQSTART_0);
volatile unsigned int * seq0_started_event = (unsigned int *)(base_address + EVENT_OFFSET_SEQSTARTED_0);
*start_seq0_task = true;
while(!*seq0_started_event){}
*seq0_started_event = false;
return 1;
}
void PWM::stop_pwm (void){
unsigned int * pwm_stop_task = (unsigned int *)(base_address + TASK_OFFSET_PWM_STOP);
volatile unsigned int * pwm_stopped_event = (unsigned int *)(base_address + EVENT_OFFSET_STOPPED);
*pwm_stop_task = true;
while(!*pwm_stopped_event){}
*pwm_stopped_event = false;
}
// PUBLIC
void PWM::init (decoderLoad load, bool decoder_mode, int loop_count){
unsigned int * decoder_reg = (unsigned int *)(base_address + REGISTER_OFFSET_DECODER);
unsigned int * loop_reg = (unsigned int *)(base_address + REGISTER_OFFSET_LOOP);
*decoder_reg = load;
if (decoder_mode){
*decoder_reg |= 0x100;
}
*loop_reg = loop_count;
}
void PWM::sequence (int seq_number, unsigned int *pointer, int count, int refresh, int enddelay){
unsigned int * seq_pointer_reg = (unsigned int *)(base_address + REGISTER_OFFSET_SEQ_0_PTR + (MODIFIER_SEQ * seq_number));
unsigned int * seq_count_reg = (unsigned int *)(base_address + REGISTER_OFFSET_SEQ_0_CNT + (MODIFIER_SEQ * seq_number));
unsigned int * seq_refresh_reg = (unsigned int *)(base_address + REGISTER_OFFSET_SEQ_0_REFRESH + (MODIFIER_SEQ * seq_number));
unsigned int * seq_enddelay_reg = (unsigned int *)(base_address + REGISTER_OFFSET_SEQ_0_ENDDELAY + (MODIFIER_SEQ * seq_number));
*seq_pointer_reg = reinterpret_cast<std::uintptr_t>(pointer);
*seq_count_reg = count;
*seq_refresh_reg = refresh;
*seq_enddelay_reg = enddelay;
}
void PWM::pinSelect (int channel, int port, int pin, bool disconnect){
unsigned int * pin_select_reg = (unsigned int *)(base_address + REGISTER_OFFSET_PSEL_OUT_0 + (MODIFIER_PSEL_OUT * channel));
*pin_select_reg = ((disconnect << 31) | (port << 5) | pin);
}
void PWM::enable (void){
enable_pwm(true);
}
void PWM::disable (void){
enable_pwm(false);
}
bool PWM::start (void){
bool pwm_seq_started = start_pwm();
return pwm_seq_started;
}
void PWM::stop (void){
stop_pwm();
}
main.cpp
#include "rav_nrf52840_base.h"
#include "rav_nrf52840_led.h"
int main(void){ // TX
setupClock (HF_64MHz_XTAL, START);
setupClock (LF_32_768kHz_XTAL, START);
int my_led_ports[3] = {0,0,0};
int my_led_pins[3] = {23,22,24}; // RED, GREEN, BLUE
LED led(true,my_led_ports,my_led_pins);
setupPin (0, 3,INPUT);
pullPin (0, 3,PULLUP);
setupPin (0,18,INPUT); // External (? Ohm) pullup resistor.
setupPin (0,22,OUTPUT);
writePin (0,22,HIGH);
setupPin (0,23,OUTPUT);
writePin (0,23,HIGH);
setupPin (0,24,OUTPUT);
writePin (0,24,HIGH);
for(;;){
if (readPin(0,3)){
;
}
else{
led.on(RED,0xFFFF);
}
if (readPin(0,18)){
;
}
else{
led.on(RED,0xF000);
}
}
return -1;
}