赞
踩
C++编写STM32代码,如何进行?
将编译器改成6
这是我的博客,虽然编译没有问题,但是代码放到STM32单片机上面运行不起来。
说明解决方法不对。但是大师兄就是用这种方法来实现的。先这么做吧!
http://t.csdnimg.cn/4Nj0D
不得不说,tortoiseGit是个好东西!!我今天发布了教程,可以去看看。
http://t.csdnimg.cn/ftYmW
如果后期,我32代码用到了现代C++特性,参考这一篇文章
有些器件,商家提供的是api函数是C语言编写,这时候想偷懒,直接调用,不想用C++重新编写了。
想在.cpp中调用c函数,首先要在cpp.h头文件中包含c函数的.h文件,同时在c函数的.h文件加上
#ifdef __cplusplus
extern "C" {
#endif
// 主体代码......
#ifdef __cplusplus
}
#endif
必须要全部括进去,我当时只括了我所用的函数,结果报错。
举个GO电机例子:
#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
#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]; }
#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
在关键C/C++接口文件里面,做以下处理:
在C中调用C++:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。