第8-9周作业--定时器&PWM应用编程

目录

前言

一、实验任务

二、定时器和PWM

1、定时器介绍

​编辑2、定时器的工作原理

3、PWM介绍

三、用定时器控制小灯周期性闪烁

1、环境搭建

2、代码编写

3、电路连接

4、烧录和运行

四、 用PWM模式运行呼吸灯

1、代码修改

2、电路连接与烧录运行

五、观察波形

总结


前言

        本文记录嵌入式开发课程第九周实验作业,学习有关定时器&PWM相关的知识以及运用。


一、实验任务

1、使用STM32F103的Tim2~Tim5其一定时器的某一个通道pin(与GPIOx管脚复用,见下图),连接一个LED,用定时器计数方式,控制LED以2s的频率周期性地亮-灭。

2、接上,采用定时器pwm模式,让 LED 以呼吸灯方式渐亮渐灭,周期为1~2秒,自己调整到一个满意效果。使用Keil虚拟示波器,观察 pwm输出波形。

3、再接上,采用定时器的另外一个通道,编程采集上面的pwm输出信号,获得其周期和脉宽,并重定向输出到串口显示。

二、定时器和PWM

1、定时器介绍

        定时器是用来定时的机器,是存在于STM32单片机中的一个外设。STM32总共有8个定时器,分别是2个高级定时器(TIM1、TIM8),4个通用定时器(TIM2、TIM3、TIM4、TIM5)和2个基本定时器(TIM5、TIM6),如下图所示:

        这三种定时器的区别在于:高级定时器具有捕获/比较通道和互补输出,通用定时器只有捕获/比较通道,基本定时器没有以上两者。


2、定时器的工作原理

        定时器可分为四个大部分,分别是:时钟产生部分,时基单元部分,输入捕获部分,输出比较部分。

        (1)时钟产生部分可选择四种时钟源:①内部时钟(CK_INT);②外部时钟模式:外部触发输入(ETR);③内部触发输入(ITRx);④外部时钟模式:外部输入脚(TIx)。

        (2)时基单元部分包括三个寄存器:

        ①计数器寄存器(TIMx_CNT):向上计数、向下计数或者中心对齐计数;

        ②预分频器寄存器(TIMx_PSC):可将时钟频率按1到65535之间的任意值进行分频,可在运行时改变其设置值;

        ③自动装载寄存器(TIMx_ARR):如果TIMx_CR1寄存器中的ARPE位为0,ARR寄存器的内容将直接写入影子寄存器;如果ARPE为1,ARR寄存器的那日同将在每次的更新时间UEV发生时,传送到影子寄存器;如果TIM1_CR1中的UDIS位为0,当计数器产生溢出条件时,产生更新事件。

        (3)输入捕获部分

        IC1、2和IC3、4可以分别通过软件设置将其映射到TI1、TI2、TI3和TI4;

        4个16位捕捉比较寄存器可以编程用于存放检测到对应的每一次输入捕捉时计数器的值;

        当产生一次捕捉,相应的CCxIF标志位被置1;同时如果中断或DMA请求使能,则产生中断或DMA请求。

        如果当CCxIF标志位已经为1,当又产生一个捕捉,则捕捉溢出标志位CCxOF将被置1。

        (4)输出比较通道(PWM)

        PWM模式有两种:边沿对齐模式和中心对齐模式。

        频率和占空比可以进行如下设定:一个自动重载寄存器用于设定PWM的周期;每个PWM通道有一个捕捉比较寄存器用于设定占空时间。

3、PWM介绍

        PWM是指脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,也就是说通过调节占空比的变化来调节信号、能量等的变化,占空比就是指在一个周期内,信号处于高电平的时间占据整个信号周期的百分比,例如方波的占空比就是50%。PWM的功能有很多种,比如控制呼吸灯、控制直流电机或者舵机等驱动原件等等,是单片机的一个十分重要的功能。广泛应用在从测量、通信到功率控制与变换的许多领域中。 ​

        以单片机为例,我们知道,单片机的IO口输出的是数字信号,IO口只能输出高电平和低电平。假设高电平为5V 低电平则为0V 那么我们要输出不同的模拟电压,就要用到PWM,通过改变IO口输出的方波的占空比从而获得使用数字信号模拟成的模拟电压信号。

        我们知道,电压是以一种连接1或断开0的重复脉冲序列被夹到模拟负载上去的(例如LED灯,直流电机等),连接即是直流供电输出,断开即是直流供电断开。通过对连接和断开时间的控制,理论上来讲,可以输出任意不大于最大电压值(即0~5V之间任意大小)的模拟电压。

