Проблема при создании библиотеки Arduino с зависимостями

У меня есть заголовочный файл ArduinoCanUtils.h и исходный файл ArduinoCanUtils.cpp, организованные в следующем дереве каталогов:

Documents
|---Arduino
|   |---libraries
|       |--- autowp-mcp2515
|       |    |--- other library files
|       |
|       |--- ArduinoCanUtils 
|            |--- ArduinoCanUtils.h
             |--- ArduinoCanUtils.cpp

Эти файлы составляют библиотеку ArduinoCanUtils, которую я пытаюсь создать. Содержание ArduinoCanUtils.h следующее:

#ifndef ArduinoCanUtils_h
#define ArduinoCanUtils_h

#include <Arduino.h>
#include <stdint.h>
#include <mcp2515.h>


class ArduinoCanUtils
{
  public:
    ArduinoCanUtils();
    uint32_t createCanMsgCanId(uint8_t priorityLevel, uint8_t activityCode, uint8_t destinationAddress, uint8_t originAddress);
    uint8_t getPriorityLevelFromCanMsgCanId(uint32_t canId);
    uint8_t getActivityCodeFromCanMsgCanId(uint32_t canId);
    uint8_t getDestinationAddressFromCanMsgCanId(uint32_t canId);
    uint8_t getOriginAddressFromCanMsgCanId(uint32_t canId);
    void setAllCanMsgDataToZero(struct can_frame &canMsg);

};

#endif

А вот содержание ArduinoCanUtils.cpp следующее:

#include <Arduino.h>
#include <stdint.h>
#include <mcp2515.h> 
#include "ArduinoCanUtils.h"

ArduinoCanUtils::ArduinoCanUtils(){}

uint32_t ArduinoCanUtils::createCanMsgCanId(uint8_t priorityLevel, uint8_t activityCode, uint8_t destinationAddress, uint8_t originAddress)
{
  uint32_t canId = 0;
  canId = canId | originAddress;
  canId = canId | destinationAddress << 8;
  canId = canId | ((uint32_t) activityCode) << 16;
  for (int i = 0; i <= 2; i++){bitWrite(canId, 26 + i, bitRead(priorityLevel, i));}  
  bitWrite(canId, 31, 1);
  return canId;
}

uint8_t ArduinoCanUtils::getPriorityLevelFromCanMsgCanId(uint32_t canId){
  uint8_t priorityLevel = 0; 
  for (int i = 0; i <= 2; i++){bitWrite(priorityLevel, i, bitRead(canId, 26 + i));}  
  return priorityLevel;
}

uint8_t ArduinoCanUtils::getActivityCodeFromCanMsgCanId(uint32_t canId){
  uint8_t activityCode = 0; 
  for (int i = 0; i <= 7; i++){bitWrite(activityCode, i, bitRead(canId, 16 + i));}  
  return activityCode;
}

uint8_t ArduinoCanUtils::getDestinationAddressFromCanMsgCanId(uint32_t canId){
  uint8_t destinationAddress = 0; 
  for (int i = 0; i <= 7; i++){bitWrite(destinationAddress, i, bitRead(canId, 8 + i));} 
  return destinationAddress;
}

uint8_t ArduinoCanUtils::getOriginAddressFromCanMsgCanId(uint32_t canId){
  uint8_t originAddress = 0; 
  for (int i = 0; i <= 7; i++){bitWrite(originAddress, i, bitRead(canId, i));}  
  return originAddress;
}

void ArduinoCanUtils::setAllCanMsgDataToZero(struct can_frame &canMsg){
    for (int i = 0; i <= 7; i++){canMsg.data[i] = 0;}
}

