The C Function Call block enables seamless integration of custom C functions into Simulink models with automatic code generation for Microchip targets. This page provides practical examples demonstrating common use cases.
The C Function Call block solves several integration challenges:
__delay_ms(), __builtin_dmaoffset()For complete block documentation, see C Function Call Block Reference .
Goal: Add a software delay using Microchip XC16/XC-DSC __delay_ms() built-in function.
[Constant: 10] โโ> [C Function Call]
(__delay_ms)
โ
[Delay Applied]
Function Configuration Tab:
| Parameter | Value |
|---|---|
| Parse user file to list functions | โ Unchecked (built-in function) |
| Function Declaration | extern void __delay_ms(unsigned long t_ms); |
| Execute function | when block is updated (default) |
| Block Input | (leave empty - parameter name is t_ms) |
| Function returned value is a block output | โ Off |
| Sample Time | -1 (inherited) |
Pins Configuration Tab: (No configuration needed)
// In model_step() function
void model_step(void) {
// ... other code ...
__delay_ms(rtb_Constant); // Executes every sample time
// ... other code ...
}
t_ms matches the function signatureGoal: Create a custom function that reads a sensor value and returns processed data through output parameters.
#include <stdint.h>
void read_sensor(int16_t input1, int16_t input2, int16_t *output) {
// Combine two analog inputs and average them
*output = (input1 + input2) / 2;
}
[ADC Channel 0] โโโ
โโโ> [C Function Call] โโ> [Display Output]
[ADC Channel 1] โโโ (read_sensor)
Function Configuration Tab:
| Parameter | Value |
|---|---|
| Parse user file to list functions | โ Checked |
| Functions found | read_sensor (auto-detected) |
| Function Declaration | extern void read_sensor(int16_t input1, int16_t input2, int16_t *output); |
| Execute function | when block is updated (default) |
| Block Input | input1, input2 |
| Function returned value is a block output | โ Off |
| Block Output | output |
| Add this function declaration in header file | โ On |
Pins Configuration Tab: (No configuration needed - ADC blocks handle pin setup)
// In model_private.h (if AddHeaderDeclaration enabled)
extern void read_sensor(int16_t input1, int16_t input2, int16_t *output);
// In model_step() function
void model_step(void) {
// ... other code ...
read_sensor(rtb_ADC_Ch0, rtb_ADC_Ch1, &rtb_SensorOutput);
// ... other code ...
}
Goal: Call a custom hardware initialization function only once at power-up.
#include <xc.h>
void init_custom_hardware(void) {
// Configure custom peripheral registers
// This code runs once during startup
// Example: Configure an external chip
// Set up SPI communication
// Load calibration values
}
[Model Initialization]
โ
[C Function Call]
(init_custom_hardware)
โ
[Application Logic]
Function Configuration Tab:
| Parameter | Value |
|---|---|
| Parse user file to list functions | โ Checked |
| Functions found | init_custom_hardware (auto-detected) |
| Function Declaration | extern void init_custom_hardware(void); |
| Execute function | only once at power-up time |
| Block Input | (leave empty - no parameters) |
| Function returned value is a block output | โ Off |
| Add this function declaration in header file | โ On |
Pins Configuration Tab: (Configure if function needs specific GPIO)
// In model_private.h
extern void init_custom_hardware(void);
// In model_initialize() function
void model_initialize(void) {
// ... other initialization ...
init_custom_hardware(); // Called once at startup
// ... other initialization ...
}
| Setting | Execution Location | Use Case |
|---|---|---|
| when block is updated (default) | model_step() | Periodic operations, data processing |
| only once at power-up time | model_initialize() | Hardware setup, calibration, one-time config |
Goal: Monitor CPU utilization and display the current load percentage.
#include <stdint.h>
// Global variable updated by ISR or background task
volatile uint32_t cpu_load_percent = 0;
uint32_t get_cpu_load(void) {
// Return current CPU utilization percentage
return cpu_load_percent;
}
[C Function Call] โโ> [Display/Scope]
(get_cpu_load) (CPU Load %)
Function Configuration Tab:
| Parameter | Value |
|---|---|
| Parse user file to list functions | โ Checked |
| Functions found | get_cpu_load (auto-detected) |
| Function Declaration | extern uint32_t get_cpu_load(void); |
| Execute function | when block is updated (default) |
| Block Input | (leave empty - no parameters) |
| Function returned value is a block output | โ On |
| Sample Time | 0.1 (update every 100ms) |
Pins Configuration Tab: (No configuration needed)
// In model_private.h
extern uint32_t get_cpu_load(void);
// In model_step() function
void model_step(void) {
// ... other code ...
rtb_CPULoad = get_cpu_load(); // Return value assigned to output
// ... other code ...
}
Goal: Control an LED pattern using custom GPIO manipulation code with automatic pin configuration.
#include <xc.h>
#include <stdint.h>
void set_led_pattern(uint8_t pattern) {
// Write pattern to PORTB pins 0-7
LATB = pattern & 0xFF;
}
[Pattern Generator] โโ> [C Function Call] โโ> LED Hardware
(0-255) (set_led_pattern) (PORTB 0-7)
Function Configuration Tab:
| Parameter | Value |
|---|---|
| Parse user file to list functions | โ Checked |
| Functions found | set_led_pattern (auto-detected) |
| Function Declaration | extern void set_led_pattern(uint8_t pattern); |
| Execute function | when block is updated (default) |
| Block Input | pattern |
| Function returned value is a block output | โ Off |
Pins Configuration Tab:
| Parameter | Value |
|---|---|
| List of port used as Digital Output | B[0:7] |
| List of port used as Digital Input | (empty) |
| List of port used as Analog Input | (empty) |
// In model_private.h
extern void set_led_pattern(uint8_t pattern);
// In model_initialize() - Automatic GPIO configuration
void model_initialize(void) {
// Configure PORTB pins 0-7 as digital outputs
TRISBbits.TRISB0 = 0; // Output
TRISBbits.TRISB1 = 0;
TRISBbits.TRISB2 = 0;
TRISBbits.TRISB3 = 0;
TRISBbits.TRISB4 = 0;
TRISBbits.TRISB5 = 0;
TRISBbits.TRISB6 = 0;
TRISBbits.TRISB7 = 0;
// Disable analog function (if device has ANSEL registers)
ANSELBbits.ANSB0 = 0; // Digital mode
ANSELBbits.ANSB1 = 0;
ANSELBbits.ANSB2 = 0;
ANSELBbits.ANSB3 = 0;
ANSELBbits.ANSB4 = 0;
ANSELBbits.ANSB5 = 0;
ANSELBbits.ANSB6 = 0;
ANSELBbits.ANSB7 = 0;
// ... other initialization ...
}
// In model_step() - Function call
void model_step(void) {
// ... other code ...
set_led_pattern(rtb_Pattern);
// ... other code ...
}
| Format | Example | Description |
|---|---|---|
| Single pin | A5 | Configure single pin (RA5) |
| Range | B[0:7] | Configure pins RB0 through RB7 |
| Multiple | A[0 1 2] | Configure RA0, RA1, RA2 |
| Mixed | A[1 2] B5 C[7:9] | Multiple ports and ranges |
The block generates initialization code for:
| Port Type | TRIS Setting | ANSEL Setting |
|---|---|---|
| Digital Input | TRISx = 1 (input) | ANSELx = 0 (digital) |
| Digital Output | TRISx = 0 (output) | ANSELx = 0 (digital) |
| Analog Input | TRISx = 1 (input) | ANSELx = 1 (analog) |
Symptom: Linker error undefined reference to 'my_function'
Solutions:
Symptom: Function receives unexpected values or garbage data
Solutions:
param1, param2, param3 (spaces optional)Symptom: Pin remains in default state (usually input/analog)
Solutions:
A0 or A[0] for single pin, A[0 1 2] for multiplemodel_initialize() to confirm setupSymptom: Initialization function runs every step, or periodic function runs only once
Solutions:
-1 for inherited)model_step() vs model_initialize()read_temperature_sensor not read_temp)inline keyword for small, frequently-called functions