比方说:占空比为50% 那就是高电平时间一半,低电平时间一半,在一定的频率下,就可以得到模拟的2.5V输出电压 那么75%的占空比 得到的电压就是3.75V。

        PWM的调节作用来源于对“占周期”的宽度控制,“占周期”变宽,输出的能量就会提高,通过阻容变换电路所得到的平均电压值也会上升,“占周期”变窄,输出的电压信号的电压平均值就会降低,通过阻容变换电路所得到的平均电压值也会下降,也就是,在一定的频率下,通过不同的占空比 即可得到不同的输出模拟电压。

        PWM是在合适的信号频率下,通过一个周期里改变占空比的方式来改变输出的有效电压,当PWM效率越大,响应越快。对于呼吸灯来说,就是高电平的时间占整个周期的比值,占空比越高,LED就越暗。

        CCR不断增大意味着低电平占的时间越来越多所以亮度由暗一直到亮。

参考链接:

https://blog.csdn.net/qq_44016222/article/details/123507270

https://blog.csdn.net/as480133937/article/details/103439546

三、用定时器控制小灯周期性闪烁

1、环境搭建

        玻珠选择用库函数的方式来建立工程,这就需要我们去下载相关的固件库,这里直接提供玻珠下载的链接,出自江协科技(另:他家B站有关STM32芯片的相关学习视频真的很详细也很好懂),链接里不仅有STM32的,还有51单片机及其他相关知识的资料链接。

资料下载icon-default.png?t=N7T8https://jiangxiekeji.com/download.html        根据教程建立新工程后,就可以对代码进行完善了。

2、代码编写

        main.c文件:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"

uint8_t i;

int main(void)
{
	OLED_Init();
	PWM_Init();
	
	while (1)
	{
			PWM_SetCompare1(0);
			Delay_ms(2000);

			PWM_SetCompare1(100);
			Delay_ms(2000);
	}
}

        PWM.c文件:

#include "stm32f10x.h"                  // Device header

void PWM_Init(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//开启时钟
	
//	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//	GPIO_PinRemapConfig(GPIO_PartialRemap1_TIM2, ENABLE);
//	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;		//复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;		//GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 100 - 1;		//ARR
	TIM_TimeBaseInitStructure.TIM_Prescaler = 720 - 1;		//PSC
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);
	
	TIM_OCInitTypeDef TIM_OCInitStructure;
	TIM_OCStructInit(&TIM_OCInitStructure);//给结构体赋初始值
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;//设置输出比较的模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;//设置输出比较极性
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//设置输出状态
	TIM_OCInitStructure.TIM_Pulse = 0;		//设置CCR
	TIM_OC1Init(TIM2, &TIM_OCInitStructure);//放入Init函数中
	
	TIM_Cmd(TIM2, ENABLE);
}

void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);
}

        PWM.h文件: 

#ifndef __PWM_H
#define __PWM_H

void PWM_Init(void);
void PWM_SetCompare1(uint16_t Compare);

#endif

        编译一下,可以看到没有错误也没有警告,并且成功生成了Hex文件(没有生成的点击魔法棒,选择output,勾选Create HEX File就可以了)。

3、电路连接

        对于USB转TTL模块和STM32F103C8T6的连接:

        GND — GND

        3v3 — 3v3

        TXD — A10

        RXD — A9

        同时将芯片上3.3V接“+”,再连一根线将小灯和PA0口连接。

        实物图如下:

4、烧录和运行

        将USB接入电脑,打开烧录软件,选择好串口,并找到刚刚生成的Hex文件。注意这里需要先将板子上的BOOT0按照如下配置:

        然后点击开始编程,同时按下板子上的RESRT键,即可成功。 

        然后 将BOOT0置0,再次按下RESRT键,即可看见小灯周期性闪烁。

