分享一个由串口uart接收命令,来动态调整tim定时器pwm模式脉冲宽度的小实验

用到了串口和定时器相关功能
串口中断模式接收一组数据,对数据进行简单判断后,处理数据动态修改pwm的占空比
命令:1,开pwm,2关pwm,3pwm脉宽调整
目测:只需最多三个字节即可完成这些命令的操作
所以,采用

HAL_UART_Receive_IT(&huart1, (uint8_t*)aRxBuffer, 3);

这种简单形式,没有复杂的校验
定义命令字节:0x11为pwm开关命令,0x01为开,0x02为关
定义:0x22为pwm调整命令,其后紧跟16位高8字节+16位低8字节
于是大致命令形式如下:
开pwm: 11 01 00
关pwm: 11 02 00
pwm调整: 22 07 D0
至于开和关后面的0x00作用是为了凑够命令长度的3个字节长度,
省了事但是不好看,不建议这样用,
可以将类似modbus协议这样的应用到这个实验,目前就不这样操作了,
关于modbus在stm32cubemx中的使用,已经在其他帖子里写过.
=========================================
时钟配置:

2.png


1.串口配置:
选择串口1,我用的是PB6和PB7配置为AF+PP+FAST,115200,8,0,1
开串口中断
2.PWM配置
选择定时器3的通道1做pwm输出
于是配置PA6为AF+PP+HIGH
具体如下图:

1.png


3.png

额,对了,上面图片中的8399更改为83,这样的话分频后是1M即1us
下面的19999就是20000*1us=20ms,嗯,就这样
无需定时器中断
生成代码!


补充一下:
本次实验主要是控制一个舵机参数如下:
舵机控制PWM信号组成(以常规航模用遥控器为例):周期20ms,控制脉宽1000us--2000us
360°旋转舵机:实际相当于无极变速的减速电机,可以控制速度和方向。没有角度限制,控制方式和一般舵机的控制信号相同。是小车,旋转平台等改装的最合适动力源。
当脉宽控制范围在1000us--1500us时,舵机正转(1000us时正转速度最快,越接近1500us越慢,1500us时舵机停转。
当脉宽控制范围在1500us--2000us时,舵机反转,(1500us时舵机停转,越接近2000us反转的速度越快,2000us时以最快的速度反转)

好了,不多说,看懂上面的用途就能理解我下面的实验为什么这么写了....
4444.jpg


Hal库中有类似的修改的函数
设置脉冲周期 即图中的T
__HAL_TIM_SetAutoreload(&hTimPwm2, period);
设置占空比50% 即图中的t,这里t时间占大T时间的一半
__HAL_TIM_SetCompare(&hTimPwm2, CHAN_TIMER_PWM2, period >> 1);

结合我这次试验的数据的话,有如下理解
周期T=20ms 即频率为50hz
占空比可变


>本站程序均有完整压缩包供下载参考!前往本站区下载!
本程序共享名:stm32f407_pwm_uart.zip

已邀请:

admin

赞同来自:

我的习惯是独立调试各个功能ok,才综合起来,
首先,先确认串口配置正确,能够和PC端的调试助手通信成功,于是
写入如下代码:


#include "stdio.h"
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}

在main中调用 printf("the uart is ok!");
串口助手显示正常则配置正确!
其次调试pwm是否有波形输出,是否按照要求输出,是否可调?于是


在main中定义


uint16_t pwm_value = 1000;

同时在main.c文件中定义一个函数,用来改变pwm的占空比用


void user_pwm_setvalue(uint16_t value)
{
TIM_OC_InitTypeDef sConfigOC;

sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = value;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
}


同时在初始化完毕之后写入代码:


user_pwm_setvalue(pwm_value);

在while中改变占空比示波器观察波形输出:


while (1)
{
/[i] USER CODE END WHILE [/i]/
HAL_Delay(300);
pwm_value += 100;
if(pwm_value > 10000) pwm_value = 1000;
else
{
user_pwm_setvalue(pwm_value);
}
}

编译之后,观察示波器波形,可以看到占空比波形有小到大变化,然后再次重新从小到大波形
证明,pwm配置正确

admin

赞同来自: 空调加棉被

ok,一切单功能ok后,综合起来.
先定义一个标志和一个接受数组


uint8_t aRxBuffer={0};
uint8_t RX_flag = 0;


main中开启串口接收中断

HAL_UART_Receive_IT(&huart1, (uint8_t*)aRxBuffer, 3);

在main.c文件中增加串口的callback函数


void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
/* NOTE: This function Should not be modified, when the callback is needed,
the HAL_UART_TxCpltCallback could be implemented in the user file
*/
RX_flag = 1; //串口接收标志
HAL_UART_Receive_IT(&huart1, (uint8_t*)aRxBuffer, 3);

}

初始化pwm数值
uint16_t pwm_value = 1000;
while循环中增加:


