STM32L4 HAL库通过串口通信改变PWM占空比

这篇具有很好参考价值的文章主要介绍了STM32L4 HAL库通过串口通信改变PWM占空比。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

STM32 L4 通过串口通信改变PWM占空比 HAL库

使用串行通信的目的是为了让上位机能控制STM32来改变PWM的输出

一、PWM初始化

#include "pwm.h"

TIM_HandleTypeDef TIM4_Handler;         //定时器4PWM句柄
TIM_OC_InitTypeDef TIM4_CHnHandler;	    //定时器4句柄

void TIM4_PWM_Init(u16 arr, u16 psc)
{
    TIM4_Handler.Instance = TIM4;          				//定时器4
    TIM4_Handler.Init.Prescaler = psc;     				//定时器分频
    TIM4_Handler.Init.CounterMode = TIM_COUNTERMODE_UP; //向上计数模式
    TIM4_Handler.Init.Period = arr;        				//自动重装载值
    TIM4_Handler.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&TIM4_Handler);       				//初始化PWM

    TIM4_CHnHandler.OCMode = TIM_OCMODE_PWM1; 			//模式选择PWM1
    TIM4_CHnHandler.Pulse = arr / 2;       				//设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为50%
    TIM4_CHnHandler.OCPolarity = TIM_OCPOLARITY_HIGH; 	//输出比较极性为低

    HAL_TIM_PWM_ConfigChannel(&TIM4_Handler, &TIM4_CHnHandler, TIM_CHANNEL_3); //配置TIM4通道3
    HAL_TIM_PWM_Start(&TIM4_Handler, TIM_CHANNEL_3); 	//开启PWM通道3

}

void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
	__HAL_RCC_TIM4_CLK_ENABLE();				//使能定时器4
    __HAL_RCC_GPIOB_CLK_ENABLE();				//开启GPIOB时钟

    GPIO_Initure.Pin = GPIO_PIN_8; //PB8
    GPIO_Initure.Mode = GPIO_MODE_AF_PP;  		//复用推挽输出
    GPIO_Initure.Pull = GPIO_PULLUP;        	//上拉
    GPIO_Initure.Speed = GPIO_SPEED_HIGH;   	//高速
    GPIO_Initure.Alternate = GPIO_AF2_TIM4;		//PB8复用为TIM2_CH1.CH2
    HAL_GPIO_Init(GPIOB, &GPIO_Initure);
}

void TIM_SetTIM4Compare3(u32 compare)
{
    TIM4->CCR3 = compare;
}

这里用的是定时器TIM4的3通道,当然也可以改为其他的定时器,具体请参考手册

串口控制pwm占空比,stm32,单片机

二、串口UART初始化

偷下懒,直接拿正点原子的例子程序修改了一下。
示例用的是UART1
引脚是PA9(TX),PA10(RX)

#include "usart.h"
#include "delay.h"
#include <stdio.h> 
#include <string.h>

extern int mypwm;
extern u16 pwmval;
extern u8 chun[10];
extern int len;

#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
    int handle;
};

FILE __stdout;
/**
 * @brief	定义_sys_exit()以避免使用半主机模式
 *
 * @param	void
 *
 * @return  void
 */
void _sys_exit(int x)
{
    x = x;
}
/**
 * @brief	重定义fputc函数
 *
 * @param	ch		输出字符量
 * @param	f		文件指针
 *
 * @return  void
 */
int fputc(int ch, FILE *f)
{
    while((USART1->ISR & 0X40) == 0); //循环发送,直到发送完毕

    USART1->TDR = (u8) ch;
    return ch;
}
#endif


#if EN_USART1_RX   //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN];     //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15,	接收完成标志
//bit14,	接收到0x0d
//bit13~0,	接收到的有效字节数目
u16 USART_RX_STA = 0;     //接收状态标记

UART_HandleTypeDef UART1_Handler; //UART句柄


