Come chiamare le funzioni C dallo schizzo di Arduino?


10

Vorrei sapere se esiste un modo per chiamare le funzioni contenute nei file C usando uno schizzo di Arduino?

Il mio file C dichiara e definisce una funzione. Per salvare inserendo la definizione della funzione disordinata nel mio schizzo di Arduino, vorrei chiamare la funzione direttamente dallo schizzo.

Esiste un modo standard per farlo usando Arduino e C? Ecco lo schizzo:

#include "crc16.h";

void setup(){

}

void loop(){

  CalculateCRC16("<09M", 4);

}

e questo è il file C ridotto:

#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'è un motivo per cui il tuo file deve usare C anziché C ++?
Peter Bloomfield,

Attualmente si. Quando provo a compilare il file usando C ++, ci sono errori, ma è privo di errori in C. L'errore è causato dalle righe: const void *c_ptre const uint8_t *c = c_ptr;. Il messaggio di errore menziona una conversione non valida tra i tipi.
nome_utente

4
Potresti pubblicare i 2 file di codice (o una versione minima semplificata di essi) che generano l'errore e copiare e incollare il messaggio di errore per intero?
Drodri,

I messaggi di errore non sono così belli: In function uint16_t CalculateCRC16(uint16_t, const void*, size_t)': 46 invalid conversion from const void * 'aconst 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.)
nome_utente

Risposte:


10

Puoi esternare "C" # includendo come segue:

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

void setup(){
}

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

E il file crc16.h potrebbe essere (alcune correzioni minori, il #pragma una volta, un cast):

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

Grazie, ora funziona bene. Potresti spiegare per favore la necessità del pragma?
nome_utente

1
Certo, è una buona pratica, anche se non è necessaria nel tuo esempio. Evita di includere due volte lo stesso file di intestazione in un file di compilazione. Immagina a.cpp -> (bh e ch) e bh-> ch che duplicheranno il contenuto di ch durante la compilazione di a.cpp. Il #pragma una volta evita questo. Anche le direttive di protezione #ifndef _MY_FILE_H_INCLUDED #define _MY_FILE_H_INCLUDED sono comuni per questo. Si noti, tuttavia, che, come sottolinea Peter R. Bloomfield, potrebbe essere meglio inserire l'implementazione di CalculateCRC16 in un file cpp e lasciare solo la dichiarazione nel file di intestazione.
Drodri,

Ok, posso vedere che diventa un problema quando il codice diventa sempre più complicato. Grazie per il consiglio.
nome_utente

4

La tua funzione CRC può essere facilmente convertita in C ++ in modo che possa andare in un file * .cpp. Tutto quello che devi fare è usare un cast esplicito quando inizializzi il cpuntatore. Ecco il modo "corretto" C ++ per farlo:

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

Tuttavia, un vecchio cast in stile C avrebbe funzionato anche:

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

Il problema è fondamentalmente che C può essere un po 'più permissivo nel permetterti di convertire implicitamente i puntatori tra i tipi. Per farlo in C ++, devi dire esplicitamente al compilatore che la conversione è intenzionale.


1

Sì, basta copiare la sua linea di dichiarazione nel tuo schizzo:

extern "C" {
    void myfunction(int arg);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.