TM4C123G学习记录(5)--PWM输出

因为想申请 CSDN 博客认证需要一定的粉丝量,而我写了五年博客才 700 多粉丝,本文开启关注才可阅读全文,很抱歉影响您的阅读体验

  • 为了准备电赛临时学一下TM4C123G,简单记录学习内容
  • 大家可以在这里下载我收集的资源,非常全面,花了很大功夫收集来的,还有书籍、例程代码等
  • 还可以在TI官网下载相关文档TI官网

一、实验简介

GPIO输出pwm信号,控制板载LED实现呼吸灯效果

二、硬件连接

检查板载LED部分原理图
在这里插入图片描述
可见PF1/PF2/PF3对应三个LED,LED由三极管开关电路控制,IO输出高电平点亮,IO输出pwm波可以控制亮度

三、TM4C单片机的PWM介绍

(1)pwm资源

TM4C123GH6PM控制器包含两个pwm模块,每个模块由4个pwm发生器和一个控制模块组成,每个发生器可以产生2个pwm信号,一共可以输出16个pwm信号(同一发生器产生的两个信号的周期是一致的,但占空比可以设为不同的

(2)pwm发生器特点

在这里插入图片描述

(3)结构图

  • pwm模块结构图
    在这里插入图片描述
  • 其中一个发生器的细节
    在这里插入图片描述

(4)pwm信号引脚映射情况

这个表格十分重要,它记录了在硬件层面上,哪些pwm信号输出连接到哪些引脚,编程时需要对照查看
在这里插入图片描述
如图可见,PF2连接到M1PWM6,PF3连接到M1PWM7,我们只需控制M1PWM6/M1PWM7在PF2/PF3上输出pwm波,即可控制引脚上连接的LED

(5)pwm模块时钟来源

在这里插入图片描述
查看原理图,可见pwm模块时钟来源于经过USEPWMDIV分频的系统时钟,所有pwm信号的时钟频率都是这个。

(6)pwm信号产生过程

(1)类似stm32,TM4C的pwm利用定时器实现(不过TM4C的pwm模块中有自带的定时器,不需要想stm32那样使用timer外设),可以选择三种计数模式

  • 向上计数(pwm信号右对齐)
  • 向下计数(pwm信号左对齐)
  • 上下计数(pwm信号中间对齐)

(2)每个pwm信号发生器,可以配置两个pwm比较器(类似stm32中的ccrx),比较器根据设定的比较值和当前计数值输出高电平脉冲
(3)所有计数器、比较器的信息会被pwm信号发生器检测,并生成对应的pwm波

(7)其它

关于pwm中断、死区配置、信号同步、故障等内容,因为本人没有深入研究,在此不提了,不好意思

四、TM4C单片机的PWM配置过程

  • 配置一个PWM发生器,频率25KHz,信号0(MnPWM0)占空比25%,信号1(MnPWM1)占空比75%,假定系统时钟频率为20M
  1. 使能PWM时钟 SysCtlPeripheralEnable()

  2. 使能被复用引脚的时钟 SysCtlPeripheralEnable()

  3. 使能引脚复用PWM功能 GPIOPinTypePWM()

  4. 将PWM信号分配到合适的引脚上 GPIOPinConfigure()

  5. 使能PWM时钟,设置PWM分频器为2分频(PWM时钟源为10M) SysCtlPWMClockSet();

  6. 配置为向下计数,参数立即更新模式 PWMGenConfigure()

  7. 设置周期时间(定时器计数范围),目标频率25K,PWM频率10M,则每一个信号周期有400个PWM周期,故装载值设为400-1(0到399共400个值) PWMGenPeriodSet()

  8. 设置信号0占空比25%,信号1占空比75% PWMPulseWidthSet()

  9. 启动PWM发生器的定时器 PWMGenEnable()

  10. 使能PWM输出 PWMOutputState()

五、示例代码

#include <stdint.h>
#include <stdbool.h>
#include "inc/tm4c123gh6pm.h"				//Register Definitions
#include "inc/hw_memmap.h"
#include "inc/hw_types.h"
#include "driverlib/sysctl.h"
#include "driverlib/interrupt.h"
#include "driverlib/gpio.h"
#include "driverlib/uart.h"
#include "uartstdio.h"
#include "driverlib/systick.h"
#include "driverlib/pin_map.h"
#include "driverlib/pwm.h"


#define delay_ms(n); SysCtlDelay(n*(SysCtlClockGet()/3000));

/******************************************************************************************************************
*函数名: PWMInit()
*描	 述:PWM初始化函数
*输	 入:无
*线  路:PF2<->M1PWM6
				 PF4<->M1PWM7
******************************************************************************************************************/
void PWMInit(void)
{
	//配置PWM时钟(设置USEPWMDIV分频器)
	SysCtlPWMClockSet(SYSCTL_PWMDIV_1);																									//PWM时钟 16M

	//使能时钟
	SysCtlPeripheralEnable(SYSCTL_PERIPH_PWM1);			//使能PWM模块1时钟																		
	SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOF);		//使能GPIOF时钟																		
	
	//使能引脚复用PWM功能
	GPIOPinTypePWM(GPIO_PORTF_BASE,GPIO_PIN_2);
	GPIOPinTypePWM(GPIO_PORTF_BASE,GPIO_PIN_3);
	
	//PWM信号分配
	GPIOPinConfigure(GPIO_PF2_M1PWM6);					//PF2->PWM模块1信号6																							
	GPIOPinConfigure(GPIO_PF3_M1PWM7);					//PF3->PWM模块1信号7																								

	//配置PWM发生器
	//模块1->发生器3->上下计数,不同步
	PWMGenConfigure(PWM1_BASE,PWM_GEN_3,PWM_GEN_MODE_UP_DOWN|PWM_GEN_MODE_NO_SYNC);	
	
	//配置PWM周期
	PWMGenPeriodSet(PWM1_BASE,PWM_GEN_3,64000);			//64*10^3/16/10^6=4ms																			
	
	//配置PWM占空比
	PWMPulseWidthSet(PWM1_BASE,PWM_OUT_6,PWMGenPeriodGet(PWM1_BASE, PWM_GEN_3)*0.01);		//比较值为四分之一总计数值,25%
	PWMPulseWidthSet(PWM1_BASE,PWM_OUT_7,PWMGenPeriodGet(PWM1_BASE, PWM_GEN_3)*0.01);		//比较值为四分之三总计数值,75%

	//使能PWM模块1输出
	PWMOutputState(PWM1_BASE,PWM_OUT_6_BIT,true);
	PWMOutputState(PWM1_BASE,PWM_OUT_7_BIT,true);
	
	//使能PWM发生器
	PWMGenEnable(PWM1_BASE,PWM_GEN_3);
}



