Flax_R 2022-12-14 11:26 采纳率: 100%
浏览 81
已结题

STM32F103C8T6的串口无法接受信息,PWM也不能控制转动

调了几天了,一直搞不定,最近刚学嵌入式,求帮助

刚入手了一套基于STM32F103C8T6的直流电机套件,想往里移植PID位置算法,但不知道哪出了问题,串口能发送信息但无法接受上位机信息,没有进入接收中断,而且电机也无法控制转动,怀疑可能初始化或移植程序不兼容出问题了,因为我只干了这两件事。。

电机接线图,只用到了A电机

img

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();                /* 开启电机 */
}
移植的程序是基于STM32F4xx的,原程序用的是PWM互补通道,串口也是USART1,一直对照原程序没找到哪有问题导致没进入中断
  • 写回答

2条回答 默认 最新

  • Vuko-wxh FPGA领域优质创作者 2022-12-15 14:22
    关注

    如果移植没问题,测试串口可以正常,就排查下硬件连接有无问题,如果因为串口的问题不能进中断,检查下是否两边模块共地,串口通信的电平标准两边是否一致

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 1月15日
  • 已采纳回答 1月7日
  • 创建了问题 12月14日

悬赏问题

  • ¥15 metadata提取的PDF元数据,如何转换为一个Excel
  • ¥15 关于arduino编程toCharArray()函数的使用
  • ¥100 vc++混合CEF采用CLR方式编译报错
  • ¥15 coze 的插件输入飞书多维表格 app_token 后一直显示错误,如何解决?
  • ¥15 vite+vue3+plyr播放本地public文件夹下视频无法加载
  • ¥15 c#逐行读取txt文本,但是每一行里面数据之间空格数量不同
  • ¥50 如何openEuler 22.03上安装配置drbd
  • ¥20 ING91680C BLE5.3 芯片怎么实现串口收发数据
  • ¥15 无线连接树莓派,无法执行update,如何解决?(相关搜索:软件下载)
  • ¥15 Windows11, backspace, enter, space键失灵