四、 用PWM模式运行呼吸灯

1、代码修改

        在上一问的基础上对代码进行修改即添加循环,便能完成呼吸灯。

        main.c文件:

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "PWM.h"

uint8_t i;

int main(void)
{
	OLED_Init();
	PWM_Init();
	
	while (1)
	{
		for (i = 0; i <= 100; i++)
		{
			PWM_SetCompare1(i);
			Delay_ms(10);
		}
		for (i = 0; i <= 100; i++)
		{
			PWM_SetCompare1(100 - i);
			Delay_ms(10);
		}
	}
}

        编译无错,生成hex文件。

2、电路连接与烧录运行

        电路的连接同上一问相同,按照上一问的步骤进行烧录,成功。

        运行结果如下:

五、观察波形

        点击魔术棒,更改Debug配置如下图,点击OK。

        点击打开逻辑分析仪,添加引脚,更改类型为Bit,点击close。

        运行结果如下: 

        串口显示:


总结

        本次实验学习了有关定时器、PWM的相关内容,旨在探索如何用PWM模式制作一个呼吸灯,并了解其工作原理。制作呼吸灯的意义不仅在于学习PWM控制原理,更重要的是掌握板子的使用方法。经过本次实验,我提高了自己的编程能力和解决问题的能力,尽管在制作过程中遇到了一些困难,但大部分都是之前碰到过的问题,稍加思考或询问同学就成功解决,收获了宝贵的经验。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 以下是一个简单的嵌入式控制 LED 灯亮灭的代码,供您参考: ```c #include <msp430g2553.h> void main(void) { WDTCTL = WDTPW + WDTHOLD; // 停用看门狗定时器 P1DIR |= BIT0; // P1.0 设置为输出 while(1) { P1OUT ^= BIT0; // P1.0 翻转状态 __delay_cycles(1000000); // 延时一秒 } } ``` 上面的代码使用 MSP430G2553 微控制器控制 P1.0 引脚的状态,实现 LED 灯的亮灭。在主函数中,首先停用看门狗定时器,然后将 P1.0 引脚设置为输出。接下来进入一个无限循环,每次循环中翻转 P1.0 引脚的状态,并延时一秒钟,从而实现 LED 灯的亮灭。 ### 回答2: 嵌入式系统主要是用于控制和管理各种设备的微型系统。其中嵌入式控制器是其中一种常见的设备,它具有灵活性和可靠性。 要控制LED灯的亮灭,首先需要了解使用的嵌入式控制器的编程语言。根据不同的控制器和开发平台,使用的编程语言可能有所不同,但在这里我将使用C语言作为示例来回答这个问题。 假设我们使用的是Arduino开发平台,代码如下: ```c // 引入基础库 #include <Arduino.h> // 指定LED的引脚 const int ledPin = 13; void setup() { // 设置LED引脚为输出模式 pinMode(ledPin, OUTPUT); } void loop() { // LED灯亮 digitalWrite(ledPin, HIGH); delay(1000); // 延迟1秒 // LED灯灭 digitalWrite(ledPin, LOW); delay(1000); // 延迟1秒 } ``` 解释一下上面的代码逻辑: 首先,我们通过引入基础库来使用Arduino开发平台的基本功能。然后,我们通过指定LED的引脚,将其设置为输出模式。在循环中,我们通过使用digitalWrite函数来控制LED灯的亮灭。当我们将引脚状态设置为HIGH时,LED灯会亮起;当我们将引脚状态设置为LOW时,LED灯会熄灭。通过使用delay函数,我们可以控制亮灭的时间间隔,上述代码中设置为1秒。 当我们在嵌入式系统中执行上述代码时,LED灯将不断地交替亮灭,每次亮灭持续1秒。这只是一个简单的示例,实际应用中,我们可以根据需要修改亮灭的时间间隔和其他功能。 这就是嵌入式控制LED灯亮灭的代码。通过编写类似的代码,我们可以利用嵌入式系统控制其他各种设备。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值