Dein Warenkorb ist gerade leer!
BACnet …
BACNET Task erstellen…
Du bekommst den offiziellen BACnet/IP Stack von Steve Karg hier:
🔗 https://github.com/bacnet-stack/bacnet-stack
Hier ablegen:
/Middlewares/BACnet/bacnet-stack/
├── bacnet/ ← kompletter Inhalt aus GitHub
├── ports/embedded/ ← für embedded config (optional)
├── demo/ ← nicht notwendig, kann gelöscht werden
In deinem Build-Setup (STM32CubeIDE → Properties → C/C++ General → Includes):
Füge diese Include-Pfade hinzu:
Middlewares/BACnet/bacnet
Middlewares/BACnet/bacnet/basic
Middlewares/BACnet/bacnet/basic/sys
Middlewares/BACnet/bacnet/datalink
Middlewares/BACnet/bacnet/object
Middlewares/BACnet/bacnet/services
------------------------------------------------------------------
bacnet_task.c:
------------------------------------------------------------------
#include "bacnet_task.h"
#include "socket.h"
#include "wizchip_conf.h"
#include "w5500.h"
#include "bacnet/bacnet.h"
#include "bacnet/datalink/bip.h"
#include "bacnet/basic/sys/mstimer.h"
#include "bacnet/basic/sys/debug.h"
#include "cmsis_os.h"
#include <string.h>
#include "bacnet_config.h"
bacnet_config_init();
#define BACNET_PORT 47808
#define BACNET_BUFFER_SIZE 1476
static uint8_t bacnet_socket = 0;
static uint8_t bacnet_buf[BACNET_BUFFER_SIZE];
static BACNET_ADDRESS src;
void bacnet_task_init(void)
{
// UDP-Socket für BACnet/IP öffnen (Port 47808)
bacnet_socket = socket(1, Sn_MR_UDP, BACNET_PORT, 0);
if (bacnet_socket != 1) {
debug_printf("[BACnet] Fehler beim Öffnen des UDP-Sockets\n");
} else {
debug_printf("[BACnet] Socket geöffnet auf Port %u\n", BACNET_PORT);
}
// BACnet Stack initialisieren
Device_Init(NULL);
bip_init(NULL);
mstimer_init();
dlenv_init();
}
void StartBACnetTask(void *argument)
{
bacnet_task_init();
for(;;)
{
uint16_t len = getSn_RX_RSR(bacnet_socket);
if (len > 0 && len < BACNET_BUFFER_SIZE) {
int received = recvfrom(bacnet_socket, bacnet_buf, len, (uint8_t*)&src.mac, &src.port);
if (received > 0) {
npdu_handler(&src, bacnet_buf, received);
}
}
// BACnet interne Timer verarbeiten
mstimer_tick(10);
osDelay(10); // 10ms Taktung
}
}
------------------------------------------------------------------
bacnet_task.h:
------------------------------------------------------------------
#ifndef __BACNET_TASK_H
#define __BACNET_TASK_H
#ifdef __cplusplus
extern "C" {
#endif
void StartBACnetTask(void *argument);
#ifdef __cplusplus
}
#endif
#endif // __BACNET_TASK_H
------------------------------------------------------------------
bacnet_config.h:
------------------------------------------------------------------
#include "bacnet/basic/object/device.h"
#include "bacnet/basic/object/analogValue.h"
#include "bacnet/basic/object/analogInput.h"
#include "bacnet/basic/object/analogOutput.h"
#include "bacnet/basic/object/binaryOutput.h"
#include "bacnet/basic/object/binaryInput.h"
#include "bacnet/basic/object/multistateInput.h"
#include "bacnet/basic/services/handlers/h_rpm.h"
#include "bacnet/basic/sys/debug.h"
#include "stm32h7xx_hal.h"
#include "data_points.h"
#include <stdint.h>
// Beispielwerte (können per WriteProperty geändert werden)
static float analog_input_value[4] = {21.5, 22.0, 23.1, 24.3};
static float analog_output_value[1] = {0.0};
static float analog_value_value[1] = {50.0};
static BACNET_BINARY_PV binary_output_state[1] = {BINARY_INACTIVE};
static BACNET_BINARY_PV binary_input_state[1] = {BINARY_INACTIVE};
static uint32_t multistate_input_value[1] = {2};
// GPIO Mapping: z. B. PE15 als Ausgang für Binary Output 0
#define BO0_GPIO_PORT GPIOE
#define BO0_GPIO_PIN GPIO_PIN_15
#define BI0_GPIO_PORT GPIOE
#define BI0_GPIO_PIN GPIO_PIN_4
void bacnet_config_init(void)
{
// Device-Objekt
Device_Set_Object_Instance_Number(1234);
Device_Object_Name_Set("STM32H7 BACnet Device", 24);
Device_Vendor_Identifier_Set(123);
// Analoge Eingänge
Analog_Input_Init();
Analog_Input_Instances_Set(4);
Analog_Input_Name_Set(0, "Temp Sensor 1", 14);
Analog_Input_Name_Set(1, "Temp Sensor 2", 14);
Analog_Input_Name_Set(2, "Temp Sensor 3", 14);
Analog_Input_Name_Set(3, "Temp Sensor 4", 14);
for (unsigned i = 0; i < 4; i++) {
Analog_Input_Present_Value_Set(i, analog_input_value[i]);
}
// Analoge Ausgänge
Analog_Output_Init();
Analog_Output_Instances_Set(1);
Analog_Output_Present_Value_Set(0, analog_output_value[0]);
Analog_Output_Name_Set(0, "Lüfterregelung", 16);
// Analoge Werte
Analog_Value_Init();
Analog_Value_Instances_Set(1);
Analog_Value_Present_Value_Set(0, analog_value_value[0]);
Analog_Value_Name_Set(0, "Sollwert", 8);
// Binary Output
Binary_Output_Init();
Binary_Output_Instances_Set(1);
Binary_Output_Name_Set(0, "Ventil", 6);
Binary_Output_Present_Value_Set(0, binary_output_state[0]);
HAL_GPIO_WritePin(BO0_GPIO_PORT, BO0_GPIO_PIN, binary_output_state[0] == BINARY_ACTIVE ? GPIO_PIN_SET : GPIO_PIN_RESET);
// Binary Input
Binary_Input_Init();
Binary_Input_Instances_Set(1);
Binary_Input_Name_Set(0, "Schalter", 8);
binary_input_state[0] = (HAL_GPIO_ReadPin(BI0_GPIO_PORT, BI0_GPIO_PIN) == GPIO_PIN_SET) ? BINARY_ACTIVE : BINARY_INACTIVE;
Binary_Input_Present_Value_Set(0, binary_input_state[0]);
// Multistate Input
Multistate_Input_Init();
Multistate_Input_Instances_Set(1);
Multistate_Input_Name_Set(0, "Moduswahl", 10);
Multistate_Input_Present_Value_Set(0, multistate_input_value[0]);
Multistate_Input_Number_Of_States_Set(0, 3);
// ReadPropertyMultiple aktivieren
handler_read_property_multiple_init();
// Abbildung für data_points
datapoint_add_float("AI1", &analog_input_value[0], DP_READONLY);
datapoint_add_float("AI2", &analog_input_value[1], DP_READONLY);
datapoint_add_float("AO1", &analog_output_value[0], DP_RW);
datapoint_add_float("AV1", &analog_value_value[0], DP_RW);
datapoint_add_uint32("MSI1", &multistate_input_value[0], DP_RW);
datapoint_add_bool("BO1", (bool*)&binary_output_state[0], DP_RW);
datapoint_add_bool("BI1", (bool*)&binary_input_state[0], DP_READONLY);
debug_printf("[BACnet] Device/Objekte konfiguriert\n");
}
------------------------------------------------------------------
data_points.c:
------------------------------------------------------------------
#include "data_points.h"
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#define MAX_DATAPOINTS 32
typedef struct {
char name[16];
void *ptr;
datapoint_type_t type;
datapoint_access_t access;
} datapoint_entry_t;
static datapoint_entry_t dp_list[MAX_DATAPOINTS];
static uint8_t dp_count = 0;
bool datapoint_add_float(const char *name, float *ptr, datapoint_access_t access)
{
if (dp_count >= MAX_DATAPOINTS) return false;
strncpy(dp_list[dp_count].name, name, sizeof(dp_list[dp_count].name)-1);
dp_list[dp_count].ptr = ptr;
dp_list[dp_count].type = DP_FLOAT;
dp_list[dp_count].access = access;
dp_count++;
return true;
}
bool datapoint_add_bool(const char *name, bool *ptr, datapoint_access_t access)
{
if (dp_count >= MAX_DATAPOINTS) return false;
strncpy(dp_list[dp_count].name, name, sizeof(dp_list[dp_count].name)-1);
dp_list[dp_count].ptr = ptr;
dp_list[dp_count].type = DP_BOOL;
dp_list[dp_count].access = access;
dp_count++;
return true;
}
bool datapoint_add_uint32(const char *name, uint32_t *ptr, datapoint_access_t access)
{
if (dp_count >= MAX_DATAPOINTS) return false;
strncpy(dp_list[dp_count].name, name, sizeof(dp_list[dp_count].name)-1);
dp_list[dp_count].ptr = ptr;
dp_list[dp_count].type = DP_UINT32;
dp_list[dp_count].access = access;
dp_count++;
return true;
}
void datapoint_list_all(void)
{
for (uint8_t i = 0; i < dp_count; i++) {
printf("%s = ", dp_list[i].name);
switch (dp_list[i].type) {
case DP_FLOAT:
printf("%.2f", *((float*)dp_list[i].ptr));
break;
case DP_BOOL:
printf("%s", *((bool*)dp_list[i].ptr) ? "true" : "false");
break;
case DP_UINT32:
printf("%lu", *((uint32_t*)dp_list[i].ptr));
break;
}
printf(" (%s)\n", dp_list[i].access == DP_RW ? "rw" : "ro");
}
}
bool datapoint_set_value(const char *name, const char *value)
{
for (uint8_t i = 0; i < dp_count; i++) {
if (strcmp(dp_list[i].name, name) == 0 && dp_list[i].access == DP_RW) {
switch (dp_list[i].type) {
case DP_FLOAT:
*((float*)dp_list[i].ptr) = atof(value);
return true;
case DP_BOOL:
*((bool*)dp_list[i].ptr) = (strcmp(value, "1") == 0 || strcmp(value, "true") == 0);
return true;
case DP_UINT32:
*((uint32_t*)dp_list[i].ptr) = strtoul(value, NULL, 10);
return true;
}
}
}
return false;
}
------------------------------------------------------------------
data_points.h:
------------------------------------------------------------------
#ifndef __DATA_POINTS_H
#define __DATA_POINTS_H
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef enum {
DP_FLOAT,
DP_BOOL,
DP_UINT32
} datapoint_type_t;
typedef enum {
DP_READONLY,
DP_RW
} datapoint_access_t;
// Registrierung
bool datapoint_add_float(const char *name, float *ptr, datapoint_access_t access);
bool datapoint_add_bool(const char *name, bool *ptr, datapoint_access_t access);
bool datapoint_add_uint32(const char *name, uint32_t *ptr, datapoint_access_t access);
// Zugriff
void datapoint_list_all(void);
bool datapoint_set_value(const char *name, const char *value);
#ifdef __cplusplus
}
#endif
#endif // __DATA_POINTS_H
Tags:

Schreibe einen Kommentar