当前位置:   article > 正文

【STM32】利用C++/C编写STM32代码_stm32 c++

stm32 c++

0、前言

C++编写STM32代码,如何进行?

将编译器改成6
在这里插入图片描述

1、与STM32Cubemx的冲突

这是我的博客,虽然编译没有问题,但是代码放到STM32单片机上面运行不起来。
说明解决方法不对。但是大师兄就是用这种方法来实现的。先这么做吧!

http://t.csdnimg.cn/4Nj0D
  • 1

不得不说,tortoiseGit是个好东西!!我今天发布了教程,可以去看看。

2、让STM32代码支持现代C++特性

http://t.csdnimg.cn/ftYmW

如果后期,我32代码用到了现代C++特性,参考这一篇文章

3、C/C++混合编程

3.1 在C++中调用C函数

有些器件,商家提供的是api函数是C语言编写,这时候想偷懒,直接调用,不想用C++重新编写了。

想在.cpp中调用c函数,首先要在cpp.h头文件中包含c函数的.h文件,同时在c函数的.h文件加上

#ifdef __cplusplus
extern "C" {
#endif

// 主体代码......

#ifdef __cplusplus
}
#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

必须要全部括进去,我当时只括了我所用的函数,结果报错。

举个GO电机例子:

cpp_GoMotor.h
#ifndef __CPP_GOMOTOR_H
#define __CPP_GOMOTOR_H
#include <stdint.h>
#include "stm32g4xx_hal.h" // stm32 hal
#include "stm32g4xx_hal_def.h"
#include "GO_M8010_6.h"



class Go_MotorData
{
public:
    Go_MotorData();
    float Speed;                        // speed
    float Torque_Current;               // 当前实际电机输出力矩
    float Angle;                        // 当前电机位置(主控0点修正,电机关节还是以编码器0点为准)
    unsigned char motor_id;             //电机ID
    unsigned char mode;                 // 0:空闲, 5:开环转动, 10:闭环FOC控制
    int Temp;                           //温度
    unsigned char MError;               //错误码
    float footForce;                    // 足端气压传感器数据 12bit (0-4095)
};

class GoMotor
{
public:
    GoMotor();

    void State_Init(uint8_t id);
    void Set_Blank(int id);
    void Set_Torque(float goal_Torque, int id);

    void receive_feedback(uint32_t id, uint8_t *data_p);

    uint8_t ID_;
    Go_MotorData motor_data_;

private:
};


#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
cpp_GoMotor.cpp
#include "cpp_GoMotor.h"
#include "stm32g4xx_hal_def.h" // stm32 hal
#include "usart.h"
#include "stdio.h"
#include "cmsis_os.h"
#define GO_DELAY_MS 1

Go_MotorData::Go_MotorData()
{
    Speed = 0;                        // speed
    Torque_Current = 0;               // 当前实际电机输出力矩
    Angle = 0;                        // 当前电机位置(主控0点修正,电机关节还是以编码器0点为准)
    motor_id = 0;             //电机ID
    mode = 0;                 // 0:空闲, 5:开环转动, 10:闭环FOC控制
    Temp = 0;                           //温度
    MError = 0;               //错误码
    footForce = 0;                    // 足端气压传感器数据 12bit (0-4095)
}

GoMotor::GoMotor()
{
}

void GoMotor::State_Init(uint8_t id)
{
    Go_State_init(id); // C函数
}

void GoMotor::Set_Blank(int id)
{
    Set_Blank(id);
}

void GoMotor::Set_Torque(float goal_Torque, int id)
{
    GO_Set_Torque(goal_Torque, id);
}