Как видите, функция setAllCanMsgDataToZero требует тип struct can_frame в качестве аргумента. Этот тип определен в сторонней библиотеке autowp-mcp2515 (ссылка: https://github.com/autowp/arduino-mcp2515.git), но когда я пытаюсь использовать эту функцию в следующем тестовом скрипте :

#include <mcp2515.h> 
#include <ArduinoCanUtils.h>

MCP2515 mcp2515Global(10); 
struct can_frame canMsg = {.can_id = 0, .can_dlc = 8, .data = {0,0,0,0,0,0,0,0}}; 
ArduinoCanUtils canUtils;

void setup() {
  // put your setup code here, to run once:

uint32_t a = canUtils.createCanMsgCanId(1, 1, 2, 1);
uint8_t b = canUtils.getActivityCodeFromCanMsgCanId(a);
canUtils.setAllCanMsgDataToZero(&canMsg);

}

void loop() {
  // put your main code here, to run repeatedly:

}

После компиляции я получаю следующий журнал ошибок (см. изображение):

Интересно, что все остальные функции из моей библиотеки работают нормально, вот только с этой функцией возникают проблемы.

Я обязательно включил все необходимые зависимости. Кроме того, другие функции, кроме setAllCanMsgDataToZero, похоже, работают нормально. Я проверил, что правильно объявляю структуру can_fame, но не знаю, почему она продолжает выдавать эту ошибку. помощь будет очень признательна. Я впервые пишу библиотеку для Arduino, и я попробовал поискать в Интернете, но не нашел никакой помощи. Я надеюсь, что вы можете мне помочь.

C++ 101: глобальное пространство предназначено для объявления переменных и создания экземпляра класса, а не для вызова метода класса для выполнения кода. Поэтому переместите это выполнение в функцию (т. е. в вашу настройку() или цикл()).

hcheung 21.02.2024 02:34

«Я пытался поискать в Интернете, но не нашел никакой помощи». Существуют такие руководства, как Написание библиотеки для Arduino и Руководство по стилю библиотеки Arduino.

hcheung 21.02.2024 02:44

Кстати, такие вещи, как for (int i = 0; i <= 7; i++){canMsg.data[i] = 0;}, можно выполнить с помощью memset(canMsg.data,0);, а большинство методов, таких как вся функция getPriorityLevelFromCanMsgCanId(uint32_t canId), можно выполнить с помощью однострочника, как (canId & 0x1c000000) > 26; (т. е. шаблон (canId & bit_mask) >> bit_position). Прочтите Bit Math или просто возьмите одну из книг по C++ и прочитайте ее.

hcheung 21.02.2024 03:07

-хечуг, спасибо за помощь!. Постараюсь ответить на каждый ваш комментарий в хронологическом порядке: 1) Вы были правы. Я переместил все строки, в которых вызываю методы CanUtils, внутри void setup(), и теперь появилась новая ошибка: «ошибка компиляции: нет соответствующей функции для вызова «ArduinoCanUtils::setAllCanMsgDataToZero(can_frame*)». Как я мог это решить? 2) Я действительно последовал примеру этой ссылки, но она не касается зависимостей. 3) Спасибо, приму во внимание, хотя в моем случае я предпочитаю читабельность и интуитивность производительности, так как я нуб.

Andrew M. 21.02.2024 22:05

В исходном дизайне параметр функции передается по ссылке с помощью &canMsg, а теперь вы передаете параметр по указателю *canMsg.

hcheung 22.02.2024 01:23

@hcheung, еще раз спасибо. Я посмотрел ссылку, которую вы разместили, и теперь вижу ошибку. Я не был так хорошо знаком с «передачей по ссылке», как думал. Мне следует использовать canUtils.setAllCanMsgDataToZero(canMsg) вместо canUtils.setAllCanMsgDataToZero(&canMsg), так как во втором случае я передаю указатель, а функция просто ожидает ссылку. Спасибо. Отмечаю вопрос как отвеченный.

Andrew M. 22.02.2024 15:44
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
6
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я не был так хорошо знаком с «передачей по ссылке», как думал. Мне следует использовать canUtils.setAllCanMsgDataToZero(canMsg) вместо canUtils.setAllCanMsgDataToZero(&canMsg), так как во втором случае я передаю указатель, а функция просто ожидает ссылку.

Оказывается, это вовсе не проблема зависимости.

Другие вопросы по теме