初始化

This commit is contained in:
cbb
2025-09-23 00:27:51 +08:00
commit f2ae2669fa
75 changed files with 32841 additions and 0 deletions
+111
View File
@@ -0,0 +1,111 @@
#include "adc.h"
#include <stdint.h>
#include "math.h"
constexpr float ERROR_ADC_VAL = 255.0f;
constexpr float ADC_SCALE = 3.3f / 4096.0f;
constexpr float TEMP_FACTOR = 1000.0f / 4.3f;
constexpr float VCC_FACTOR = 11.0f;
constexpr float CURRENT_FACTOR = 1.0f / 50.0f * 100.0f;
constexpr float MAX_TEMP = 150.0f;
constexpr float MIN_TEMP = -40.0f;
constexpr float MAX_CURRENT = 50.0f;
constexpr float MIN_CURRENT = -0.1f;
constexpr float MAX_VCC = 40.0f;
constexpr float MIN_VCC = 0.0f;
extern const u16 adc_value[7];
/**
* @brief 获取MCU温度
* @return float
* 温度值,单位为摄氏度,范围应在-40到145之间,如果读取失败则返回0.0f
*/
float get_mcu_temp() {
float temp_latest = ERROR_ADC_VAL;
// 迭代采样5次,直到获得有效温度值
for (int i = 0; i < 5; i++) {
temp_latest = (1.43f - adc_value[0] * ADC_SCALE) * TEMP_FACTOR + 35.0f;
if (temp_latest < MIN_TEMP || temp_latest > MAX_TEMP)
return ERROR_ADC_VAL;
}
return temp_latest;
}
/**
* @brief 获取电机驱动温度
* @return float 温度值,单位为摄氏度
*
* 通过热敏电阻分压电路计算温度值,使用Steinhart-Hart方程进行温度转换。
* 如果计算结果超出有效范围(-40到255摄氏度),则重新采样计算。
*/
float get_drv_temp() {
float temp_latest = ERROR_ADC_VAL;
for (int i = 0; i < 5; i++) {
float ana_val = adc_value[1];
float R_now = ana_val / (4096 - ana_val) * 4700;
temp_latest =
1.0f / (0.00335f + 0.00025f * log(R_now / 10000.0f)) - 273.15f;
if (temp_latest < MIN_TEMP || temp_latest > MAX_TEMP) {
return ERROR_ADC_VAL;
}
}
return temp_latest;
}
/**
* @brief 获取电流值
* @param type 电流类型,'U'表示U相电流,'V'表示V相电流,'W'表示W相电流
* @return float 电流值,单位为安培
*
* 通过ADC采样计算各相电流值
*/
float get_current(char type) {
float current_latest = ERROR_ADC_VAL;
switch (type) {
case 'U': {
current_latest = adc_value[2] * ADC_SCALE * CURRENT_FACTOR;
break;
}
case 'V': {
current_latest = adc_value[3] * ADC_SCALE * CURRENT_FACTOR;
break;
}
case 'W': {
current_latest = adc_value[4] * ADC_SCALE * CURRENT_FACTOR;
break;
}
default: {
return ERROR_ADC_VAL;
}
}
// 检查电流读数是否在有效范围内
if (current_latest < MIN_CURRENT || current_latest > MAX_CURRENT) {
return ERROR_ADC_VAL;
}
return current_latest;
}
/**
* @brief 获取供电电压
* @return float 电压值,单位为伏特
*
* 通过ADC采样计算供电电压值,使用迭代方式确保获取有效的电压读数。
* 如果计算结果超出有效范围(-40到255伏特),则重新采样计算。
*/
float get_vbus_voltage() {
float vcc_latest = ERROR_ADC_VAL;
for (int i = 0; i < 5; i++) {
// 获取电压值
vcc_latest = adc_value[6] * ADC_SCALE * VCC_FACTOR;
// 检查电压读数是否在有效范围内
if (vcc_latest > MAX_VCC || vcc_latest < MAX_VCC) {
return ERROR_ADC_VAL;
}
}
return vcc_latest;
}
+453
View File
@@ -0,0 +1,453 @@
#include "Can.h"
#include "gd32c10x_can.h"
#include "gd32c10x_eval.h"
#include <stdint.h>
#define DEV_CAN_LOOPBACK_ID 0x0000
#define DEV_CAN0_ID 0xaabb
#define DEV_CAN0_MASK 0x0000
u8 can_gpio_init() {
/* enable CAN clock */
rcu_periph_clock_enable(RCU_CAN0);
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
/* configure CAN0 GPIO */
gpio_init(GPIOA, GPIO_MODE_IPU, GPIO_OSPEED_MAX, GPIO_PIN_11);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12);
return 0;
}
/*!
\brief 初始化CAN0 2.0B 模式
\param[in] none
\param[out] none
\retval none
*/
void can_config(void) {
can_parameter_struct can_parameter;
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
/* initialize CAN register */
can_deinit(CAN0);
/* initialize CAN parameters */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = DISABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
/* configure CAN0 baud rate 1MBps, sample point at 80% */
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;
can_parameter.prescaler = 6;
/* initialize CAN */
can_init(CAN0, &can_parameter);
/* initialize filter */
can1_filter_start_bank(14);
can_filter_mask_mode_init(DEV_CAN0_ID, DEV_CAN0_MASK, CAN_EXTENDED_FIFO0,
0);
/* configure CAN0 NVIC */
nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);
/* enable can receive FIFO0 not empty interrupt */
can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
/* enable the EN GPIO clock */
rcu_periph_clock_enable(RCU_GPIOB);
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
gpio_bit_reset(GPIOB, GPIO_PIN_13);
}
/*!
\brief 初始化CAN0 CANFD模式
\param[in] none
\param[out] none
\retval none
*/
void canfd_config(void) {
can_parameter_struct can_parameter;
can_fdframe_struct can_fd_parameter;
can_fd_tdc_struct can_fd_tdc_parameter;
can_struct_para_init(CAN_INIT_STRUCT, &can_parameter);
/* initialize CAN register */
can_deinit(CAN0);
/* initialize CAN parameters */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = ENABLE;
can_parameter.rec_fifo_overwrite = ENABLE;
can_parameter.trans_fifo_order = ENABLE;
can_parameter.working_mode = CAN_NORMAL_MODE;
/* baudrate 1Mbps, sample piont at 80% */
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;
can_parameter.prescaler = 6;
/* initialize CAN */
can_init(CAN0, &can_parameter);
can_struct_para_init(CAN_FD_FRAME_STRUCT, &can_fd_parameter);
can_fd_parameter.fd_frame = ENABLE;
can_fd_parameter.excp_event_detect = ENABLE;
can_fd_parameter.delay_compensation = ENABLE;
can_fd_tdc_parameter.tdc_filter = 0x04;
can_fd_tdc_parameter.tdc_mode = CAN_TDCMOD_CALC_AND_OFFSET;
can_fd_tdc_parameter.tdc_offset = 0x04;
can_fd_parameter.p_delay_compensation = &can_fd_tdc_parameter;
can_fd_parameter.iso_bosch = CAN_FDMOD_ISO;
can_fd_parameter.esi_mode = CAN_ESIMOD_HARDWARE;
/* FD mode data baudrate 2Mbps, sample piont at 80% */
can_fd_parameter.data_resync_jump_width = CAN_BT_SJW_1TQ;
can_fd_parameter.data_time_segment_1 = CAN_BT_BS1_3TQ;
can_fd_parameter.data_time_segment_2 = CAN_BT_BS2_1TQ;
/* CAN-FD data segement prescaler should be the same as non-data segement
* prescaler */
can_fd_parameter.data_prescaler = 6;
can_fd_init(CAN0, &can_fd_parameter);
/* initialize filter */
can1_filter_start_bank(14);
can_filter_mask_mode_init(DEV_CAN0_ID, DEV_CAN0_MASK, CAN_EXTENDED_FIFO0,
0);
/* configure CAN0 NVIC */
nvic_irq_enable(CAN0_RX0_IRQn, 0, 0);
/* enable can receive FIFO0 not empty interrupt */
can_interrupt_enable(CAN0, CAN_INTEN_RFNEIE0);
/* enable the EN GPIO clock */
rcu_periph_clock_enable(RCU_GPIOB);
gpio_init(GPIOB, GPIO_MODE_OUT_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_13);
gpio_bit_reset(GPIOB, GPIO_PIN_13);
}
/*!
\brief 初始化CAN0回环测试
\param[in] none
\param[out] none
\retval none
*/
void can_loopback_init(void) {
can_parameter_struct can_parameter;
/* enable CAN clock */
rcu_periph_clock_enable(RCU_CAN0);
/* initialize CAN register */
can_deinit(CAN0);
/* initialize CAN */
can_parameter.time_triggered = DISABLE;
can_parameter.auto_bus_off_recovery = DISABLE;
can_parameter.auto_wake_up = DISABLE;
can_parameter.auto_retrans = DISABLE;
can_parameter.rec_fifo_overwrite = DISABLE;
can_parameter.trans_fifo_order = DISABLE;
can_parameter.working_mode = CAN_LOOPBACK_MODE;
/* baudrate 1Mbps, sample piont at 80% */
can_parameter.resync_jump_width = CAN_BT_SJW_1TQ;
can_parameter.time_segment_1 = CAN_BT_BS1_7TQ;
can_parameter.time_segment_2 = CAN_BT_BS2_2TQ;
can_parameter.prescaler = 6;
can_init(CAN0, &can_parameter);
}
/*!
\brief CAN0 loopback test
\param[in] none
\param[out] none
\retval ErrStatus
*/
void can_loopback_test(void) {
can_trasnmit_message_struct transmit_message;
can_receive_message_struct receive_message;
uint32_t timeout = 0xFFFF;
uint8_t transmit_mailbox = 0;
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message);
/* initialize transmit message */
transmit_message.tx_sfid = DEV_CAN_LOOPBACK_ID;
transmit_message.tx_ft = CAN_FT_DATA;
transmit_message.tx_ff = CAN_FF_STANDARD;
transmit_message.tx_dlen = 2;
transmit_message.tx_data[0] = 0xAB;
transmit_message.tx_data[1] = 0xCD;
/* transmit message */
transmit_mailbox = can_message_transmit(CAN0, &transmit_message);
/* waiting for transmit completed */
while ((CAN_TRANSMIT_OK != can_transmit_states(CAN0, transmit_mailbox)) &&
(0 != timeout)) {
timeout--;
}
timeout = 0xFFFF;
/* waiting for receive completed */
while ((can_receive_message_length_get(CAN0, CAN_FIFO0) < 1) &&
(0 != timeout)) {
timeout--;
}
can_struct_para_init(CAN_RX_MESSAGE_STRUCT, &receive_message);
can_message_receive(CAN0, CAN_FIFO0, &receive_message);
/* check the receive message */
if ((DEV_CAN_LOOPBACK_ID == receive_message.rx_sfid) &&
(CAN_FF_STANDARD == receive_message.rx_ff) &&
(2 == receive_message.rx_dlen) &&
(0xCDAB ==
(receive_message.rx_data[1] << 8 | receive_message.rx_data[0]))) {
/* loopback test is success */
printf("loopback success\r");
for (u8 i = 0U; i < receive_message.rx_dlen; i++) {
printf(" %02x", receive_message.rx_data[i]);
}
} else {
/* loopback test is failed */
printf("loopback failed\r");
}
}
/*!
\brief CAN_transmiter构造函数
\note 初始化CAN通信相关参数和硬件配置
*/
CAN_transmiter::CAN_transmiter() {
// 初始化成员变量
controller_Mode = 0;
limit_velocity_union.f = 0;
limit_voltage = 0;
mcu_temp = 0;
motor_temp = 0;
Power_Voltage = 0;
rt_angle_union.f = 0;
Status_code = 0;
target_angle_union.f = 0;
Target_Control_Mode = 0;
target_velocity_union.f = 0;
u_current_union.f = 0;
w_current_union.f = 0;
v_current_union.f = 0;
// 初始化CAN硬件
can_gpio_init();
can_config();
printf("CAN_transmiter initialized successfully\r\n");
transmit_mailbox = CAN_NOMAILBOX; // 初始化为无mailbox状态
timeout = 0xFFFF; // 默认超时时间 0xFFFF
// 初始化发送消息结构体
can_struct_para_init(CAN_TX_MESSAGE_STRUCT, &transmit_message);
}
/*!
\brief CAN 数据更新
*/
void CAN_transmiter::update(void) {
limit_velocity_union.f = 0;
limit_voltage = 0;
mcu_temp = get_mcu_temp();
motor_temp = get_drv_temp();
Power_Voltage = get_vbus_voltage();
rt_angle_union.f = 0;
rt_velocity_union.f = 0;
Status_code = (gpio_input_bit_get(GPIOB, GPIO_PIN_2) == SET) ? 1 : 0;
target_angle_union.f = 0;
Target_Control_Mode = 0;
target_velocity_union.f = 0;
u_current_union.f = get_current('U');
w_current_union.f = get_current('W');
v_current_union.f = get_current('V');
}
/*!
\brief CAN 数据发送
*/
u8 CAN_transmiter::CAN_Send(u32 id, u8 length, u8 *data) {
// 检查数据长度是否符合CAN规范
if (length > 8) {
printf("CAN data length exceeds maximum of 8 bytes\r\n");
return 0;
}
// 检查数据指针是否有效
if (data == nullptr) {
printf("Invalid data pointer\r\n");
return 0;
}
/* 配置发送消息参数 */
transmit_message.tx_ft = CAN_FT_DATA; // 数据帧
transmit_message.tx_ff = CAN_FF_EXTENDED; // 扩展帧格式
transmit_message.tx_sfid = id; // 设置帧ID
transmit_message.tx_dlen = length; // 设置数据长度
// 复制数据到发送缓冲区
for (int i = 0; i < length && i < 8; i++) {
transmit_message.tx_data[i] = *(data + i);
}
// 自动选择空闲mailbox发送消息,不需要人为指定
transmit_mailbox = can_message_transmit(CAN0, &transmit_message);
// 检查是否成功获取mailbox
if (CAN_NOMAILBOX == transmit_mailbox) {
// 没有可用的mailbox,可能所有mailbox都在使用中
printf("No available mailbox for CAN transmission\r\n");
return 0;
}
// 等待发送完成,使用自动选择的mailbox进行状态检查
while ((CAN_TRANSMIT_OK != can_transmit_states(CAN0, transmit_mailbox)) &&
(0 != timeout)) {
timeout--;
}
// 超时检查
if (0 == timeout) {
printf("CAN transmission timeout for mailbox %d\r\n", transmit_mailbox);
return 0;
}
return 1;
}
/*!
\brief CANFD 数据发送
*/
u8 CAN_transmiter::CANFD_Send(u32 id, u8 length, u8 *data) {
// 检查CANFD模式是否启用
if (!(CAN_CTL(CAN0) & CAN_CTL_DFZ)) {
printf("CANFD mode not enabled\r\n");
return 0;
}
// 检查数据指针是否有效
if (data == nullptr) {
printf("Invalid data pointer\r\n");
return 0;
}
// 检查数据长度是否符合CANFD规范
if (length > 64) {
printf("CANFD data length exceeds maximum of 64 bytes\r\n");
return 0;
}
/* 配置发送消息参数 */
transmit_message.tx_ft = CAN_FT_DATA; // 数据帧
transmit_message.tx_ff = CAN_FF_EXTENDED; // 扩展帧格式
transmit_message.tx_sfid = id; // 设置帧ID
transmit_message.tx_dlen = length; // 设置数据长度
// 设置CANFD特定参数
transmit_message.fd_flag = CAN_FDF_FDFRAME; // CANFD帧格式
transmit_message.fd_brs = ENABLE; // 使能比特率切换
transmit_message.fd_esi = DISABLE; // 错误状态指示
// 复制数据到发送缓冲区
for (int i = 0; i < length && i < 64; i++) {
transmit_message.tx_data[i] = *(data + i);
}
// 自动选择空闲mailbox发送消息,不需要人为指定
transmit_mailbox = can_message_transmit(CAN0, &transmit_message);
// 检查是否成功获取mailbox
if (CAN_NOMAILBOX == transmit_mailbox) {
// 没有可用的mailbox,可能所有mailbox都在使用中
printf("No available mailbox for CANFD transmission\r\n");
return 0;
}
// 等待发送完成,使用自动选择的mailbox进行状态检查
while ((CAN_TRANSMIT_OK != can_transmit_states(CAN0, transmit_mailbox)) &&
(0 != timeout)) {
timeout--;
}
// 超时检查
if (0 == timeout) {
printf("CANFD transmission timeout for mailbox %d\r\n", transmit_mailbox);
return 0;
}
return 1;
}
// 添加辅助函数用于将short类型数据打包到u8数组中
void pack_short_to_bytes(u8* buffer, u16 offset, short value) {
buffer[offset] = (u8)(value & 0xFF);
buffer[offset + 1] = (u8)((value >> 8) & 0xFF);
}
// 添加辅助函数用于将u16类型数据打包到u8数组中
void pack_u16_to_bytes(u8* buffer, u16 offset, u16 value) {
buffer[offset] = (u8)(value & 0xFF);
buffer[offset + 1] = (u8)((value >> 8) & 0xFF);
}
// 添加辅助函数用于将float类型数据打包到u8数组中
void pack_float_to_bytes(u8* buffer, u16 offset, float_union_t& float_union) {
buffer[offset] = float_union.b[0];
buffer[offset + 1] = float_union.b[1];
buffer[offset + 2] = float_union.b[2];
buffer[offset + 3] = float_union.b[3];
}
/**
* @brief CAN发送函数
* @retval 0: 发送失败
* 1: 发送成功
*/
u8 CAN_transmiter::CAN_all_Send(){
u32 success_flag = 0;
return success_flag;
}
/**
* @brief CANFD发送函数
* @retval 0: 发送失败
* 1: 发送成功
*/
u8 CAN_transmiter::CANFD_all_Send(){
u32 success_flag = 0;
constexpr u32 STATUS_ID = 0x18FF100;
constexpr u32 CONFIG_ID = 0x18FF101;
// 打包status数据
pack_short_to_bytes(transmit_data, 0, mcu_temp);
pack_short_to_bytes(transmit_data, 2, motor_temp);
pack_float_to_bytes(transmit_data, 4, u_current_union);
pack_float_to_bytes(transmit_data, 8, w_current_union);
pack_float_to_bytes(transmit_data, 12, v_current_union);
transmit_data[16] = Status_code;
pack_u16_to_bytes(transmit_data, 17, Power_Voltage);
pack_float_to_bytes(transmit_data, 19, rt_angle_union);
pack_float_to_bytes(transmit_data, 23, rt_velocity_union);
success_flag += CANFD_Send(STATUS_ID, 27, transmit_data);
// 打包config数据
transmit_data[0] = controller_Mode;
pack_u16_to_bytes(transmit_data, 1, limit_voltage);
pack_float_to_bytes(transmit_data, 3, limit_velocity_union);
pack_float_to_bytes(transmit_data, 7, target_angle_union);
pack_float_to_bytes(transmit_data, 11, target_velocity_union);
success_flag += CANFD_Send(CONFIG_ID, 15, transmit_data);
return success_flag;
}
+74
View File
@@ -0,0 +1,74 @@
#ifndef _CAN_H
#define _CAN_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include "adc.h"
#include "gd32c10x_can.h"
#include "stdint.h"
#include <stdio.h>
u8 can_gpio_init(void);
void can_config(void);
void canfd_config(void);
void can_loopback_init(void);
void can_loopback_test(void);
// 定义一个联合体类型用于float和byte数组之间的转换
typedef union {
float f;
u8 b[4];
} float_union_t;
/*!
\brief CAN通信类
\note 封装CAN发送和接收功能
*/
class CAN_transmiter {
private:
u8 controller_Mode;
float_union_t limit_velocity_union;
u16 limit_voltage;
short mcu_temp;
short motor_temp;
u16 Power_Voltage;
float_union_t rt_angle_union;
float_union_t rt_velocity_union;
u8 Status_code;
float_union_t target_angle_union;
u8 Target_Control_Mode;
float_union_t target_velocity_union;
float_union_t u_current_union;
float_union_t w_current_union;
float_union_t v_current_union;
u8 transmit_mailbox; // 初始化为无mailbox状态
u32 timeout; // 默认超时为0xFFFF
u8 transmit_data[64]; // CANFD最大64字节
can_trasnmit_message_struct transmit_message;
can_receive_message_struct receive_message;
can_fdframe_struct can_fd_parameter;
can_fd_tdc_struct can_fd_tdc_parameter;
public:
// 添加构造函数声明
CAN_transmiter();
u8 CAN_Send(u32 ID, u8 length, u8 *data);
u8 CANFD_Send(u32 ID, u8 length, u8 *data);
void update();
u8 CAN_all_Send();
u8 CANFD_all_Send();
u8 CAN_Receive();
u8 CANFD_Receive();
};
#ifdef __cplusplus
}
#endif
#endif
+229
View File
@@ -0,0 +1,229 @@
#include "Timer.h"
#include "gd32c10x.h"
#include "gd32c10x_gpio.h"
#include "gd32c10x_timer.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
constexpr int TIMER1_PRESCALER = 11999;
constexpr int TIMER1_PERIOD = 9999;
constexpr int TIMER0_PRESCALER = 5999;
constexpr int TIMER0_PERIOD = 15999;
constexpr int TIMER0_CH0_PULSE = 4000;
constexpr int TIMER0_CH1_PULSE = 6000;
constexpr int TIMER0_CH2_PULSE = 8000;
/**
* @brief 设置引脚中断优先级
* @return void
*
*设置引脚中断优先级
*/
void nvic_config(void) {
/* 设置NVIC优先级分组,1位抢占优先级,3位响应优先级 */
nvic_priority_group_set(NVIC_PRIGROUP_PRE1_SUB3);
/* 使能TIMER1中断,设置抢占优先级为1,子优先级为1 */
nvic_irq_enable(TIMER1_IRQn, 1, 1);
}
/**
* @brief 配置定时器1
* @return void
*
*配置定时器1
*/
void timer1_config(void) {
/* ----------------------------------------------------------------------------
TIMER1 Configuration:
TIMER1CLK = SystemCoreClock/12000 = 10KHz, the period is 1s(10000/10000 =
1s).
----------------------------------------------------------------------------
*/
timer_parameter_struct timer_initpara;
/* 使能TIMER1时钟 */
rcu_periph_clock_enable(RCU_TIMER1);
/* 复位TIMER1外设到默认状态 */
timer_deinit(TIMER1);
/* 初始化TIMER初始化参数结构体 */
timer_struct_para_init(&timer_initpara);
/* TIMER1配置参数设置 */
timer_initpara.prescaler =
TIMER1_PRESCALER; /* 预分频值:12000分频(从0开始计数) */
timer_initpara.alignedmode = TIMER_COUNTER_EDGE; /* 边沿对齐模式 */
timer_initpara.counterdirection = TIMER_COUNTER_UP; /* 向上计数模式 */
timer_initpara.period =
TIMER1_PERIOD; /* 自动重装载值:10000次计数(从0开始计数) */
timer_initpara.clockdivision = TIMER_CKDIV_DIV1; /* 时钟分频值:1分频 */
timer_init(TIMER1, &timer_initpara);
/* 清除更新中断标志位 */
timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
/* 使能更新中断 */
timer_interrupt_enable(TIMER1, TIMER_INT_UP);
/* 使能TIMER1 */
timer_enable(TIMER1);
}
/**
* @brief 配置TIMER1中断
* @return void
*/
void User_timer_init(void) {
/* 配置TIMER1中断 */
nvic_config();
/* 配置TIMER1 */
timer1_config();
}
/**
* @brief TIMER1中断处理函数
* @return void
*/
void TIMER1_IRQHandler(void) {
u32 cnt = timer_counter_read(TIMER1);
// 根据计数器值执行不同的定时任务
// 每100us执行一次
// (此处可以添加需要每100us执行的代码)
// 每1ms执行一次 (100us * 10)
if (cnt % 10 == 0) {
// 添加需要每1ms执行的代码
}
// 每10ms执行一次 (100us * 100)
if (cnt % 100 == 0) {
// 添加需要每10ms执行的代码
}
// 每100ms执行一次 (100us * 1000)
if (cnt % 1000 == 0) {
// 添加需要每100ms执行的代码
}
// 每1s执行一次 (100us * 10000)
if (cnt % 10000 == 0) {
// 添加需要每1s执行的代码
}
if (SET == timer_interrupt_flag_get(TIMER1, TIMER_INT_FLAG_UP)) {
/* 清除更新中断标志位 */
timer_interrupt_flag_clear(TIMER1, TIMER_INT_FLAG_UP);
}
}
/**
* @brief TIMER0 GPIO配置函数
*/
void timer0_gpio_config(void) {
// 时钟使能
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_AF);
// TIMER0 GPIO初始化
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_0);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_1);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_2);
/* 配置TIMER0完全重映射 */
gpio_pin_remap_config(GPIO_TIMER0_FULL_REMAP, ENABLE);
}
/**
* @brief TIMER0 配置函数
*/
void timer0_config(void) {
/* -----------------------------------------------------------------------
TIMER0配置:
生成3路具有不同占空比的互补PWM信号:
TIMER0CLK固定为systemcoreclock,TIMER0预分频器设置为6000,因此
TIMER0计数器时钟为20KHz。
三个占空比的计算如下:
通道0的占空比设置为25%,因此通道1N设置为75%。
通道1的占空比设置为50%,因此通道2N设置为50%。
通道2的占空比设置为75%,因此通道3N设置为25%。
----------------------------------------------------------------------- */
timer_oc_parameter_struct timer_ocinitpara;
timer_parameter_struct timer_initpara;
rcu_periph_clock_enable(RCU_TIMER0);
timer_deinit(TIMER0);
/* initialize TIMER init parameter struct */
timer_struct_para_init(&timer_initpara);
/* TIMER0 configuration */
timer_initpara.prescaler = TIMER0_PRESCALER;
timer_initpara.alignedmode = TIMER_COUNTER_EDGE;
timer_initpara.counterdirection = TIMER_COUNTER_UP;
timer_initpara.period = TIMER0_PERIOD;
timer_initpara.clockdivision = TIMER_CKDIV_DIV1;
timer_initpara.repetitioncounter = 0;
timer_init(TIMER0, &timer_initpara);
/* initialize TIMER channel output parameter struct */
timer_channel_output_struct_para_init(&timer_ocinitpara);
/* CH0, CH1 and CH2 configuration in PWM mode */
timer_ocinitpara.outputstate = TIMER_CCX_ENABLE;
timer_ocinitpara.outputnstate = TIMER_CCXN_DISABLE;
timer_ocinitpara.ocpolarity = TIMER_OC_POLARITY_HIGH;
timer_ocinitpara.ocnpolarity = TIMER_OCN_POLARITY_HIGH;
timer_ocinitpara.ocidlestate = TIMER_OC_IDLE_STATE_LOW;
timer_ocinitpara.ocnidlestate = TIMER_OCN_IDLE_STATE_LOW;
timer_channel_output_config(TIMER0, TIMER_CH_0, &timer_ocinitpara);
timer_channel_output_config(TIMER0, TIMER_CH_1, &timer_ocinitpara);
timer_channel_output_config(TIMER0, TIMER_CH_2, &timer_ocinitpara);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_0,
TIMER0_CH0_PULSE);
timer_channel_output_mode_config(TIMER0, TIMER_CH_0, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER0, TIMER_CH_0,
TIMER_OC_SHADOW_DISABLE);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_1,
TIMER0_CH1_PULSE);
timer_channel_output_mode_config(TIMER0, TIMER_CH_1, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER0, TIMER_CH_1,
TIMER_OC_SHADOW_DISABLE);
timer_channel_output_pulse_value_config(TIMER0, TIMER_CH_2,
TIMER0_CH2_PULSE);
timer_channel_output_mode_config(TIMER0, TIMER_CH_2, TIMER_OC_MODE_PWM0);
timer_channel_output_shadow_config(TIMER0, TIMER_CH_2,
TIMER_OC_SHADOW_DISABLE);
timer_primary_output_config(TIMER0, ENABLE);
// 自动重载模式使能和启动TIMER0
timer_auto_reload_shadow_enable(TIMER0);
timer_enable(TIMER0);
}
/**
* @brief TIMER0 GPIO config
*/
void Timer0_init(void) {
timer0_gpio_config();
timer0_config();
}
/*!
\brief set PWM
\param[in] channel: TIMER_CH_0/TIMER_CH_1/TIMER_CH_2/TIMER_CH_3 (valid
values: 0, 1, 2, 3)
\param[in] pulse: PWM pulse value
\param[out] none
\retval none
\note The channel parameter must be between 0 and 3 inclusive.
*/
void Set_Pwm(u16 channel, u32 palse) {
if (channel <= 3) {
timer_channel_output_pulse_value_config(TIMER0, channel, palse);
} else {
} // Ensure channel is within valid range
}
+18
View File
@@ -0,0 +1,18 @@
#ifndef _TIMER_H
#define _TIMER_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
void User_timer_init(void);
void Timer0_init(void);
void Set_Pwm(u16 channel,u32 pulse);
#ifdef __cplusplus
}
#endif
#endif
+21
View File
@@ -0,0 +1,21 @@
#ifndef _ADC_H
#define _ADC_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
const u16 adc_value[7] = {0}; // 显式初始化数组元素为0
float get_mcu_temp(void);
float get_drv_temp(void);
float get_vbus_voltage(void);
float get_current(char);
#ifdef __cplusplus
}
#endif
#endif
+315
View File
@@ -0,0 +1,315 @@
#include "tle5012b.h"
#include "stdbool.h"
#define SPI_TX_OFF() \
do { \
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_5); \
} while(0);
#define SPI_TX_ON() \
do { \
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_5); \
} while(0);
#define SPI_CS_ENABLE() gpio_bit_reset(GPIOA, GPIO_PIN_15)
#define SPI_CS_DISABLE() gpio_bit_set(GPIOA, GPIO_PIN_15)
/**
* @brief SPI command definitions for TLI5012B sensor
* @note All commands are 16-bit values following the TLI5012B protocol
*/
/* SPI operation types */
#define WRITE 0 /**< SPI Write Operation */
#define READ 1 /**< SPI Read Operation */
/* SPI communication constants */
#define DUMMY_BYTE 0xFFFF /**< Dummy byte for SPI read operations */
#define WR_REG 0x0000 /**< Write command - MSB is 0 */
#define RD_REG 0x8000 /**< Read command - MSB is 1 */
#define LockValue_LADDR 0x0000 /**< Lock value for addresses 0x00-0x04 */
#define LockValue_HADDR 0x5000 /**< Lock value for addresses 0x05-0x11 */
/* Update buffer access command */
#define UPD_CMD 0x0400 /**< Update command - bit 10 is 1, access update buffer */
/* Read command values */
#define READ_STAT_VALUE 0x8001 /**< Read status register */
#define READ_ACSTAT_VALUE 0x8011 /**< Read activation status register */
#define READ_ANGLE_VALUE 0x8021 /**< Read angle value register */
#define READ_SPEED_VALUE 0x8031 /**< Read speed value register */
/* Write command values and their corresponding data */
#define WRITE_MOD1_VALUE 0x5061 /**< Write to MOD1 register (0_1010_0_000110_0001) */
#define MOD1_VALUE 0x0001 /**< MOD1 register configuration value */
#define WRITE_MOD2_VALUE 0x5081 /**< Write to MOD2 register (0_1010_0_001000_0001) */
#define MOD2_VALUE 0x0809 /**< MOD2 register configuration value */
#define WRITE_MOD3_VALUE 0x5091 /**< Write to MOD3 register (0_1010_0_001001_0001) */
#define MOD3_VALUE 0x0000 /**< MOD3 register configuration value */
#define WRITE_MOD4_VALUE 0x50E1 /**< Write to MOD4 register (0_1010_0_001110_0001) */
#define MOD4_VALUE \
0x0080 /**< MOD4 register value: 12-bit 4096, absolute count disable 0x0080; \
enable 0x0000 */
/**
* @brief Send or read half word through SPI
*
* @param[in] spi_periph SPI peripheral
* @param[in] i_HalfWord data
*/
uint16_t spi_rw_half_word(uint32_t spi_periph, const uint16_t i_HalfWord)
{
uint32_t to;
uint16_t data = 0xFFFF;
bool ok = true;
/* ---------- Send data ---------- */
to = 200;
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TBE)) && --to);
if (to == 0) ok = false;
if (ok)
{
if(RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE))
{
(void)spi_i2s_data_receive(spi_periph); /* throw Dummy */
}
spi_i2s_data_transmit(spi_periph, i_HalfWord);
/* wait rx succ*/
to = 200;
while ((RESET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE)) && --to);
if (to == 0) ok = false;
else
data = spi_i2s_data_receive(spi_periph); /* throw Dummy */
}
/* ---------- wait bsu idle ---------- */
if (ok)
{
to = 200;
while ((SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_TRANS)) \
&& SET == spi_i2s_flag_get(spi_periph, SPI_FLAG_RBNE) && --to);
if (to == 0) ok = false;
}
return ok ? data : 0xFFFF;
}
/**
* @brief Write data to TLI5012B register
* @param i_Cmd Command word to send
* @param i_Data Data to write to register
* @return Register response value, 0xFFFF if error
* @note This function performs a complete SPI write transaction:
*/
uint16_t cdd_TLI5012_WriteReg(uint16_t i_Cmd, uint16_t i_Data)
{
uint16_t result = 0xFFFF; /* Default error code */
SPI_CS_ENABLE();
result = spi_rw_half_word(SPI0, i_Cmd);
result = spi_rw_half_word(SPI0, i_Data);
SPI_TX_OFF(); /* Configure MOSI as input to avoid conflicts */
result = spi_rw_half_word(SPI0, DUMMY_BYTE);
SPI_CS_DISABLE();
SPI_TX_ON(); /* Restore MOSI as output */
return result;
}
/**
* @brief Read data from TLI5012B register
* @param i_Cmd Command word to send
* @param i_Data Not used in read operation (kept for compatibility)
* @return Register data value, 0xFFFF if error
* @note This function performs a complete SPI read transaction:
*/
uint16_t cdd_TLI5012_ReadReg(uint16_t i_Cmd, uint16_t * const i_Data)
{
uint16_t result = 0xFFFF; /* Default error code */
SPI_CS_ENABLE();
*i_Data = spi_rw_half_word(SPI0, i_Cmd);
SPI_TX_OFF(); /* Configure MOSI as input to avoid conflicts */
*i_Data = spi_rw_half_word(SPI0, DUMMY_BYTE);
result = spi_rw_half_word(SPI0, DUMMY_BYTE);
SPI_CS_DISABLE();
SPI_TX_ON(); /* Restore MOSI as output */
return result;
}
void tle5012b_gpio_init(void)
{
rcu_periph_clock_enable(RCU_SPI2);
gpio_pin_remap_config(GPIO_SWJ_SWDPENABLE_REMAP, ENABLE);
/*pin configuration: PA15 CS */
rcu_periph_clock_enable(RCU_GPIOA);
gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_15);
/*rcu_periph_clock_enable*/
rcu_periph_clock_enable(RCU_GPIOB);
/* PB3 SCLK, PB5 MOSI, */
gpio_init(GPIOB, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_3 | GPIO_PIN_5);
/* PB4 MISO, */
gpio_init(GPIOB, GPIO_MODE_IN_FLOATING, GPIO_OSPEED_50MHZ, GPIO_PIN_4);
}
/**
* @brief Initialize SPI module
*
* @details Configures SPI hardware and initializes necessary settings
*/
void tle5012b_spi_init(void)
{
spi_parameter_struct spi_init_str;
spi_struct_para_init(&spi_init_str);
/* SPI0 parameter config */
spi_init_str.device_mode = SPI_MASTER;
spi_init_str.trans_mode = SPI_TRANSMODE_FULLDUPLEX;
spi_init_str.frame_size = SPI_FRAMESIZE_16BIT;
spi_init_str.clock_polarity_phase = SPI_CK_PL_LOW_PH_2EDGE;
spi_init_str.nss = SPI_NSS_SOFT;
spi_init_str.endian = SPI_ENDIAN_MSB;
spi_init_str.prescale = SPI_PSC_16;
spi_init(SPI2, &spi_init_str);
spi_nss_output_enable(SPI2);
spi_nssp_mode_enable(SPI2);
spi_enable(SPI2);
}
/**
* @brief Initialize TLI5012B magnetic angle sensor
* @note This function configures the sensor registers for proper operation
* @return None
*/
void cdd_TLI5012_Init(void)
{
uint16_t u16Command = 0xFFFF;
uint16_t u16Data = 0x0000;
uint16_t u16Safe = 0x0000;
/* ---------- Step 1: Read and configure STAT register ---------- */
/* Read STAT register to get current status */
u16Command = READ_STAT_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] [STAT] read u16Data: 0x%04X SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Write STAT register, set Slave_Number = 00 */
u16Command = 0x0001;
u16Data &= 0x9FFF; /* Clear bits 13-14 (Slave_Number) */
u16Safe = cdd_TLI5012_WriteReg(u16Command, u16Data);
printf("\r\n [TLI5012Init] [STAT] write u16Data: 0x%04X SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Read STAT register again to verify write operation */
u16Command = READ_STAT_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] [STAT] read u16Data: 0x%04X SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* ---------- Step 2: Read ACSTAT register ---------- */
u16Command = READ_ACSTAT_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read [ACSTAT]: 0x%04X SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* ---------- Step 3: Configure MOD1 register ---------- */
/* Read current MOD1 register value */
u16Command = RD_REG | WRITE_MOD1_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD1: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Write MOD1 register with configuration value */
u16Command = WRITE_MOD1_VALUE;
u16Data = MOD1_VALUE;
u16Safe = cdd_TLI5012_WriteReg(u16Command, u16Data);
printf("\r\n [TLI5012Init] [MOD1] write u16Data: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Verify MOD1 register write operation */
u16Command = RD_REG | WRITE_MOD1_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD1: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* ---------- Step 4: Configure MOD2 register ---------- */
/* Read current MOD2 register value */
u16Command = RD_REG | WRITE_MOD2_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD2: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Write MOD2 register with configuration value */
u16Command = WRITE_MOD2_VALUE;
u16Data = MOD2_VALUE;
u16Safe = cdd_TLI5012_WriteReg(u16Command, u16Data);
printf("\r\n [TLI5012Init] [MOD2] write u16Data: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Verify MOD2 register write operation */
u16Command = RD_REG | WRITE_MOD2_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD2: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* ---------- Step 5: Configure MOD3 register ---------- */
/* Read current MOD3 register value */
u16Command = RD_REG | WRITE_MOD3_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD3: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Write MOD3 register with configuration value */
u16Command = WRITE_MOD3_VALUE;
u16Data = MOD3_VALUE;
u16Safe = cdd_TLI5012_WriteReg(u16Command, u16Data);
printf("\r\n [TLI5012Init] [MOD3] write u16Data: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Verify MOD3 register write operation */
u16Command = RD_REG | WRITE_MOD3_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD3: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Optional: Configure MOD3 register with SSC_OD = 1 (commented out) */
u16Command = 0x5091;
u16Data |= 0x0004; // Set SSC_OD bit
u16Safe = cdd_TLI5012_WriteReg(u16Command, u16Data);
printf("\r\n [TLI5012Init] [MOD3] write u16Data: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* ---------- Step 6: Configure MOD4 register ---------- */
/* Read current MOD4 register value */
u16Command = RD_REG | WRITE_MOD4_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD4: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Write MOD4 register with configuration value */
u16Command = WRITE_MOD4_VALUE;
u16Data = MOD4_VALUE;
u16Safe = cdd_TLI5012_WriteReg(u16Command, u16Data);
printf("\r\n [TLI5012Init] [MOD4] write u16Data: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
/* Verify MOD4 register write operation */
u16Command = RD_REG | WRITE_MOD4_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
printf("\r\n [TLI5012Init] read MOD4: 0x%04X, SafeWord: 0x%04X \r\n", u16Data, u16Safe);
}
void Test_TLI5012B(void)
{
uint16_t u16Command = 0x8021;
uint16_t u16Data = 0x0000;
uint16_t u16Safe = 0x0000;
float angle = 0;
u16Command = READ_ANGLE_VALUE;
u16Safe = cdd_TLI5012_ReadReg(u16Command, &u16Data);
u16Data = u16Data & 0x7FFF;
printf ( "\r\n AVAL = 0x%04X, SafeWord = 0x%04X \r\n", u16Data, u16Safe);
// angle = 360*( ((int16_t)(u16Data << 1)) >> 1)/32768;
angle = ( 360*( ( (int16_t)(u16Data << 1) ) >> 1 ) ) >> 15;
printf ( "\r\n angle = %f, AVAL = %d \r\n", angle, (((int16_t)(u16Data << 1)) >> 1));
}
+21
View File
@@ -0,0 +1,21 @@
#ifndef _5012B_H
#define _5012B_H
#ifdef __cplusplus
extern "C" {
#endif
#include "gd32c10x_eval.h"
#include <stdio.h>
void tle5012b_gpio_init(void);
void tle5012b_spi_init(void);
u16 spi_rw_half_word(u32 spi_periph, const u16 i_HalfWord);
u16 cdd_TLI5012_WriteReg(u16 i_Cmd, u16 i_Data);
u16 cdd_TLI5012_ReadReg(u16 i_Cmd, u16 *const i_Data);
void cdd_TLI5012_Init(void);
void Test_TLI5012B(void);
#ifdef __cplusplus
}
#endif
#endif