void GoMotor::receive_feedback(uint32_t id, uint8_t *data_p)
{
    // 关于数组标号,在GO_M8010_6.c的void GO_UART_IRQHandler(UART_HandleTypeDef *huart)
    motor_data_.motor_id = data_p[0];
    motor_data_.Angle = data_p[6];
    motor_data_.Speed = data_p[5];
    motor_data_.Torque_Current = data_p[4];
    motor_data_.Temp = data_p[2];
    motor_data_.mode = data_p[1];
    motor_data_.footForce = data_p[7];
    motor_data_.MError = data_p[3];
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
GO_M8010_6.h
#ifndef __MOTOR_CONTORL_H
#define __MOTOR_CONTORL_H
#include <stdint.h>
#include "stm32g4xx_hal_def.h" // stm32 hal
#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif

#define SET_485_DE_UP() HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET)  //定义
#define SET_485_DE_DOWN() HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_RESET)

#define SET_485_RE_UP() HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_SET)
#define SET_485_RE_DOWN() HAL_GPIO_WritePin(RS485_DE_GPIO_Port, RS485_DE_Pin, GPIO_PIN_RESET)

#define SET_4852_DE_UP() HAL_GPIO_WritePin(RS4852_DE_GPIO_Port, RS4852_DE_Pin, GPIO_PIN_SET)  //定义
#define SET_4852_DE_DOWN() HAL_GPIO_WritePin(RS4852_DE_GPIO_Port, RS4852_DE_Pin, GPIO_PIN_RESET)

#define SET_4852_RE_UP() HAL_GPIO_WritePin(RS4852_DE_GPIO_Port, RS4852_DE_Pin, GPIO_PIN_SET)
#define SET_4852_RE_DOWN() HAL_GPIO_WritePin(RS4852_DE_GPIO_Port, RS4852_DE_Pin, GPIO_PIN_RESET)
typedef signed char int8_t;
typedef signed short int int16_t;
typedef signed int int32_t;
typedef signed long long int64_t;

/* exact-width unsigned integer types */
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;
typedef unsigned char bool_t;
typedef float fp32;
typedef double fp64;

extern HAL_StatusTypeDef GoMotor_SendRecv_IsOk;

/**
 * @brief Go-M8010-6关节电机驱动 精简通讯指令集
 * @version 0.1
 * @date 2022-03-04
 * @copyright Copyright (c) unitree robotics .co.ltd. 2022
 */

#pragma pack(1)

/**
 * @brief 电机模式控制信息
 *
 */
typedef struct
{
    uint8_t id     : 4;     // 电机ID: 0,1...,13,14 15表示向所有电机广播数据(此时无返回)
    uint8_t status : 3;     // 工作模式: 0.锁定 1.FOC闭环 2.编码器校准 3.保留
    uint8_t none   : 1;     // 保留位
} RIS_Mode_t;   // 控制模式 1Byte

/**
 * @brief 电机状态控制信息
 *
 */
typedef struct
{
    int16_t tor_des;        // 期望关节输出扭矩 unit: N.m      (q8)
    int16_t spd_des;        // 期望关节输出速度 unit: rad/s    (q8)
    int32_t pos_des;        // 期望关节输出位置 unit: rad      (q15)
    int16_t k_pos;          // 期望关节刚度系数 unit: -1.0-1.0 (q15)
    int16_t k_spd;          // 期望关节阻尼系数 unit: -1.0-1.0 (q15)

} RIS_Comd_t;   // 控制参数 12Byte

/**
 * @brief 电机状态反馈信息
 *
 */
typedef struct
{
    int16_t  torque;        // 实际关节输出扭矩 unit: N.m     (q8)
    int16_t  speed;         // 实际关节输出速度 unit: rad/s   (q8)
    int32_t  pos;           // 实际关节输出位置 unit: rad     (q15)
    int8_t   temp;          // 电机温度: -128~127°C
    uint8_t  MError : 3;    // 电机错误标识: 0.正常 1.过热 2.过流 3.过压 4.编码器故障 5-7.保留
    uint16_t force  : 12;   // 足端气压传感器数据 12bit (0-4095)
    uint8_t  none   : 1;    // 保留位
} RIS_Fbk_t;   // 状态数据 11Byte

/*
 * Actuator Communication Reduced Instruction Set
 * Unitree robotics (c) .Co.Ltd. 2022 All Rights Reserved.
 */
typedef union
{
    int32_t     L;
    uint8_t     u8[4];
    uint16_t    u16[2];
    uint32_t    u32;
    float       F;
} COMData32;

typedef struct
{
    // 定义 数据包头
    unsigned char start[2]; // 包头
    unsigned char motorID;  // 电机ID  0,1,2,3 ...   0xBB 表示向所有电机广播(此时无返回)
    unsigned char reserved;
} COMHead;

typedef struct
{
    // 以 4个字节一组排列 ,不然编译器会凑整
    // 定义 数据
    uint8_t mode;       // 当前关节模式
    uint8_t ReadBit;    // 电机控制参数修改     是否成功位
    int8_t Temp;        // 电机当前平均温度
    uint8_t MError;     // 电机错误 标识

    COMData32 Read;     // 读取的当前 电机 的控制数据
    int16_t T;          // 当前实际电机输出力矩       7 + 8 描述

    int16_t W;          // 当前实际电机速度(高速)   8 + 7 描述
    float LW;           // 当前实际电机速度(低速)

    int16_t W2;         // 当前实际关节速度(高速)   8 + 7 描述
    float LW2;          // 当前实际关节速度(低速)

    int16_t Acc;        // 电机转子加速度       15+0 描述  惯量较小
    int16_t OutAcc;     // 输出轴加速度         12+3 描述  惯量较大

    int32_t Pos;        // 当前电机位置(主控0点修正,电机关节还是以编码器0点为准)
    int32_t Pos2;       // 关节编码器位置(输出编码器)

    int16_t INS[3];    // 电机驱动板6轴传感器数据
    int16_t acc[3];

    // 力传感器的数据
    int16_t Fgyro[3];
    int16_t Facc[3];
    int16_t Fmag[3];
    uint8_t Ftemp;      // 8位表示的温度  7位(-28~100度)  1位0.5度分辨率

    int16_t Force16;    // 力传感器高16位数据
    int8_t Force8;      // 力传感器低8位数据

    uint8_t FError;     //  足端传感器错误标识

    int8_t Res[1];      // 通讯 保留字节

} ServoComdV3; // 加上数据包的包头 和CRC 78字节(4+70+4)

typedef struct
{
    uint8_t head[2];    // 包头         2Byte
    RIS_Mode_t mode;    // 电机控制模式  1Byte
    RIS_Fbk_t   fbk;    // 电机反馈数据 11Byte
    uint16_t  CRC16;    // CRC          2Byte
} MotorData_t;  //返回数据

typedef struct
{
    uint8_t none[8];            // 保留

} LowHzMotorCmd;

typedef struct
{
    // 以 4个字节一组排列 ,不然编译器会凑整
    // 定义 数据
    uint8_t mode;               // 关节模式选择
    uint8_t ModifyBit;          // 电机控制参数修改位
    uint8_t ReadBit;            // 电机控制参数发送位
    uint8_t reserved;

    COMData32 Modify;           // 电机参数修改 的数据
    //实际给FOC的指令力矩为:
    // K_P*delta_Pos + K_W*delta_W + T
    int16_t T;                  // 期望关节的输出力矩(电机本身的力矩)x256, 7 + 8 描述
    int16_t W;                  // 期望关节速度 (电机本身的速度) x128,       8 + 7描述
    int32_t Pos;                // 期望关节位置 x 16384/6.2832, 14位编码器(主控0点修正,电机关节还是以编码器0点为准)

    int16_t K_P;                // 关节刚度系数 x2048  4+11 描述
    int16_t K_W;                // 关节速度系数 x1024  5+10 描述

    uint8_t LowHzMotorCmdIndex; // 保留
    uint8_t LowHzMotorCmdByte;  // 保留

    COMData32 Res[1];           // 通讯 保留字节  用于实现别的一些通讯内容

} MasterComdV3;           // 加上数据包的包头 和CRC 34字节

typedef struct
{
    // 定义 电机控制命令数据包
    uint8_t head[2];    // 包头         2Byte
    RIS_Mode_t mode;    // 电机控制模式  1Byte
    RIS_Comd_t comd;    // 电机期望数据 12Byte
    uint16_t   CRC16;   // CRC          2Byte
} ControlData_t;        //电机控制命令数据包

#pragma pack()


//go电机发送接收数据结构体变量
typedef struct
{
    // 定义 发送格式化数据
    ControlData_t motor_send_data;      //电机控制数据结构体
    int hex_len;                        //发送的16进制命令数组长度, 34
    long long send_time;                //发送该命令的时间, 微秒(us)
    // 待发送的各项数据
    unsigned short id;                  //电机ID,0代表全部电机
    unsigned short mode;                // 0:空闲, 5:开环转动, 10:闭环FOC控制
    //实际给FOC的指令力矩为:
    // K_P*delta_Pos + K_W*delta_W + T
    float T;                            //期望关节的输出力矩(电机本身的力矩)(Nm)
    float W;                            //期望关节速度(电机本身的速度)(rad/s)
    float Pos;                          //期望关节位置(rad)
    float K_P;                          //关节刚度系数
    float K_W;                          //关节速度系数
    COMData32 Res;                      // 通讯 保留字节  用于实现别的一些通讯内容

} MOTOR_send;

typedef struct
{
    // 定义 接收数据
    MotorData_t motor_recv_data;        //电机接收数据结构体,详见motor_msg.h
    int hex_len;                        //接收的16进制命令数组长度, 78
    long long resv_time;                //接收该命令的时间, 微秒(us)
    int correct;                        //接收数据是否完整(1完整,0不完整)
    //解读得出的电机数据
    unsigned char motor_id;             //电机ID
    unsigned char mode;                 // 0:空闲, 5:开环转动, 10:闭环FOC控制
    int Temp;                           //温度
    unsigned char MError;               //错误码
    float T;                            // 当前实际电机输出力矩
    float W;                                        // speed
    float Pos;                          // 当前电机位置(主控0点修正,电机关节还是以编码器0点为准)
    float footForce;                            // 足端气压传感器数据 12bit (0-4095)

} MOTOR_recv;


typedef struct
{

    uint32_t           HAL_OK_count; //自检
    fp32               Postemp;   //当前
    fp32               Posinit;

    uint32_t           error_times;//丢包率
    fp32               ErrorRate;
    float              RxRate;

} Go_Check_;

typedef struct
{
    HAL_StatusTypeDef   GO_state[4];     //用来显示四个电机发送是否成功
    Go_Check_           Pos_Check[4];          //位置速度信息

    bool                Check_Flag;
    uint8_t             dma_rx_flag;

    int                 total_times;
    int                 dma_rx_times[4];

} Communicate_state;

//crc
/*
 * This mysterious table is just the CRC of each possible byte. It can be
 * computed using the standard bit-at-a-time methods. The polynomial can
 * be seen in entry 128, 0x8408. This corresponds to x^0 + x^5 + x^12.
 * Add the implicit x^16, and you have the standard CRC-CCITT.
 * https://github.com/torvalds/linux/blob/5bfc75d92efd494db37f5c4c173d3639d4772966/lib/crc-ccitt.c
 */

static uint16_t crc_ccitt_byte(uint16_t crc, const uint8_t c);
static uint16_t crc_ccitt(uint16_t crc, uint8_t const *buffer, size_t len);
uint32_t crc32_core(uint32_t *ptr, uint32_t len);
int modify_data(MOTOR_send *motor_s);
int extract_data(MOTOR_recv *motor_r);
extern MOTOR_recv rx_data[16];
HAL_StatusTypeDef SERVO_1_Send_recv(MOTOR_send *pData, MOTOR_recv *rData,  uint8_t id);
HAL_StatusTypeDef SERVO_2_Send_recv(MOTOR_send *pData, MOTOR_recv *rData,  uint8_t id);
HAL_StatusTypeDef Send_recv(MOTOR_send *pData, MOTOR_recv *rData, uint8_t id);
HAL_StatusTypeDef Go_callback_handle(MOTOR_recv *rData, uint16_t rxlen);
void Go_Callback_Check(uint8_t id, uint16_t rxlen);
extern Communicate_state GO_State;
void Go_State_init(uint8_t id);
void GO_Set_Blank(int id);
void GO_Set_Speed(int goal_speed, int id);
void GO_Set_Pos(float goal_pos, float goal_T, float goal_Kp, int id);
void GO_Set_Damp(float goal_damp, int id);
void GO_Set_Torque(float goal_Torque, int id);
void GO_Set_Zero_Torque(int id);
void GO_UART_IRQHandler(UART_HandleTypeDef *huart);

#ifdef __cplusplus
}
#endif

#endif


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305

3.2 在C中调用C++函数

在关键C/C++接口文件里面,做以下处理:
在这里插入图片描述
在C中调用C++:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/1004302
推荐阅读
相关标签
  

闽ICP备14008679号