本文参考了众多文章还有江科大的视频实现的,有些底层逻辑我也不是很清楚但是调通了,感兴趣可以自己改一下代码,接线图和江科大定时器PWM控制直流电机一致其图片如下:
1.创建rt-thread工程
打开rt-thread studio,点击右上角的文件->新建->rt_thread项目,选择配置如下:
2.使用外部晶振作为时钟源
点击drivers找到board.h文件打开,往下翻找到时钟源配置,设置为如图所示:
3.配置rt-thread的PWM驱动
此时可以点击上方工具栏的第二个小锤子编译以下,也可不用直接配置下一步
4.使用STM32CubeMX生成配置文件
这一步注意不要再rt-thread studio工程中的CubeMX Settings中配置!
打开STM32CubeMX新建一个工程,找到STM32F103C8T6
接下来配置定时器2,如图所示
5.获取所需代码
打开使用STM32Cube生成的工程,按如图所示复制代码
代码大致如下:
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspPostInit 0 */
/* USER CODE END TIM2_MspPostInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM2 GPIO Configuration
PA2 ------> TIM2_CH3
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM2_MspPostInit 1 */
/* USER CODE END TIM2_MspPostInit 1 */
}
}
接下来回到rt-thread studio中,将得到的代码复制到board.c文件的最下方,并将函数HAL_TIM_Base_MspInit改成HAL_TIM_PWM_MspInit
6.打开和补全所需宏定义
PWM2对应TIM2,CH3对应通道3,因为本实验所使用的定时器是TIM2,所以在pwm_config.h文件中有其PWM2的定义,故我们不需要补全其定义,但如果你想使用TIM1,应该复制其代码并且进行修改后,将PWM2修改为PWM1并且重新添加进去,因为我们没有使用到,故不需定义,具体图如下:
TIM1添加代码如下
最后编译查看是否有报错
7.代码实现
在main.c文件中编写以下代码OLED.h头文件是将江科大提供的代码移植的,只需要将其使用的标准库函数转换成HAL库函数即可),有感兴趣的大佬可以改改代码,或者自己写也可以,本人代码写的比较丑陋:
#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>
#define DBG_TAG "main"
#define DBG_LVL DBG_LOG
#include <rtdbg.h>
#include "OLED.h"
#define LED_Pin GET_PIN(B,10)
#define Key1 GET_PIN(B,1)
#define PWM_DEV_NAME "pwm2"
#define PWM_DEV_CHAN 3
rt_thread_t thread1;
rt_thread_t thread_uart;
rt_thread_t thread2;
rt_thread_t thread3;
rt_mq_t dmq;
rt_mq_t dmq1;
rt_mutex_t sempare;
void thread1_entry(void *arg);
void uartthread_entry(void *arg);
void thread2_entry(void *arg);
void thread3_entry(void *arg);
struct rt_device_pwm *pwm_dev;
int main(void)
{
OLED_Init();
OLED_ShowString(1,1,"SPEED:");
rt_pin_mode(LED_Pin, PIN_MODE_OUTPUT_OD);
rt_pin_mode(Key1, PIN_MODE_INPUT_PULLUP);
rt_pin_mode(GET_PIN(A,4),PIN_MODE_OUTPUT);
rt_pin_mode(GET_PIN(A,5),PIN_MODE_OUTPUT);
sempare = rt_mutex_create("sem1",RT_IPC_FLAG_FIFO);
dmq = rt_mq_create("compare", sizeof(int), 10, RT_IPC_FLAG_FIFO);
dmq1 = rt_mq_create("compare", sizeof(int), 10, RT_IPC_FLAG_FIFO);
thread1 = rt_thread_create("thread1",thread1_entry, RT_NULL, 1024, 10, 10);
thread_uart = rt_thread_create("uart_thread",uartthread_entry, RT_NULL, 1024, 10, 10);
thread2 = rt_thread_create("thread2", thread2_entry,RT_NULL,1024,10,10);
thread3 = rt_thread_create("thread3", thread3_entry,RT_NULL,1024,10,10);
pwm_dev = (struct rt_device_pwm *)rt_device_find(PWM_DEV_NAME);
if(pwm_dev == RT_NULL)
{
rt_kprintf("device error\r\n");
return RT_ERROR;
}
rt_pwm_set(pwm_dev, PWM_DEV_CHAN, 100, 0);
rt_pwm_enable(pwm_dev, PWM_DEV_CHAN);
rt_thread_startup(thread1);
rt_thread_startup(thread_uart);
rt_thread_startup(thread2);
rt_thread_startup(thread3);
return RT_EOK;
}
void thread1_entry(void *arg)
{
int compare = 0;
while(1)
{
if(rt_pin_read(Key1) == PIN_LOW)
{
rt_thread_mdelay(20);
while(rt_pin_read(Key1) == PIN_LOW);
rt_thread_mdelay(20);
compare+=2000;
if(compare>10000)
{
compare = -10000;
}
rt_mq_send(dmq, &compare, sizeof(int));
rt_mq_send(dmq1, &compare, sizeof(int));
}
}
}
void uartthread_entry(void *arg)
{
while (1)
{
rt_kprintf("此内容无效\r\n");
rt_thread_mdelay(1000);
}
}
void thread2_entry(void *arg)
{
int compare = 0;
while(1)
{
rt_mq_recv(dmq, &compare, sizeof(int), RT_WAITING_FOREVER);
if(compare>=0)
{
rt_pin_write(GET_PIN(A,5), PIN_HIGH);
rt_pin_write(GET_PIN(A,4), PIN_LOW);
}
else
{
rt_pin_write(GET_PIN(A,4), PIN_HIGH);
rt_pin_write(GET_PIN(A,5), PIN_LOW);
compare = -compare;
}
rt_mutex_take(sempare, RT_WAITING_FOREVER);
rt_pwm_set(pwm_dev, PWM_DEV_CHAN,10000,compare);
rt_mutex_release(sempare);
}
}
void thread3_entry(void *agr)
{
int compare = 0;
OLED_ShowSignedNum(2, 1, compare, 6);
while(1)
{
rt_mq_recv(dmq1, &compare, sizeof(int), RT_WAITING_FOREVER);
OLED_ShowSignedNum(2, 1, compare, 6);
rt_thread_mdelay(1000);
}
}