Как вызвать функции C из скетча ардуино?
Я хотел бы знать, есть ли способ вызвать функции, содержащиеся в файлах C, с помощью скетча Arduino?
Мой файл C объявляет и определяет функцию. Чтобы не помещать грязное определение функции в мой скетч Arduino sketch, я бы хотел вызвать эту функцию прямо из скетча.
Есть ли стандартный способ сделать это с помощью Arduino и C? Вот скетч:
#include "crc16.h";
void setup(){
}
void loop(){
CalculateCRC16("<09M", 4);
}
а это урезанный файл C:
#include <stdio.h>
#include <stdint.h>
uint16_t crctable[256] =
{
0x0000, 0x1189,.....
uint16_t // Returns Calculated CRC value
CalculateCRC16( // Call example CalculateCRC16("<09M", 4);
const void *c_ptr, // Pointer to byte array to perform CRC on
size_t len) // Number of bytes to CRC
{
uint16_t crc = 0xFFFF // Seed for CRC calculation
const uint8_t *c = c_ptr;
while (len--)
crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];
return crc;
}
@user_name, 👍11
Обсуждение3 ответа
Лучший ответ:
Вы можете добавить "C" #, например, следующее:
extern "C"{
#include "crc16.h"
};
void setup(){
}
void loop(){
CalculateCRC16("<09M", 4);
}
И файл crc16.h может быть (некоторые незначительные исправления, #pragma один раз, приведение):
#pragma once
#include <stdio.h>
#include <stdint.h>
uint16_t crctable[2] ={ 0x0000, 0x1189};
uint16_t CalculateCRC16( // Вызов примера CalculateCRC16("<09M", 4);
const void *c_ptr, // Указатель на массив байтов для выполнения CRC на
size_t len) // Количество байтов для CRC
{
uint16_t crc = 0xFFFF; // Начальное значение для вычисления CRC
const uint8_t *c = (const uint8_t *)c_ptr;
while (len--)
crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];
return crc;
}
Спасибо, сейчас это работает просто отлично. Не могли бы вы, пожалуйста, объяснить необходимость прагмы?, @user_name
Конечно, это хорошая практика, хотя в вашем примере она не нужна. Это позволяет избежать повторного включения одного и того же файла заголовка в файл компиляции. Представьте себе a.cpp->(b.h и c.h) и b.h->>c.h., которые будут дублировать содержимое c.h при компиляции a.cpp. #pragma однажды избежит этого. Также для этого используются директивы защиты #ifndef _MY_FILE_H_INCLUDED #define _MY_FILE_H_INCLUDED. Однако обратите внимание, что, как указывает Питер Р. Блумфилд, возможно, было бы лучше поместить реализацию CalculateCRC16 в файл cpp и оставить только объявление в файле заголовка., @drodri
Хорошо, я вижу, что это становится проблемой, когда код становится все более и более сложным. Спасибо за совет., @user_name
Да, просто скопируйте его строку объявления в свой скетч:
extern "C" {
void myfunction(int arg);
}
Вашу функцию CRC можно легко преобразовать в C++, чтобы она могла перейти в файл *.cpp. Все, что вам нужно сделать, это использовать явное приведение при инициализации указателя c
. Вот "правильный" способ C++ сделать это:
const uint8_t *c = static_cast<const uint8_t*>(c_ptr);
Тем не менее, старый актерский состав в стиле C также будет работать:
const uint8_t *c = (const uint8_t*)c_ptr;
Проблема в основном в том, что C может быть немного более снисходительным, позволяя вам неявно преобразовывать указатели между типами. Чтобы сделать это на C++, вам нужно явно сообщить компилятору, что преобразование является преднамеренным.
- Сброс Arduino Uno в коде
- max7219 связанный дисплей, показывающий зеркальный текст
- Проблема с Software Serial: нет ответа
- Пиринговая коммуникация
- Запуск С для ардуино
- Как связаться с ESP8266 ESP01, отправив данные через программный сериал на Arduino Uno?
- Прерывание ардуино при смене контакта
- GSM-модуль IOT-GA6 Arduino + ошибка CME 58
Есть ли причина, по которой ваш файл должен использовать C вместо C++?, @Peter Bloomfield
Вообще-то да. Когда я пытаюсь скомпилировать файл с помощью C++, есть ошибки, но в C. Ошибка вызвана строками:
const void *c_ptr
и`const uint8_t *c = c_ptr;'. В сообщении об ошибке упоминается недопустимое преобразование между типами., @user_nameНе могли бы вы опубликовать 2 файла кода (или упрощенную минимальную версию), которые производят ошибку, и скопировать и вставить сообщение об ошибке в полном объеме?, @drodri
Сообщения об ошибках не так хороши:
В функции uint16_t CalculateCRC16(uint16_t, const void*, size_t)': 46 недопустимое преобразование из
const void*' в `const uint8_t*' В функции int main()': 57 system' undeclared (сначала используйте эту функцию) (Каждый незаявленный идентификатор сообщается только один раз для каждой функции, в которой он появляется.), @user_nameКогда функция была вызвана в файле c, как я замечаю это в оригинальном файле Arduino (ino)? Могу ли я создать любую функцию обратного вызова из файла c в файл ino?, @tk97tk
Файлы INO - это C++. Если вы хотите вызвать функцию C++ из C, вы должны создать ее с помощью связи C.
extern "C" void foo() { Serial.println("Foo"); }
, @Majenko