/******************************************************************************************************************
*函数名: SetDuty(uint32_t ui32Base,uint32_t ui32PWMOut,float duty)
*描	 述:PWM初始化函数
*输	 入:PWM模块编号、信号编号、占空比
******************************************************************************************************************/
void SetDuty(uint32_t ui32Base,uint32_t ui32PWMOut,float duty)
{
		uint32_t ui32Gen;
		uint32_t ui32OutBits;
	
		switch(ui32PWMOut)
		{
			case PWM_OUT_0:	ui32Gen=PWM_GEN_0,ui32OutBits=PWM_OUT_0_BIT;	break;
			case PWM_OUT_1:	ui32Gen=PWM_GEN_0,ui32OutBits=PWM_OUT_1_BIT;	break;
			case PWM_OUT_2:	ui32Gen=PWM_GEN_1,ui32OutBits=PWM_OUT_2_BIT;	break;
			case PWM_OUT_3:	ui32Gen=PWM_GEN_1,ui32OutBits=PWM_OUT_3_BIT;	break;
			case PWM_OUT_4:	ui32Gen=PWM_GEN_2,ui32OutBits=PWM_OUT_4_BIT;	break;
			case PWM_OUT_5:	ui32Gen=PWM_GEN_2,ui32OutBits=PWM_OUT_5_BIT;	break;
			case PWM_OUT_6:	ui32Gen=PWM_GEN_3,ui32OutBits=PWM_OUT_6_BIT;	break;
			case PWM_OUT_7:	ui32Gen=PWM_GEN_3,ui32OutBits=PWM_OUT_7_BIT;	break;
		}
	
    //配置占空比
    PWMPulseWidthSet(ui32Base, ui32PWMOut, PWMGenPeriodGet(ui32Base, ui32Gen)*duty);
    PWMOutputState(ui32Base, ui32OutBits, true);
    //使能发生器模块
    PWMGenEnable(ui32Base, ui32Gen);
}

