基于STM32的rttread开发实例(1):电机驱动

 不上操作系统的玩差不多了就更新一下基于操作系统的,当然一些非常底层的东西确实还是没有接触到。最近投简历快给人整麻了。好了,废话不说,介绍一下今天的工程实例

本工程详细使用与使用中遇到的bug总结:
前情提要:本工程基于STM32F407VE,本工程使用cubemx与rt_thread studio 混合编程。过程遇到过一些bug,目前处理手法如下:如若不能正常使用请及时反馈。

首先,遇到的问题主要来源于自动生成的bsp文件与未出现报错的stm32f103的bsp文件不同,出现了一系列的错误,包括但不限于:

'PWMN_CMD_ENABLE' undeclared (first use in this function)

error: 'struct rt_pwm_configuration' has no member named 'complementary'

等,通过与stm32f103系列工程(未出现如上错误)BSP文件对比,对生成工程中的drv_pwm.c文件,drv_usart.c文件,board.c文件,bord.h文件进行修改

使drv_pwm.c文件部分内容如下图所示

修改后代码如下

static rt_err_t drv_pwm_control(struct rt_device_pwm *device, int cmd, void *arg)
{
    struct rt_pwm_configuration *configuration = (struct rt_pwm_configuration *)arg;
    TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)device->parent.user_data;

    switch (cmd)
    {
    case PWM_CMD_ENABLE:
        return drv_pwm_enable(htim, configuration, RT_TRUE);
    case PWM_CMD_DISABLE:
        return drv_pwm_enable(htim, configuration, RT_FALSE);
    case PWM_CMD_SET:
        return drv_pwm_set(htim, configuration);
    case PWM_CMD_GET:
        return drv_pwm_get(htim, configuration);
    default:
        return RT_EINVAL;
  }
}

还有这里:

 

 修改后代码如下:

static rt_err_t drv_pwm_enable(TIM_HandleTypeDef *htim, struct rt_pwm_configuration *configuration, rt_bool_t enable)
{
    /* Converts the channel number to the channel number of Hal library */
    rt_uint32_t channel = 0x04 * (configuration->channel - 1);


        if (!enable)
        {
            HAL_TIM_PWM_Stop(htim, channel);
        }
        else
        {
            HAL_TIM_PWM_Start(htim, channel);
        }

    return RT_EOK;
}

修改后代码如下(注意,此时文件是drv_usart.c

static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
    struct stm32_uart *uart;
    RT_ASSERT(serial != RT_NULL);
    RT_ASSERT(cfg != RT_NULL);

    uart = rt_container_of(serial, struct stm32_uart, serial);

    /* uart clock enable */
    stm32_uart_clk_enable(uart->config);
    /* uart gpio clock enable and gpio pin init */
    stm32_gpio_configure(uart->config);

    uart->handle.Instance          = uart->config->Instance;
    uart->handle.Init.BaudRate     = cfg->baud_rate;
    uart->handle.Init.Mode         = UART_MODE_TX_RX;
    uart->handle.Init.OverSampling = UART_OVERSAMPLING_16;


    switch (cfg->data_bits)
    {
    case DATA_BITS_8:
        if (cfg->parity == PARITY_ODD || cfg->parity == PARITY_EVEN)
            uart->handle.Init.WordLength = UART_WORDLENGTH_9B;
        else
            uart->handle.Init.WordLength = UART_WORDLENGTH_8B;
        break;
    case DATA_BITS_9:
        uart->handle.Init.WordLength = UART_WORDLENGTH_9B;
        break;
    default:
        uart->handle.Init.WordLength = UART_WORDLENGTH_8B;
        break;
    }

    switch (cfg->stop_bits)
    {
    case STOP_BITS_1:
        uart->handle.Init.StopBits   = UART_STOPBITS_1;
        break;
    case STOP_BITS_2:
        uart->handle.Init.StopBits   = UART_STOPBITS_2;
        break;
    default:
        uart->handle.Init.StopBits   = UART_STOPBITS_1;
        break;
    }

    switch (cfg->parity)
    {
    case PARITY_NONE:
        uart->handle.Init.Parity     = UART_PARITY_NONE;
        break;
    case PARITY_ODD:
        uart->handle.Init.Parity     = UART_PARITY_ODD;
        break;
    case PARITY_EVEN:
        uart->handle.Init.Parity     = UART_PARITY_EVEN;
        break;
    default:
        uart->handle.Init.Parity     = UART_PARITY_NONE;
        break;
    }

#ifdef RT_SERIAL_USING_DMA
    uart->dma_rx.last_index = 0;
#endif

    if (HAL_UART_Init(&uart->handle) != HAL_OK)
    {
        return -RT_ERROR;
    }

    return RT_EOK;
}

 

接着我们修改board.h文件

本工程中我们使用了TIM.PWM,所以我们只需要这样

当然这是基于实在是不知道哪导致的错误(明明都是系统自动生成的但是就是报错),没办法之下的办法,就是将STM32F4生成的代码与STM32F1生成的代码横向比较删去其中导致莫名错误的地方(不排除怀疑是软件bug的可能,搜了一下有的人也是采用注释掉或者删掉的方式进行)。如果在第一次编译之后没有错误发生就可以不修改文件。

下面是工程源码的链接,我的注释我觉得可以说非常之详细了。仅在此总结一些常用的函数以及书写规范以及我在CV工程的时候遇到的问题的总结。

工程源码icon-default.png?t=N5K3https://gitee.com/cointreau97/cointreau

MSH_CMD_EXPORT(choice,choice mode);

首先就是MSH这个函数,函数作用很简单,创建一个命令可以在msh命令行中使用。第一个函数是需要添加的命令(函数名),desc 是命令的描述。,第二个参数是说明。

然后我们看这么一段代码:

void choice(int argc,char *argv[])
{
    if(argc<2){
        LOG_W("请按照一下格式输入:choice () 括号内容任意");
        return;

    }
    choice_mode(atoi(argv[1]));
}

argc其实是参数长度,例如我输入:

choice 1

此时参数长度是2,是为了约束msh命令格式的。而agrv[]则是参数的存储空间,比如刚刚我输入的是 choice 1 那么此处的argv[1]就是这里输入的1。就完成了传参,具体的底层流程有些一知半解,如果有大佬知道可与我私聊交流。

    MOTOR=rt_thread_create("motor",
            motor_thread_entry,
            RT_NULL,
            THREAD_STACK_SIZE ,
            THREAD_PRIORITY,
            THREAD_TIMESLICE);
    if(MOTOR == RT_EOK)
        rt_thread_startup(MOTOR);
    else{
        LOG_D("Can not create motor thread");
        return -1;
    }
 

再然后就是生成一个动态线程这个流程了,仅作记录,关于动态线程与静态线程这个改天再唠。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cointreau97

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值