/**
 * @brief	初始化串口1函数
 *
 * @param	bound	串口波特率
 *
 * @return  void
 */
void uart_init(u32 bound)
{
    //UART 初始化设置
    UART1_Handler.Instance = USART1;					  //USART1
    UART1_Handler.Init.BaudRate = bound;				  //波特率
    UART1_Handler.Init.WordLength = UART_WORDLENGTH_8B; //字长为8位数据格式
    UART1_Handler.Init.StopBits = UART_STOPBITS_1;	  //一个停止位
    UART1_Handler.Init.Parity = UART_PARITY_NONE;		  //无奇偶校验位
    UART1_Handler.Init.HwFlowCtl = UART_HWCONTROL_NONE; //无硬件流控
    UART1_Handler.Init.Mode = UART_MODE_TX_RX;		  //收发模式
    HAL_UART_Init(&UART1_Handler);					    //HAL_UART_Init()会使能UART1

    __HAL_UART_ENABLE_IT(&UART1_Handler, UART_IT_RXNE); //开启接收中断
    HAL_NVIC_EnableIRQ(USART1_IRQn);					//使能USART1中断通道
    HAL_NVIC_SetPriority(USART1_IRQn, 3, 3);				//抢占优先级3,子优先级3
		printf("\r\n串口已准备--\r\n");
}


/**
 * @brief	HAL库串口底层初始化,时钟使能,引脚配置,中断配置
 *
 * @param	huart	串口句柄
 *
 * @return  void
 */
void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
    //GPIO端口设置
    GPIO_InitTypeDef GPIO_Initure;

    if(huart->Instance == USART1) //如果是串口1,进行串口1 MSP初始化
    {
        __HAL_RCC_GPIOA_CLK_ENABLE();				//使能GPIOA时钟
        __HAL_RCC_USART1_CLK_ENABLE();				//使能USART1时钟

        GPIO_Initure.Pin = GPIO_PIN_9;				//PA9
        GPIO_Initure.Mode = GPIO_MODE_AF_PP;		//复用推挽输出
        GPIO_Initure.Pull = GPIO_PULLUP;			//上拉
        GPIO_Initure.Speed = GPIO_SPEED_FAST;		//高速
        GPIO_Initure.Alternate = GPIO_AF7_USART1;	//复用为USART1
        HAL_GPIO_Init(GPIOA, &GPIO_Initure);	   	//初始化PA9

        GPIO_Initure.Pin = GPIO_PIN_10;				//PA10
        HAL_GPIO_Init(GPIOA, &GPIO_Initure);	   	//初始化PA10
    }

}

/**
 * @brief	串口1中断服务程序
 *
 * @remark	下面代码我们直接把中断控制逻辑写在中断服务函数内部
 * 			说明:采用HAL库处理逻辑,效率不高。
 *
 * @param   void
 *
 * @return  void
 */
void USART1_IRQHandler(void)
{
    u8 Res;
		int i;
    if((__HAL_UART_GET_FLAG(&UART1_Handler, UART_FLAG_RXNE) != RESET)) //接收中断(接收到的数据必须是0x0d 0x0a结尾)
    {
        HAL_UART_Receive(&UART1_Handler, &Res, 1, 1000);

        if((USART_RX_STA & 0x8000) == 0) //接收未完成
        {
            if(USART_RX_STA & 0x4000) //接收到了0x0d
            {
                if(Res != 0x0a)USART_RX_STA = 0; //接收错误,重新开始

                else USART_RX_STA |= 0x8000;	//接收完成了
            }
            else //还没收到0X0D
            {
                if(Res == 0x0d)USART_RX_STA |= 0x4000;
                else
                {
                    USART_RX_BUF[USART_RX_STA] = Res;
                    USART_RX_STA++;

                    if(USART_RX_STA > (USART_REC_LEN - 1))USART_RX_STA = 0; //接收数据错误,重新开始接收
                }
            }
        }
    }
		HAL_UART_Transmit(&UART1_Handler, &Res, 1, 1000);//发送数据函数,通过USART1通道发送res数据出去
		if(USART_RX_STA&0x8000)                    
		{					   
			len=USART_RX_STA&0x3fff;//计算出接受数据的总长度
			
			for(i=0;i<len;i++)
			{
				chun[i] = (USART_RX_BUF[i]-0x30);	
				USART_RX_BUF[i]=0;	
				//HAL_UART_Transmit(&UART1_Handler, &chun[i], 1, 1000);//发送数据函数,通过USART1通道发送res数据出去
			}
			
			USART_RX_STA = 0; 
		}
    HAL_UART_IRQHandler(&UART1_Handler);
}