int main()
{
	SysCtlClockSet(SYSCTL_SYSDIV_1|SYSCTL_USE_OSC|SYSCTL_XTAL_16MHZ|SYSCTL_OSC_MAIN);		//系统时钟16M
	PWMInit();
	
	float duty1=0.1,duty2=0.9;
	float d=0.01;
	
	while(1)
	{
		SetDuty(PWM1_BASE,PWM_OUT_6,duty1);
		SetDuty(PWM1_BASE,PWM_OUT_7,duty2);
		delay_ms(10);
		duty1+=d;
		duty2-=d;
		
		if(duty1>=0.95 && duty2<=0.05)
			d=-0.01;
		else if(duty2>=0.95 && duty1<=0.05)
			d=0.01;
	}
}


  • 36
    点赞
  • 160
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 20
    评论
下面是一个使用TM4C123的PWM模块控制占空比的示例代码: ```c #include <stdint.h> #include "inc/tm4c123gh6pm.h" #define PWM_PERIOD 40000 // PWM周期为40000个系统时钟周期 #define DUTY_CYCLE 20000 // 初始占空比为50% void PWM_Init(void) { // 配置GPIO PC4为PWM输出 SYSCTL_RCGCGPIO_R |= SYSCTL_RCGCGPIO_R2; // 使能GPIO Port C时钟 GPIO_PORTC_AFSEL_R |= 0x10; // PC4使用替代功能 GPIO_PORTC_PCTL_R = (GPIO_PORTC_PCTL_R & 0xFFF0FFFF) | 0x00070000; // PC4为PWM输出 GPIO_PORTC_DEN_R |= 0x10; // PC4数字输出使能 // 配置PWM模块1 SYSCTL_RCGCPWM_R |= SYSCTL_RCGCPWM_R1; // 使能PWM模块1时钟 SYSCTL_RCC_R |= SYSCTL_RCC_USEPWMDIV; // 使用PWM分频器 SYSCTL_RCC_R &= ~SYSCTL_RCC_PWMDIV_M; // PWM分频器设置为2 SYSCTL_RCC_R |= SYSCTL_RCC_PWMDIV_2; PWM1_2_CTL_R = 0; // 禁止PWM模块1的输出 PWM1_2_GENA_R = 0x0000008C; // PWM模块1的PWM5通道设置为基本模式 PWM1_2_LOAD_R = PWM_PERIOD - 1; // PWM周期设置为40000个系统时钟周期 PWM1_2_CMPA_R = DUTY_CYCLE - 1; // 初始占空比设置为50% PWM1_2_CTL_R |= PWM_0_CTL_ENABLE; // 使能PWM模块1的输出 PWM1_ENABLE_R |= PWM_ENABLE_PWM5EN; // 使能PWM模块1的PWM5输出 } void PWM_SetDutyCycle(uint16_t dutyCycle) { // 设置PWM占空比 PWM1_2_CMPA_R = dutyCycle - 1; } int main(void) { PWM_Init(); while (1) { // 通过改变占空比控制LED亮度 PWM_SetDutyCycle(10000); // 占空比为25% SysCtlDelay(1000000); // 延迟1秒 PWM_SetDutyCycle(20000); // 占空比为50% SysCtlDelay(1000000); // 延迟1秒 PWM_SetDutyCycle(30000); // 占空比为75% SysCtlDelay(1000000); // 延迟1秒 PWM_SetDutyCycle(40000); // 占空比为100% SysCtlDelay(1000000); // 延迟1秒 } } ``` 在上面的代码中,我们使用PWM模块1的PWM5通道来控制GPIO PC4的输出。在初始化函数PWM_Init中,我们首先将PC4设置为PWM输出,并配置PWM模块1的基本参数,如PWM周期、占空比等。在主函数中,我们通过改变占空比来控制LED亮度,PWM_SetDutyCycle函数用于设置占空比。在每次改变占空比后,我们延迟1秒钟。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

云端FFF

所有博文免费阅读,求打赏鼓励~

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

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

打赏作者

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

抵扣说明:

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

余额充值