调了几天了,一直搞不定,最近刚学嵌入式,求帮助
刚入手了一套基于STM32F103C8T6的直流电机套件,想往里移植PID位置算法,但不知道哪出了问题,串口能发送信息但无法接受上位机信息,没有进入接收中断,而且电机也无法控制转动,怀疑可能初始化或移植程序不兼容出问题了,因为我只干了这两件事。。
电机接线图,只用到了A电机
IN口控制电机运行及旋转方向
USART初始化,用的USART1,
#if USART_EN_RX /* 如果使能了接收 */
UART_HandleTypeDef g_uart1_handle; /* UART句柄 */
/**
* @brief 串口X初始化函数
* @param baudrate: 波特率, 根据自己需要设置波特率值
* @note 注意: 必须设置正确的时钟源, 否则串口波特率就会设置异常.
* 这里的USART的时钟源在sys_stm32_clock_init()函数中已经设置过了.
* @retval 无
*/
void usart_init(uint32_t baudrate)
{
g_uart1_handle.Instance = USART1;
g_uart1_handle.Init.BaudRate = 115200;
g_uart1_handle.Init.WordLength = UART_WORDLENGTH_8B;
g_uart1_handle.Init.StopBits = UART_STOPBITS_1;
g_uart1_handle.Init.Parity = UART_PARITY_NONE;
g_uart1_handle.Init.Mode = UART_MODE_TX_RX;
g_uart1_handle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
g_uart1_handle.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&g_uart1_handle) != HAL_OK)
{
Error_Handler();
}
}
/**
* @brief UART底层初始化函数
* @param huart: UART句柄类型指针
* @note 此函数会被HAL_UART_Init()调用
* 完成时钟使能,引脚配置,中断配置
* @retval 无
*/
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
GPIO_InitTypeDef gpio_init_struct;
if(huart->Instance == USART1) /* 如果是串口1,进行串口1 MSP初始化 */
{
__HAL_RCC_USART1_CLK_ENABLE(); /* USART1 时钟使能 */
__HAL_RCC_GPIOA_CLK_ENABLE(); /* 发送接受引脚时钟使能 */
gpio_init_struct.Pin = GPIO_PIN_9; /* TX引脚 */
gpio_init_struct.Mode = GPIO_MODE_AF_PP; /* 复用推挽输出 */
gpio_init_struct.Pull = GPIO_PULLUP; /* 上拉 */
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH; /* 高速 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 初始化发送引脚 */
gpio_init_struct.Pin = GPIO_PIN_10; /* RX引脚 */
HAL_GPIO_Init(GPIOA, &gpio_init_struct); /* 初始化接收引脚 */
__HAL_UART_DISABLE_IT(&g_uart1_handle, UART_IT_TC); /* 开启中断 */
#if USART_EN_RX
__HAL_UART_ENABLE_IT(&g_uart1_handle, UART_IT_RXNE); /* 开启接收中断 */
HAL_NVIC_SetPriority(USART_UX_IRQn, 0, 3); /* 抢占优先级0,子优先级3 */
HAL_NVIC_EnableIRQ(USART_UX_IRQn); /* 使能USART1中断通道 */
#endif
}
}
//串口中断函数
void USART_UX_IRQHandler(void)
{
uint8_t res;
if(__HAL_UART_GET_FLAG(&g_uart1_handle, UART_FLAG_RXNE) != RESET)
{
led_on(); //调试用
delay_ms(1000);
led_off();
HAL_UART_Receive(&g_uart1_handle, &res, 1, 1000);
debug_handler(&res);
}
}
#endif
PWM初始化,电机针脚都是固定的,只能用PIN8:
/* 定时器配置句柄 定义 */
TIM_HandleTypeDef g_atimx_cplm_pwm_handle; /* 定时器x句柄 */
/* 互补输出带死区控制 */
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig; /* 死区时间设置 */
void atim_timx_cplm_pwm_init(uint16_t arr, uint16_t psc) /* 电机接线用的TIM4定时器,移植程序用的TIM1高级定时器,为避免BUG没修改名称 */
{
TIM_OC_InitTypeDef sConfigOC;
g_atimx_cplm_pwm_handle.Instance = TIM4; /* 定时器x */
g_atimx_cplm_pwm_handle.Init.Prescaler = psc; /* 定时器预分频系数 */
g_atimx_cplm_pwm_handle.Init.CounterMode = TIM_COUNTERMODE_UP; /* 向上计数模式 */
g_atimx_cplm_pwm_handle.Init.Period = arr; /* 自动重装载值 */
g_atimx_cplm_pwm_handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; /* 时钟分频因子 */
g_atimx_cplm_pwm_handle.Init.RepetitionCounter = 0; /* 重复计数器寄存器为0 */
g_atimx_cplm_pwm_handle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; /* 不使能影子寄存器TIMx_ARR */
HAL_TIM_PWM_Init(&g_atimx_cplm_pwm_handle);
/* 设置PWM输出 */
sConfigOC.OCMode = TIM_OCMODE_PWM1; /* PWM模式1 */
sConfigOC.Pulse = 0; /* 比较值为0 */
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; /* OCy 高电平有效 */
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; /* 不使用快速模式 */
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; /* 通道的空闲状态 */
HAL_TIM_PWM_ConfigChannel(&g_atimx_cplm_pwm_handle, &sConfigOC, TIM_CHANNEL_3);
HAL_TIM_PWM_ConfigChannel(&g_atimx_cplm_pwm_handle, &sConfigOC, TIM_CHANNEL_4);
/* 设置死区参数,开启死区中断 */
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_ENABLE; /* OSSR设置为1 */
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; /* OSSI设置为0 */
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; /* 上电只能写一次,需要更新死区时间时只能用此值 */
sBreakDeadTimeConfig.DeadTime = 0X0F; /* 死区时间 */
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; /* BKE = 0, 关闭BKIN检测 */
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_LOW; /* BKP = 1, BKIN低电平有效 */
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; /* 使能AOE位,允许刹车后自动恢复输出 */
HAL_TIMEx_ConfigBreakDeadTime(&g_atimx_cplm_pwm_handle, &sBreakDeadTimeConfig); /* 设置BDTR寄存器 */
}
/**
* @brief 定时器底层驱动,时钟使能,引脚配置
此函数会被HAL_TIM_PWM_Init()调用
* @param htim:定时器句柄
* @retval 无
*/
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
if (htim->Instance == ATIM_TIMX_CPLM)
{
GPIO_InitTypeDef gpio_init_struct;
__HAL_RCC_GPIOB_CLK_ENABLE(); /* 通道X对应IO口时钟使能 */
__HAL_RCC_TIM4_CLK_ENABLE(); /* 定时器x时钟使能 */
/* 配置PWM通道引脚 */
gpio_init_struct.Pin = GPIO_PIN_8;
gpio_init_struct.Mode = GPIO_MODE_AF_PP;
gpio_init_struct.Pull = GPIO_NOPULL;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH ;
HAL_GPIO_Init(TIM_TIMX_CPLM_CHY_GPIO_PORT, &gpio_init_struct);
}
}
/**
* @brief 电机初始化
* @param 无
* @retval 无
*/
void dcmotor_init(void)
{
IN_GPIO_CLK_ENABLE();
GPIO_InitTypeDef gpio_init_struct;
/* IN引脚设置,设置为推挽输出 */
gpio_init_struct.Pin = IN1_Pin|IN2_Pin;
gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
gpio_init_struct.Pull = GPIO_NOPULL;
gpio_init_struct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(MOTOR_A_Port, &gpio_init_struct);
HAL_GPIO_WritePin(MOTOR_A_Port, IN1_Pin|IN2_Pin, GPIO_PIN_SET); /* IN拉高,关闭输出 */
dcmotor_stop(); /* 停止电机 */
dcmotor_dir(0); /* 设置正转 */
dcmotor_speed(0); /* 速度设置为0 */
dcmotor_start(); /* 开启电机 */
}