634 lines
18 KiB
C
634 lines
18 KiB
C
/* USER CODE BEGIN Header */
|
||
/**
|
||
******************************************************************************
|
||
* @file : main.c
|
||
* @brief : Main program body
|
||
******************************************************************************
|
||
* @attention
|
||
*
|
||
* Copyright (c) 2025 STMicroelectronics.
|
||
* All rights reserved.
|
||
*
|
||
* This software is licensed under terms that can be found in the LICENSE file
|
||
* in the root directory of this software component.
|
||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||
*
|
||
******************************************************************************
|
||
*/
|
||
/* USER CODE END Header */
|
||
/* Includes ------------------------------------------------------------------*/
|
||
#include "main.h"
|
||
#include "can.h"
|
||
#include "dma.h"
|
||
#include "tim.h"
|
||
#include "usart.h"
|
||
#include "gpio.h"
|
||
|
||
/* Private includes ----------------------------------------------------------*/
|
||
/* USER CODE BEGIN Includes */
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
/* USER CODE END Includes */
|
||
|
||
/* Private typedef -----------------------------------------------------------*/
|
||
/* USER CODE BEGIN PTD */
|
||
|
||
/* USER CODE END PTD */
|
||
|
||
/* Private define ------------------------------------------------------------*/
|
||
/* USER CODE BEGIN PD */
|
||
|
||
/* USER CODE END PD */
|
||
|
||
/* Private macro -------------------------------------------------------------*/
|
||
/* USER CODE BEGIN PM */
|
||
|
||
/* USER CODE END PM */
|
||
|
||
/* Private variables ---------------------------------------------------------*/
|
||
|
||
/* USER CODE BEGIN PV */
|
||
uint8_t dbus_buf[DBUS_BUFLEN];
|
||
rc_info_t rc = rc_Init;
|
||
extern UART_HandleTypeDef huart3;
|
||
/* USER CODE END PV */
|
||
|
||
/* Private function prototypes -----------------------------------------------*/
|
||
void SystemClock_Config(void);
|
||
/* USER CODE BEGIN PFP */
|
||
|
||
/* USER CODE END PFP */
|
||
|
||
/* Private user code ---------------------------------------------------------*/
|
||
/* USER CODE BEGIN 0 */
|
||
|
||
|
||
//can总线电机6020
|
||
static int uart_receive_dma_no_it(UART_HandleTypeDef* huart, uint8_t* pData, uint32_t Size)
|
||
{
|
||
uint32_t tmp1 = 0;
|
||
tmp1 = huart->RxState;
|
||
|
||
if (tmp1 == HAL_UART_STATE_READY)
|
||
{
|
||
if ((pData == NULL) || (Size == 0))
|
||
{
|
||
return HAL_ERROR;
|
||
}
|
||
|
||
huart->pRxBuffPtr = pData;
|
||
huart->RxXferSize = Size;
|
||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||
|
||
HAL_DMA_Start(huart->hdmarx, (uint32_t)&huart->Instance->DR, (uint32_t)pData, Size);
|
||
|
||
|
||
SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||
|
||
return HAL_OK;
|
||
}
|
||
else
|
||
{
|
||
return HAL_BUSY;
|
||
}
|
||
}
|
||
|
||
void dbus_uart_init(void)
|
||
{
|
||
__HAL_UART_CLEAR_IDLEFLAG(&DBUS_HUART);
|
||
|
||
__HAL_UART_ENABLE_IT(&DBUS_HUART, UART_IT_IDLE);
|
||
|
||
uart_receive_dma_no_it(&DBUS_HUART, dbus_buf, DBUS_MAX_LEN);
|
||
}
|
||
|
||
|
||
void rc_callback_handler(rc_info_t *rc, uint8_t *buff)
|
||
{
|
||
rc->ch0 = (buff[0] | buff[1] << 8) & 0x07FF;
|
||
rc->ch0 -= 1024;
|
||
rc->ch1 = (buff[1] >> 3 | buff[2] << 5) & 0x07FF;
|
||
rc->ch1 -= 1024;
|
||
rc->ch2 = (buff[2] >> 6 | buff[3] << 2 | buff[4] << 10) & 0x07FF;
|
||
rc->ch2 -= 1024;
|
||
rc->ch3 = (buff[4] >> 1 | buff[5] << 7) & 0x07FF;
|
||
rc->ch3 -= 1024;
|
||
rc->roll = (buff[16] | (buff[17] << 8)) & 0x07FF;
|
||
rc->roll -= 1024;
|
||
|
||
rc->sw1 = ((buff[5] >> 4) & 0x000C) >> 2;
|
||
rc->sw2 = (buff[5] >> 4) & 0x0003;
|
||
|
||
if ((abs(rc->ch0) > 660) || \
|
||
(abs(rc->ch1) > 660) || \
|
||
(abs(rc->ch2) > 660) || \
|
||
(abs(rc->ch3) > 660))
|
||
|
||
{
|
||
memset(rc, 0, sizeof(rc_info_t));
|
||
}
|
||
}
|
||
|
||
uint16_t dma_current_data_counter(DMA_Stream_TypeDef *dma_stream)
|
||
{
|
||
return ((uint16_t)(dma_stream->NDTR));
|
||
}
|
||
|
||
static void uart_rx_idle_callback(UART_HandleTypeDef* huart)
|
||
{
|
||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||
|
||
|
||
if (huart == &DBUS_HUART)
|
||
{
|
||
__HAL_DMA_DISABLE(huart->hdmarx);
|
||
|
||
if ((DBUS_MAX_LEN - dma_current_data_counter(huart->hdmarx->Instance)) == DBUS_BUFLEN)
|
||
{
|
||
rc_callback_handler(&rc, dbus_buf);
|
||
}
|
||
__HAL_DMA_SET_COUNTER(huart->hdmarx, DBUS_MAX_LEN);
|
||
__HAL_DMA_ENABLE(huart->hdmarx);
|
||
}
|
||
}
|
||
void uart_receive_handler(UART_HandleTypeDef *huart)
|
||
{
|
||
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE) &&
|
||
__HAL_UART_GET_IT_SOURCE(huart, UART_IT_IDLE))
|
||
{
|
||
uart_rx_idle_callback(huart);
|
||
}
|
||
}typedef struct
|
||
{
|
||
uint16_t ecd;//编码器值 -16384--+16384
|
||
int16_t speed_rpm;//转速 转每分钟
|
||
int16_t given_current;//输出电流值
|
||
uint8_t temperate;//电机温度
|
||
int16_t last_ecd;//上次编码器值
|
||
} motor_measure_t;
|
||
|
||
motor_measure_t motor_chassis[4] = {0};
|
||
//void Drive_Motor(float vx, float vy, float vz);
|
||
//void Motor_Speed_Control_Task(float dt);
|
||
//void Send_Motor_Commands(void);
|
||
//void Motor_PID_Init(void);
|
||
//void Update_Motor_Measure(uint8_t motor_id, motor_measure_t* measure);
|
||
//void Print_Motor_Status(void);
|
||
//void Update_Motor_Measure(uint8_t motor_id, motor_measure_t* measure);
|
||
/**
|
||
* @brief 更新电机测量数据到控制器
|
||
* @param motor_id: 电机ID (0-3)
|
||
* @param measure: 电机测量数据指针
|
||
*/
|
||
|
||
static CAN_TxHeaderTypeDef chassis_tx_message;
|
||
static uint8_t chassis_can_send_data[8];
|
||
void CAN_cmd_chassis(int16_t motor1, int16_t motor2, int16_t motor3, int16_t motor4)
|
||
//can总线数据发送函数
|
||
//motor1-右上 motor2-左上 motor3-左下 motor4-右下
|
||
//以c板的正方向为基准
|
||
{
|
||
uint32_t send_mail_box;
|
||
chassis_tx_message.StdId = 0x1FF;
|
||
chassis_tx_message.IDE = CAN_ID_STD;
|
||
chassis_tx_message.RTR = CAN_RTR_DATA;
|
||
chassis_tx_message.DLC = 0x08;
|
||
chassis_can_send_data[0] = motor1 >> 8;
|
||
chassis_can_send_data[1] = motor1;
|
||
chassis_can_send_data[2] = motor2 >> 8;
|
||
chassis_can_send_data[3] = motor2;
|
||
chassis_can_send_data[4] = motor3 >> 8;
|
||
chassis_can_send_data[5] = motor3;
|
||
chassis_can_send_data[6] = motor4 >> 8;
|
||
chassis_can_send_data[7] = motor4;
|
||
HAL_CAN_AddTxMessage(&hcan1, &chassis_tx_message,
|
||
chassis_can_send_data, &send_mail_box);
|
||
|
||
}
|
||
|
||
//滤波器 只接受 ID 1-4 的电机
|
||
//此段后续可优化为列表模式
|
||
void can_filter_init(void)
|
||
{
|
||
CAN_FilterTypeDef can_filter_st;
|
||
can_filter_st.FilterActivation = ENABLE;
|
||
can_filter_st.FilterMode = CAN_FILTERMODE_IDMASK;
|
||
can_filter_st.FilterScale = CAN_FILTERSCALE_32BIT;
|
||
can_filter_st.FilterIdHigh = 0x0000;//高八位
|
||
can_filter_st.FilterIdLow = 0x0000;//低八位
|
||
can_filter_st.FilterMaskIdHigh = 0x0000;
|
||
can_filter_st.FilterMaskIdLow = 0x0007;
|
||
can_filter_st.FilterBank = 0;
|
||
can_filter_st.FilterFIFOAssignment = CAN_RX_FIFO0;
|
||
HAL_CAN_ConfigFilter(&hcan1, &can_filter_st);
|
||
HAL_CAN_Start(&hcan1);
|
||
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
|
||
|
||
|
||
can_filter_st.SlaveStartFilterBank = 14;
|
||
can_filter_st.FilterBank = 14;
|
||
HAL_CAN_ConfigFilter(&hcan1, &can_filter_st);
|
||
HAL_CAN_Start(&hcan1);
|
||
HAL_CAN_ActivateNotification(&hcan1, CAN_IT_RX_FIFO0_MSG_PENDING);
|
||
}
|
||
//过滤器笔记
|
||
//SlaveStartFilterBank参数只有在双CAN模式(CAN1和CAN2)下才需要,如果只有CAN1,可以不用设置
|
||
|
||
// PID控制器结构体
|
||
typedef struct {
|
||
float kp; // 比例系数
|
||
float ki; // 积分系数
|
||
float kd; // 微分系数
|
||
float integral; // 积分项
|
||
float prev_error; // 上一次误差
|
||
float output; // 输出值
|
||
float integral_limit; // 积分限幅
|
||
float output_limit; // 输出限幅
|
||
} PID_Controller_t;
|
||
|
||
// 电机控制结构体
|
||
typedef struct {
|
||
motor_measure_t measure; // 电机测量值(速度单位:RPM)
|
||
PID_Controller_t speed_pid; // 速度环PID
|
||
float target_speed; // 目标速度 (rad/s)
|
||
} Motor_Controller_t;
|
||
// 四个电机的控制器
|
||
Motor_Controller_t motor_controller[4] = {0};
|
||
// 存储四个电机的控制命令
|
||
int16_t motor_commands[4] = {0};
|
||
// 底盘参数(根据实际机械结构调整)
|
||
#define WHEEL_RADIUS 0.175f // 轮子半径 (米)
|
||
#define WHEELBASE_WIDTH 0.135f // 轮距宽度/2 (米)
|
||
#define WHEELBASE_LENGTH 0.2f // 轮距长度/2 (米)
|
||
/**
|
||
* @brief 更新电机测量数据到控制器
|
||
* @param motor_id: 电机ID (0-3)
|
||
* @param measure: 电机测量数据指针
|
||
*/
|
||
|
||
void Update_Motor_Measure(uint8_t motor_id, motor_measure_t* measure)
|
||
{
|
||
if (motor_id < 4) {
|
||
// 直接结构体赋值(更简洁)
|
||
motor_controller[motor_id].measure = *measure;
|
||
}
|
||
}
|
||
//中断回调函数
|
||
//判断接受对象的ID-符合条件-完成解码-发送数据包
|
||
//motor_chassis:motor_measure_t 类型的数组,其中装有电机转子角度,电机转子转速,控制电流,温度
|
||
//定义函数
|
||
#define get_motor_measure(ptr, data) \
|
||
{ \
|
||
(ptr)->last_ecd = (ptr)->ecd; \
|
||
(ptr)->ecd = (uint16_t)((data)[0] << 8 | (data)[1]); \
|
||
(ptr)->speed_rpm = (uint16_t)((data)[2] << 8 | (data)[3]); \
|
||
(ptr)->given_current = (uint16_t)((data)[4] << 8 | (data)[5]); \
|
||
(ptr)->temperate = (data)[6]; \
|
||
}
|
||
//can传回参数结构体定义
|
||
|
||
//回调函数
|
||
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
|
||
{
|
||
CAN_RxHeaderTypeDef rx_header;
|
||
uint8_t rx_data[8];
|
||
HAL_CAN_GetRxMessage(hcan, CAN_RX_FIFO0, &rx_header, rx_data);
|
||
switch (rx_header.StdId)
|
||
{
|
||
case 1:
|
||
case 2:
|
||
case 3:
|
||
case 4:
|
||
{
|
||
static uint8_t i = 0;
|
||
//读取电机ID
|
||
i = rx_header.StdId - 1;
|
||
get_motor_measure(&motor_chassis[i], rx_data);
|
||
Update_Motor_Measure(i, &motor_chassis[i]);
|
||
break;
|
||
}
|
||
default:
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
//HAL库接收函数HAL_CAN_GetRxMessage
|
||
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[]);
|
||
|
||
/**
|
||
* @brief 将RPM转换为rad/s
|
||
*/
|
||
float RPM_To_RadPerSec(int16_t rpm)
|
||
{
|
||
return (float)rpm * 2.0f * 3.1415926535f / 60.0f;
|
||
}
|
||
|
||
/**
|
||
* @brief 将rad/s转换为RPM
|
||
*/
|
||
int16_t RadPerSec_To_RPM(float rad_per_sec)
|
||
{
|
||
return (int16_t)(rad_per_sec * 60.0f / (2.0f * 3.1415926535f));
|
||
}
|
||
|
||
/**
|
||
* @brief PID控制器初始化
|
||
*/
|
||
void PID_Init(PID_Controller_t* pid, float kp, float ki, float kd, float integral_limit, float output_limit)
|
||
{
|
||
pid->kp = kp;
|
||
pid->ki = ki;
|
||
pid->kd = kd;
|
||
pid->integral = 0.0f;
|
||
pid->prev_error = 0.0f;
|
||
pid->output = 0.0f;
|
||
pid->integral_limit = integral_limit;
|
||
pid->output_limit = output_limit;
|
||
}
|
||
|
||
/**
|
||
* @brief PID计算函数
|
||
*/
|
||
float PID_Calculate(PID_Controller_t* pid, float error, float dt)
|
||
{
|
||
// 比例项
|
||
float proportional = pid->kp * error;
|
||
|
||
// 积分项(带限幅)
|
||
pid->integral += error * dt;
|
||
if (pid->integral > pid->integral_limit) {
|
||
pid->integral = pid->integral_limit;
|
||
} else if (pid->integral < -pid->integral_limit) {
|
||
pid->integral = -pid->integral_limit;
|
||
}
|
||
float integral = pid->ki * pid->integral;
|
||
|
||
// 微分项
|
||
float derivative = pid->kd * (error - pid->prev_error) / dt;
|
||
pid->prev_error = error;
|
||
|
||
// 计算总输出
|
||
pid->output = proportional + integral + derivative;
|
||
|
||
// 输出限幅
|
||
if (pid->output > pid->output_limit) {
|
||
pid->output = pid->output_limit;
|
||
} else if (pid->output < -pid->output_limit) {
|
||
pid->output = -pid->output_limit;
|
||
}
|
||
|
||
return pid->output;
|
||
}
|
||
|
||
/**
|
||
* @brief 初始化所有电机的PID控制器
|
||
*/
|
||
void Motor_PID_Init(void)
|
||
{
|
||
// PID参数(需要根据实际电机调试)
|
||
float speed_kp = 5.0f; // 速度环比例系数
|
||
float speed_ki = 0.5f; // 速度环积分系数
|
||
float speed_kd = 0.1f; // 速度环微分系数
|
||
|
||
for (int i = 0; i < 4; i++) {
|
||
PID_Init(&motor_controller[i].speed_pid, speed_kp, speed_ki, speed_kd, 1000.0f, 16000.0f);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 设置单个电机的目标速度
|
||
* @param motor_id: 电机ID (0-3)
|
||
* @param target_speed_rad_s: 目标速度 (rad/s)
|
||
*/
|
||
void Set_Motor_Target_Speed(uint8_t motor_id, float target_speed_rad_s)
|
||
{
|
||
if (motor_id < 4) {
|
||
motor_controller[motor_id].target_speed = target_speed_rad_s;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* @brief 电机速度控制任务(需要定期调用)
|
||
* @param dt: 时间间隔 (秒)
|
||
*/
|
||
void Motor_Speed_Control_Task(float dt)
|
||
{
|
||
for (int i = 0; i < 4; i++) {
|
||
// 将电机反馈的RPM转换为rad/s
|
||
float actual_speed_rads = RPM_To_RadPerSec(motor_controller[i].measure.speed_rpm);
|
||
|
||
// 计算速度误差(单位:rad/s)
|
||
float speed_error = motor_controller[i].target_speed - actual_speed_rads;
|
||
|
||
// PID计算
|
||
float pid_output = PID_Calculate(&motor_controller[i].speed_pid, speed_error, dt);
|
||
|
||
// 存储控制命令
|
||
motor_commands[i] = (int16_t)pid_output;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
/**
|
||
* @brief 麦克纳姆轮速度解算函数
|
||
* @param vx: X方向速度 (m/s)
|
||
* @param vy: Y方向速度 (m/s)
|
||
* @param vz: 旋转角速度 (rad/s)
|
||
*/
|
||
void Drive_Motor(float vx, float vy, float vz)
|
||
{
|
||
// 麦克纳姆轮运动学逆解算(输出单位:rad/s)
|
||
float wheel1_speed = (+vx + vy + vz * (WHEELBASE_WIDTH + WHEELBASE_LENGTH)) / WHEEL_RADIUS;
|
||
float wheel2_speed = (+vx - vy - vz * (WHEELBASE_WIDTH + WHEELBASE_LENGTH)) / WHEEL_RADIUS;
|
||
float wheel3_speed = (+vx + vy - vz * (WHEELBASE_WIDTH + WHEELBASE_LENGTH)) / WHEEL_RADIUS;
|
||
float wheel4_speed = (+vx - vy + vz * (WHEELBASE_WIDTH + WHEELBASE_LENGTH)) / WHEEL_RADIUS;
|
||
|
||
Set_Motor_Target_Speed(0, wheel1_speed); // 右上轮
|
||
Set_Motor_Target_Speed(1, wheel2_speed); // 左上轮
|
||
Set_Motor_Target_Speed(2, wheel3_speed); // 左下轮
|
||
Set_Motor_Target_Speed(3, wheel4_speed); // 右下轮
|
||
}
|
||
/**
|
||
* @brief 将遥控器值(-660~660)映射为速度值(m/s)
|
||
* @param input: 遥控器输入值 (-660 到 660)
|
||
* @param max_speed: 最大速度 (m/s)
|
||
* @return 映射后的速度值
|
||
*/
|
||
float Map_Remote_to_Speed(int16_t input, float max_speed)
|
||
{
|
||
// 限制输入范围
|
||
if (input > 660) input = 660;
|
||
if (input < -660) input = -660;
|
||
|
||
// 死区处理(避免摇杆微小抖动)
|
||
if (abs(input) < 50) {
|
||
return 0.0f;
|
||
}
|
||
|
||
// 线性映射到速度
|
||
return (input / 660.0f) * max_speed;
|
||
}
|
||
/**
|
||
* @brief 处理遥控器数据并设置底盘速度
|
||
*/
|
||
void Process_Remote_Control(void)
|
||
{
|
||
// 映射遥控器值到速度 (m/s)
|
||
float vx = Map_Remote_to_Speed(rc.ch2, 2.0f); // 前后方向,最大2m/s
|
||
float vy = Map_Remote_to_Speed(rc.ch3, 2.0f); // 左右方向,最大2m/s
|
||
float vz = Map_Remote_to_Speed(rc.ch0, 3.0f); // 旋转方向,最大3rad/s
|
||
|
||
// 调用运动学解算
|
||
Drive_Motor(vx, vy, vz);
|
||
}
|
||
|
||
/* USER CODE END 0 */
|
||
|
||
/**
|
||
* @brief The application entry point.
|
||
* @retval int
|
||
*/
|
||
int main(void)
|
||
{
|
||
|
||
/* USER CODE BEGIN 1 */
|
||
|
||
/* USER CODE END 1 */
|
||
|
||
/* MCU Configuration--------------------------------------------------------*/
|
||
|
||
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
|
||
HAL_Init();
|
||
|
||
/* USER CODE BEGIN Init */
|
||
|
||
/* USER CODE END Init */
|
||
|
||
/* Configure the system clock */
|
||
SystemClock_Config();
|
||
|
||
/* USER CODE BEGIN SysInit */
|
||
|
||
/* USER CODE END SysInit */
|
||
|
||
/* Initialize all configured peripherals */
|
||
MX_GPIO_Init();
|
||
MX_DMA_Init();
|
||
MX_CAN1_Init();
|
||
MX_USART3_UART_Init();
|
||
MX_TIM1_Init();
|
||
/* USER CODE BEGIN 2 */
|
||
dbus_uart_init();
|
||
HAL_CAN_Start(&hcan1);
|
||
Motor_PID_Init();
|
||
can_filter_init();
|
||
uint32_t last_control_time = 0;
|
||
uint32_t dt = 0;
|
||
/* USER CODE END 2 */
|
||
|
||
/* Infinite loop */
|
||
/* USER CODE BEGIN WHILE */
|
||
while (1)
|
||
{ uint32_t current_time = HAL_GetTick();
|
||
|
||
// 控制任务:固定频率执行(100Hz,10ms)
|
||
if (current_time - last_control_time >= 10)
|
||
{
|
||
dt = (current_time - last_control_time) * 0.001f;
|
||
Process_Remote_Control( );
|
||
Motor_Speed_Control_Task(dt);
|
||
CAN_cmd_chassis(motor_commands[0],motor_commands[1],motor_commands[2],motor_commands[3]);
|
||
last_control_time=current_time;
|
||
}
|
||
HAL_Delay(1);
|
||
/* USER CODE END WHILE */
|
||
|
||
/* USER CODE BEGIN 3 */
|
||
}
|
||
/* USER CODE END 3 */
|
||
}
|
||
|
||
|
||
/**
|
||
* @brief System Clock Configuration
|
||
* @retval None
|
||
*/
|
||
void SystemClock_Config(void)
|
||
{
|
||
RCC_OscInitTypeDef RCC_OscInitStruct = {0};
|
||
RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
|
||
|
||
/** Configure the main internal regulator output voltage
|
||
*/
|
||
__HAL_RCC_PWR_CLK_ENABLE();
|
||
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
|
||
|
||
/** Initializes the RCC Oscillators according to the specified parameters
|
||
* in the RCC_OscInitTypeDef structure.
|
||
*/
|
||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
|
||
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
|
||
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
|
||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
|
||
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
|
||
RCC_OscInitStruct.PLL.PLLM = 8;
|
||
RCC_OscInitStruct.PLL.PLLN = 168;
|
||
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
|
||
RCC_OscInitStruct.PLL.PLLQ = 4;
|
||
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
|
||
{
|
||
Error_Handler();
|
||
}
|
||
|
||
/** Initializes the CPU, AHB and APB buses clocks
|
||
*/
|
||
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
|
||
|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
|
||
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
|
||
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
|
||
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
|
||
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;
|
||
|
||
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
|
||
{
|
||
Error_Handler();
|
||
}
|
||
}
|
||
|
||
/* USER CODE BEGIN 4 */
|
||
|
||
/* USER CODE END 4 */
|
||
|
||
/**
|
||
* @brief This function is executed in case of error occurrence.
|
||
* @retval None
|
||
*/
|
||
void Error_Handler(void)
|
||
{
|
||
/* USER CODE BEGIN Error_Handler_Debug */
|
||
/* User can add his own implementation to report the HAL error return state */
|
||
__disable_irq();
|
||
while (1)
|
||
{
|
||
}
|
||
/* USER CODE END Error_Handler_Debug */
|
||
}
|
||
#ifdef USE_FULL_ASSERT
|
||
/**
|
||
* @brief Reports the name of the source file and the source line number
|
||
* where the assert_param error has occurred.
|
||
* @param file: pointer to the source file name
|
||
* @param line: assert_param error line source number
|
||
* @retval None
|
||
*/
|
||
void assert_failed(uint8_t *file, uint32_t line)
|
||
{
|
||
/* USER CODE BEGIN 6 */
|
||
/* User can add his own implementation to report the file name and line number,
|
||
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
|
||
/* USER CODE END 6 */
|
||
}
|
||
#endif /* USE_FULL_ASSERT */
|