Làm thế nào để gọi các chức năng C từ Arduino sketch?


10

Tôi muốn biết liệu có cách nào để gọi các hàm được chứa trong các tệp C bằng cách sử dụng bản phác thảo Arduino không?

Tập tin C của tôi khai báo và định nghĩa một hàm. Để tiết kiệm việc đưa định nghĩa hàm lộn xộn vào bản phác thảo Arduino của tôi, tôi muốn gọi hàm này ngay từ bản phác thảo.

Có một cách tiêu chuẩn để làm điều này bằng cách sử dụng Arduino và C? Đây là bản phác thảo:

#include "crc16.h";

void setup(){

}

void loop(){

  CalculateCRC16("<09M", 4);

}

và đây là tập tin C được cắt bớt:

#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;
}

Có một lý do tại sao tập tin của bạn phải sử dụng C thay vì C ++?
Peter Bloomfield

Trên thực tế, có. Khi tôi cố gắng biên dịch tệp bằng C ++, có lỗi, nhưng không có lỗi trong C. Lỗi là do các dòng: const void *c_ptrconst uint8_t *c = c_ptr;. Thông báo lỗi đề cập đến một chuyển đổi không hợp lệ giữa các loại.
user_name

4
Bạn có thể vui lòng gửi 2 tệp mã (hoặc một phiên bản tối thiểu của chúng) tạo ra lỗi và sao chép và dán đầy đủ thông báo lỗi không?
drodri

Các thông báo lỗi không đẹp lắm: In function uint16_t CalculateCRC16(uint16_t, const void*, size_t)': 46 invalid conversion from const void * 'toconst uint8_t*' In function int main()': 57 system' undeclared (first use this function) (Each undeclared identifier is reported only once for each function it appears in.)
user_name

Câu trả lời:


10

Bạn có thể thoát khỏi "C" #incolee như sau:

extern "C"{
#include "crc16.h"
};

void setup(){
}

void loop(){
  CalculateCRC16("<09M", 4);
}

Và tệp crc16.h có thể là (một số sửa chữa nhỏ, #pragma một lần, diễn viên):

#pragma once

#include <stdio.h>
#include <stdint.h>

uint16_t crctable[2] ={ 0x0000, 0x1189};

uint16_t 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 = (const uint8_t *)c_ptr;

    while (len--)
        crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)];

    return crc;
}

Cảm ơn, nó hoạt động tốt bây giờ. Bạn có thể vui lòng giải thích sự cần thiết của pragma?
user_name

1
Chắc chắn, đó là một thực hành tốt, mặc dù nó không cần thiết trong ví dụ của bạn. Nó tránh cùng một tệp tiêu đề được đưa vào hai lần trong một tệp biên dịch. Tưởng tượng a.cpp -> (bh và ch) và bh-> ch Điều đó sẽ nhân đôi nội dung của ch trong khi biên dịch a.cpp. Các #pragma một lần tránh điều này. Đồng thời bảo vệ các chỉ thị #ifndef _MY_FILE_H_INCLUDED #define _MY_FILE_H_INCLUDED là phổ biến cho việc này. Tuy nhiên, lưu ý rằng như Peter R. Bloomfield chỉ ra, có lẽ tốt hơn là đặt việc triển khai Tính toánCRC16 trong tệp cpp và chỉ để lại khai báo trong tệp tiêu đề.
drodri

Ok, tôi có thể thấy rằng trở thành một vấn đề khi mã ngày càng phức tạp hơn. Cảm ơn vì lời khuyên.
user_name

4

Hàm CRC của bạn có thể dễ dàng được chuyển đổi thành C ++ để có thể chuyển thành tệp * .cpp. Tất cả bạn cần làm là sử dụng một diễn viên rõ ràng khi bạn khởi tạo ccon trỏ của bạn . Đây là cách C ++ 'phù hợp' để làm điều đó:

const uint8_t *c = static_cast<const uint8_t*>(c_ptr);

Tuy nhiên, một dàn diễn viên kiểu C cũ cũng sẽ hoạt động:

const uint8_t *c = (const uint8_t*)c_ptr;

Vấn đề cơ bản là C có thể dễ dãi hơn một chút về việc cho phép bạn chuyển đổi con trỏ ngầm giữa các loại. Để làm điều đó trong C ++, bạn cần nói rõ cho trình biên dịch rằng việc chuyển đổi là có chủ ý.


1

Có, chỉ cần sao chép dòng khai báo của nó trong bản phác thảo của bạn:

extern "C" {
    void myfunction(int arg);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.