#endif

主要修改的地方在接收数据的部分,我用len=USART_RX_STA&0x3fff
计算出串口接收到数据的长度,然后把接收缓存USART_RX_BUF中的每一位逐个放到chun[ ]数组中。
由于pc端每次发送的是字符类型的数据,例如‘1’对应的ASCII码是0x31,0对应的是0x30。那么对于输入的数字每个都要减去0x30就会得到 01,02,03.。。。
串口控制pwm占空比,stm32,单片机

三、赋值

初始化都处理完了之后就准备在主函数进行赋值了

#include "sys.h"
#include "usart.h"
#include "delay.h"
#include "pwm.h"

#define ARR1 1000
#define PSC1 80

int mypwm=0;
u16 pwmval = 0;			
u8 chun[10];
int len=0;

int main(void)
{
    HAL_Init();
    SystemClock_Config();		//初始化系统时钟为80M
    delay_init(80); 			//初始化延时函数    80M系统时钟
    uart_init(115200);			//初始化串口,波特率为115200

	TIM4_PWM_Init(ARR1 - 1, PSC1 - 1);//TIM2时钟频率 80M/80=1M   计数频率1M/1000=1KHZ     默认占空比为50%
	pwmval=0;
		
    while(1)
    {
			if(len==2)
			{
				mypwm =((int)chun[0]*10 + (int)chun[1]);
			}
			else if(len==3)
			{
				mypwm =((int)chun[0]*10*10 + (int)chun[1]*10 + (int)chun[2]);
				if(mypwm>100)
				{
					printf("\r\n占空比不能超过100%\r\n");
					mypwm = 0;
					len=0;
				}
			}
			else if(len==1)
			{
				mypwm =((int)chun[0]);
			}
			else if(len>3)
			{
				printf("\r\n请输入长度 < 3的字符\r\n");
				printf("\r\n占空比最大为100,不用输入百分号\r\n");
				len=0;
			}			
			pwmval = ARR1*(mypwm*1.0/100);//计算占空比并赋值
			if(pwmval>ARR1)pwmval=ARR1;//限幅
			TIM_SetTIM4Compare3(pwmval);//输出PWM
    }
}

四、最后附上效果图

占空比为30%串口控制pwm占空比,stm32,单片机
串口控制pwm占空比,stm32,单片机文章来源地址https://www.toymoban.com/news/detail-609873.html