while (1)
{
/[i] USER CODE END WHILE [/i]/
if(RX_flag == 1)//接收到数据
{
RX_flag = 0; //清标志
if(aRxBuffer == 0x11) //开关命令0x11
{
if(aRxBuffer == 0x01) //打开PWM
{
HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
printf("pwm is on!");
}
else if(aRxBuffer == 0x02) //关闭PWM
{
HAL_TIM_PWM_Stop(&htim3, TIM_CHANNEL_1);
printf("pwm is off!");
}
}
if(aRxBuffer == 0x22) //调整PWM命令
{
pwm_value = (aRxBuffer<<8) + aRxBuffer;
user_pwm_setvalue(pwm_value);
printf("set is success!");
}
}
/[i] USER CODE BEGIN 3 [/i]/

}


以上就是完整的实验代码,实验结果如描述现象.

4.png

XMETOO

赞同来自:

不错,一步一步 很有趣。

moshuipingzi - 一句话介绍

赞同来自:

实例小但是有意思,学习了

lolo

赞同来自:

顶,学习了

容成及澈

赞同来自: lolo

不错不错。。。问楼主一个问题,可以同时开两个串口吗?如果同时开两个串口的话,那个回传函数怎么判断是那个串口进来的啊。。。

new01boy

赞同来自:

实例小但是有意思,一步一步学习了

BG4RFF

赞同来自:

感觉楼主的程序存在一个冒险,就是接收回调函数里面只是做了个标志位和重新开始接收,我感觉要做一个数据缓冲好一些

lingyun20003

赞同来自:

老大,我按你现在的设置和改变,那个占空比怎么都不改变,怎么会是了?

用的是STM32F103C8Tx

代码如下:
初始化的程序是STM32CubeMX生成的:
void MX_TIM2_Init(void)
{

TIM_ClockConfigTypeDef sClockSourceConfig;
TIM_MasterConfigTypeDef sMasterConfig;
TIM_OC_InitTypeDef sConfigOC;

htim2.Instance = TIM2;
htim2.Init.Prescaler = 9;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 7199;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim2);

sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig);

HAL_TIM_PWM_Init(&htim2);

sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig);

sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);

HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2);
}
自己写的代码:
void Light_Config(uint32_t Channel,uint16_t Dutyfactor)
{
TIM_OC_InitTypeDef sConfigOC;

sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = Dutyfactor;//*5;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;

HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, Channel);
HAL_TIM_PWM_Start(&htim2, Channel);
}

在while(1)以前,开启
Light_Config(TIM_CHANNEL_1,Dutyfactor1);
Light_Config(TIM_CHANNEL_2,Dutyfactor2);

然后再串口处理函数里面,将收到的比较值通过Light_Config(TIM_CHANNEL_1,Dutyfactor1);重新配置,但出来的波形只是保持初始化的样子,后面怎么改变Dutyfactor1的值,占空比都没有变化。

着急啊,希望能得到解决。

lingyun20003

赞同来自:

在Light_Config(TIM_CHANNEL_2,Dutyfactor2);后再加一个函数HAL_TIM_PWM_Start(&htim2,TIM_CHANNEL_2);就可以更改占空比了,还不知道具体原因,等会查一下代码。没有加的话,PWM波形将没有输出。奇怪。。。。。

evanhe

赞同来自:

楼主修改pwm占空比时是自己定义的一个函数。以前的库函数中有一个函数(TIM_SetComparex())可以直接修改,不知道HAL库中有类似的函数吗?
QQ截图20150917150145.png

admin

赞同来自: 彩虹之南

补充一下:
本次实验主要是控制一个舵机参数如下:
舵机控制PWM信号组成(以常规航模用遥控器为例):周期20ms,控制脉宽1000us--2000us
360°旋转舵机:实际相当于无极变速的减速电机,可以控制速度和方向。没有角度限制,控制方式和一般舵机的控制信号相同。是小车,旋转平台等改装的最合适动力源。
当脉宽控制范围在1000us--1500us时,舵机正转(1000us时正转速度最快,越接近1500us越慢,1500us时舵机停转。
当脉宽控制范围在1500us--2000us时,舵机反转,(1500us时舵机停转,越接近2000us反转的速度越快,2000us时以最快的速度反转)

好了,不多说,看懂上面的用途就能理解我下面的实验为什么这么写了....

彩虹之南

赞同来自:

学习了

tb8505537 - 一句话介绍

赞同来自:

感谢

咫尺天涯

赞同来自:

这个为什么没有看到清理中断标志位

zjhjhx

赞同来自:

没有了 - -找不到程序了。。擦。

正南其北哩

赞同来自:

硬缺失挺呢,学习了

不穿辣条吃秋裤i

赞同来自:

讲的很清楚呢,很棒

想飞的四轴

赞同来自:

谢谢楼主分享,学习啦

要回复问题请先登录注册