CC2530实现呼吸灯效果-PWM调光-TIM1定时器使用

目录

一、前言

二、思路及实现方法

三、CC2530相关寄存器

四、思路以及代码实现

五、源码


一、前言

        前面我们提到了非定时器模式实现呼吸灯效果,但由于其占用单片机主线程,如果不能加入RTOS的话,很难实现与其他功能的同步使用,因此,在实际应用中,仍需要通过定时器来操作LED实现呼吸灯效果,本文将带领大家逐步梳理开发过程,供各位借鉴。

二、思路及实现方法

        首先,我们介绍一下CC2530系列的定时器。

        CC2530具有4个定时器,TIM1是16位定时/计数器,支持输入采样、PWM功能,具有5个独立采样/输出比较通道。TIM3和TIM4是8位定时/计数器,支持输出比较和PWM功能,具有2个独立采样/输出比较通道。

        本篇文章实现程序采用的是TIM1实现PWM呼吸灯功能。

        TIM1具有三种运行模式,分别是自由运行模式、模模式、正反计数模式。本文将使用三种模式之一的模模式。在该模式下,计数器从0x0000开始计数,当计数器达到T1CC0时溢出,此时计数器回到0x0000并开始重新计数。

三、CC2530相关寄存器

        通过查阅CC2530数据开发手册,现将CC2530芯片有关TIM1的寄存器列出:

四、思路以及代码实现

        毋庸置疑,首先我们需要查看开发板原理图,找到我们想要实现呼吸灯效果的引脚。

        此处,根据我的原理图,我选择P1_1引脚上连接的LED灯泡来实现呼吸灯效果。

        首先,初始化P1_1引脚。

        随后,我们操作T1CTL寄存器,将定时器1设置为128分频,模模式计数。

        经过计算,在此模式下,每250个时钟边沿为1ms。我们需要其产生1ms的溢出。

        通过查看开发手册对模模式的介绍,我们可以得知,计数器会在达到T1CC0上保存的值后复位,因此我们只需将T1CC0设置为250,即可实现1ms复位,这类似于STM32的定时器开发的重装载值RCC。

        随后,我们应该开始设置与比较相关的配置。首先我们需要找到P1_1是否对应定时器的某个通道,如果没有对应通道,我们就应该另选端口。

        通过查阅CC2530开发手册,我们通过下表得知,P1_1在TIM1的备用位置2中的通道1中使用。

        首先,我们需要使能TIM1的备用位置2。

        通过开发手册中对TIM1的介绍,我们可以得知备用位置的设置需要操作PERCFG寄存器的T1CFG。因此我们寻找有关PERCFG的介绍。

        查到相关寄存器的介绍后,根据如下表,我们需要对第6位置1以使能备用位置。

        由于我们使用的是TIM1的通道1,因此我们需要配置定时器1通道1的捕获/比较控制寄存器:

        此处,我们首先需要设置Mode为1,即比较模式,随后设置CMP为110,即:当等于T1CC0时设置, 当等于T1CC1时清除。其流程如下:

        设置完比较模式后,我们需要设置比较值,查阅开发手册,发现比较值寄存器如下:

        此处,我们操作的T1CC1用来存储我们的比较值。可能大家会有一个疑问,为什么T1CC0却被用于模模式的溢出了呢?通过查阅手册我们不难发现,如果不使用自由运行模式,是无法使用TIM1的通道0进行PWM输出的比较的,因此无论是模模式还是正反计数模式都占用了T1CC0这个寄存器,因此我完成本项目的时候也是选用了TIM1的通道1。     

         此处,我们暂时先设置比较值为0。

        注意,此处我是先给低八位赋值,随后再给高八位赋值,这是为什么呢?

        我们注意看T1CCL的描述,写入时并不会写入T1CCL,而是会写入缓存,等到下次写入高八位时同时写入,因此建议先写低八位,后写高八位。

        随后,我们在主函数死循环中,写一个比较值从0~250的循环,以实现呼吸灯效果。

        烧录程序,即可查看运行效果。

五、源码

        附源代码.c文件:CC2530定时器实现PWM源代码-西西菜鸟

  • 10
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
在 Keil 中实现呼吸灯功能,可以使用 PWM (脉冲宽度调制) 来控制 LED 的亮度。下面是一个示例代码,使用 PWM 实现呼吸灯: ```c #include <stdio.h> #include <stm32f10x.h> #define PWM_FREQUENCY 10000 // PWM 频率,单位为 Hz void setupPWM() { // 使能 GPIOB 时钟 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // 配置 PB1 为 AFPP (复用推挽输出) 模式 GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); // 使能 TIM3 时钟 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); // 配置 TIM3 为 PWM 模式,频率为 PWM_FREQUENCY TIM_TimeBaseInitTypeDef TIM_InitStruct; TIM_InitStruct.TIM_Period = 1000 / PWM_FREQUENCY - 1; // 计数器自动重载值 TIM_InitStruct.TIM_Prescaler = SystemCoreClock / 1000000 - 1; // 分频系数,时钟频率为 1 MHz TIM_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_InitStruct.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(TIM3, &TIM_InitStruct); // 配置 TIM3_CH2 为 PWM 输出模式 TIM_OCInitTypeDef TIM_OC_InitStruct; TIM_OC_InitStruct.TIM_OCMode = TIM_OCMode_PWM1; TIM_OC_InitStruct.TIM_OutputState = TIM_OutputState_Enable; TIM_OC_InitStruct.TIM_Pulse = 0; // 初始占空比为 0% TIM_OC_InitStruct.TIM_OCPolarity = TIM_OCPolarity_High; TIM_OC2Init(TIM3, &TIM_OC_InitStruct); // 启动 TIM3 TIM_Cmd(TIM3, ENABLE); } int main(void) { setupPWM(); while (1) { for (int i = 0; i < 1000; i++) { TIM_SetCompare2(TIM3, i); // 占空比从 0% 到 100% for (int j = 0; j < 100000; j++); // 延时 } for (int i = 1000; i > 0; i--) { TIM_SetCompare2(TIM3, i); // 占空比从 100% 到 0% for (int j = 0; j < 100000; j++); // 延时 } } } ``` 这段代码使用了 STM32F10x 的 TIM3_CH2 PWM 输出功能,通过改变 PWM 的占空比来控制 LED 的亮度。由于这里没有使用定时器,而是使用了简单的 for 循环来实现呼吸灯效果,所以程序的精度可能会受到影响。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

西西菜鸟

打赏支持获得问题解答机会

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

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

打赏作者

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

抵扣说明:

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

余额充值