到了这里,关于STM32L4 HAL库通过串口通信改变PWM占空比的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 普中STM32-PZ6806L开发板(HAL库函数实现-TIM5 设置 PWM input, 获取频率跟占空比)

    连线 APIs 创建项目 参考 普中STM32-PZ6806L开发板(HAL库函数实现-PWM呼吸灯), 使用同一个GPIO口PC7产生PWM,然后PA0引脚进行捕获 初始化TIM5 CH1 合并通道, 选项为PWM输入到CH1, 这里其实就是合并1和2通道使一个采集上升沿一个采集下降沿 主从模式开启, 先启动会等待另外一个同步启动

    2024年02月19日
    浏览(32)
  • HAL库 STM32 串口通信

    将STM32的PA9复用为串口1的TX,PA10复用为串口1的RX。STM32芯片的输出TX和接收RX与CH340的接收RX和发送TX相连(收发交叉且PCB上默认没有相连,所以需要用P3跳线帽进行手动连接),CH340的另一端通过USB口引出与USB线相接。CH340作用:RS232电平标准转USB电平标准)。再使用USB转串口线

    2024年02月13日
    浏览(28)
  • STM32 HAL SWD下载与串口通信

    SWD是ST公司推出的开源的四线下载方式,分别为3V3、SWD、SWCLK、GND,相比JTAG等可以用较少的线来实现下载和仿真。 首先你需要购买一个DAPLINK,tb购买15块钱左右。只需要接到STM32F103C8T6最小系统板上面的同样的这四个排针即完成接线。 而对于类似正点原子的精英板等,则需要在

    2024年02月03日
    浏览(37)
  • STM32—HAL库中断/DMA控制和完成串口通信

    目录 一、解决的问题 二、串口通讯协议和RS-232的介绍以及USB/TTL转232模块的工作原理   1、 串口协议和RS-232标准:  (1)串口协议: (2)RS-232 标准:   2、RS232电平与TTL电平的区别   3、USB/TTL转232“模块(CH340芯片为例)  (1)基本原理:  (2)CH340模块介绍: ​三、搭

    2024年02月02日
    浏览(61)
  • openmv和STM32串口通信识别条形码、二维码(HAL库)

    因为自己的毕设用到了条形码识别,所以在这里写一篇关于使用openmv识别条形码和二维码并且与STM32实现串口通讯,希望能帮到以后用到这一模块的同学,STM32方面我使用的是STM32F103RCT6,并且使用HAL进行编写代码。 OpenMV端:由图知UART_RX—P5 ------ UART_TX—P4 2.STM32端:这里我使用

    2023年04月13日
    浏览(41)
  • HAL库 STM32运用DMA与IDLE中断实现高效串口通信 (附代码)

    最近想做一个控制电机的项目,其中会用到Pytho与单片机STM32之间的互同,最近也在看一些关于数据通信和拆包的相关知识,所以记录一下这段时间里对两者之间的互通所做的事情和发现的问题,以供自己和大家参考。 单片机的串口是我们常用的与电脑通信的外设,本次与P

    2024年01月22日
    浏览(46)
  • 【STM32】HAL库UART含校验位的串口通信配置BUG避坑

    【STM32】HAL库UART含校验位的串口通信配置BUG避坑 UART通过一条线就能完成数据的发送 另外一条线则完成数据的接收 所以一共是两条线 TX RX UART在空闲时为低电平 时钟周期由波特率确定 通常是115200bit/s UART协议由四个部分组成: 起始位: 固定低电平 1个时钟周期 数据域: 通常

    2024年01月20日
    浏览(43)
  • 【STM32基础】第四篇、控制PWM占空比

    目录 第一部分、STM32定时器的基本知识 1、STM32定时器的分类(图片来自野火文档) 2、开发过程中定时器的常用基础功能 3、定时器挂在的总线  第二部分、能用的代码   1、定时器计时代码 2、定时器输出PWM代码 第三部分、总结 1、STM32定时器的分类(图片来自野火文档)  

    2024年02月07日
    浏览(37)
  • STM32机器人控制开发教程No.4 使用串口通信控制电机(基于HAL库)

    在机器人控制中,单片机(Arduino/STM32)与上位机(Raspberry Pi/NVIDIA Jetson nano)之间的通信经常采用串口通信的方式,那应该如何使用STM32的串口通信以及根据自己定义的协议来完成数据的接收与发送呢?在本篇文章中将给你演示如何通过自定协议来完成对电机的控制以及获取编码

    2023年04月25日
    浏览(49)
  • STM32通过DMA方式实现串口通信

    目录 一、DMA工作原理  二、创建工程项目 三、编写代码 1.在main.c写入以下函数 2.main函数中的while循环中写入以下代码

    2024年02月15日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包