由于在使用zigbee网络时往往有对电机、灯具等执行器进行控制的需要,而出于成本和简化系统的需求,我们又往往希望在CC2530上实现相关的控制及ZigBee的组网工作,使用CC2530芯片实现PWM输出则是一项重要的控制能力。

首先,需要选定输出PWM的IO口,查阅CC2530的数据手册关于GPIO与外设的映射关系如下:

为了方便程序编写,选择TIMER1作为PWM的定时器,选择其备用位置1作为PWM比较输出的位置。注意到TIMER1与USART0存在默认位置的冲突,故这里仅选用TIMER1的2、3、4通道,1、2通道留给USART0串口使用,方便程序调试。

对于这样的复用功能,由于串口的优先级往往更高,因此还需要对寄存器进行进一步的配置。查阅数据手册中配置USART0与TIMER1的优先级顺序的寄存器,如下图:

可以看到,相关寄存器位于P2DIR中,这是由于P2的IO口数量较少(不足8个),因此与其它功能共用一个8bit寄存器地址。(需要注意的是,我们需要配置的是位于P0的IO口,因此不要错误使用P2SEL对其它备用位置的IO进行优先级配置)

而定时器的启动及相关配置较为简单,在此不再赘述,可参考数据手册与代码增进理解。

仿照TI官方的HAL库写法,添加两个文件,分别是hal_pwm.h和hal_pwm.c。

//hal_pwm.h
#ifndef HAL_PWM_H
#define HAL_PWM_H#ifdef __cplusplus
extern "C"
{
#endif#include "hal_board.h"void PWM_Init(uint16 freq); // PWM初始化并设置频率
void PWM_Set(uint8 duty1, uint8 duty2, uint8 duty3); // 传入3个通道的比较值,0~255有效#ifdef __cplusplus
}
#endif#endif
//hal_pwm.c
#include "hal_pwm.h"#define PWM_1 P0_4
#define PWM_2 P0_5
#define PWM_3 P0_6void PWM_Init(uint16 freq)
{freq = 250000 / freq;PWM_1 = 1;PWM_2 = 1;PWM_3 = 1;CLKCONCMD &= ~0x40;       //设置系统时钟源为32MHZ晶振while(CLKCONSTA & 0x40);  //等待晶振稳定为32MCLKCONCMD &= ~0x07;       //设置系统主时钟频率为32MHZCLKCONCMD |= 0x38;        //设置定时器所分频率为250KHZPERCFG &= 0x00;           //选择定时器1映射的IO口位置,此处我们选择备用位置(Alt)1,它映射的IO口包括P0_4/5/6P2DIR |= 0xC0;            //当PERCFG分配给一些外设到相同引脚的时候,此时设定谁的优先级高,此处设定第1优先级为定时器1通道2-3P0DIR |= 0x70;            //设置P0_4/5/6为输出P0SEL |= 0x70;            //此时将P0_4/5/6配置为外设功能,即定时器1的输出比较T1CC0H = HI_UINT16(freq); //设定整个信号的周期时间(CC0即使不用也要设置)T1CC0L = LO_UINT16(freq) - 1;T1CC2H = 0x00;T1CC2L = 0x00;T1CCTL2 = 0x24;T1CC3H = 0x00;T1CC3L = 0x00;T1CCTL3 = 0x24;T1CC4H = 0x00;T1CC4L = 0x00;T1CCTL4 = 0x24;T1CTL = 0x02;            //设定定时器频率250KHz,1分频,设定运行模式为"模"模式,即从0x0000到T1CC0反复计数
}void PWM_Set(uint8 duty1, uint8 duty2, uint8 duty3) //0~255
{uint16 duty_set;uint16 duty_comp = BUILD_UINT16(T1CC0L, T1CC0H);float duty_precent;duty_precent = duty1/255.0;   //取得PWM实际占空比duty_set = (uint16)(duty_precent * duty_comp); //计算比较值T1CC2H = HI_UINT16(duty_set); //高位赋值T1CC2L = LO_UINT16(duty_set); //低位赋值duty_precent = duty2/255.0;duty_set = (uint16)(duty_precent * duty_comp);T1CC3H = HI_UINT16(duty_set);T1CC3L = LO_UINT16(duty_set);duty_precent = duty3/255.0;duty_set = (uint16)(duty_precent * duty_comp);T1CC4H = HI_UINT16(duty_set);T1CC4L = LO_UINT16(duty_set);
}#endif

代码中首先配置了系统时钟,若使用TI的Zstack协议栈则这些项目都是默认进行的配置(TI内部的OSAL系统使用TIMER4的1ms中断驱动操作系统工作)。

其次便是将定时器配置为1分频(不分频)模式,能够产生250KHz的最高频率,留给我们更多的配置空间。

通过对PERCFG寄存器的配置选择了TIMER0的位置选择,P2DIR则决定了这些IO上的优先等级。

P0DIR与P0SEL的功能与它们的名称一致,配置了IO映射到复用功能上,并设定方向为输出。

T1CC0则需要引起注意,由于我们选择的是输出的PWM频率与占空比皆可变化的“模”模式,因此T1CC0是PWM频率比较的基准,即使我们不使用TIMER1和通道0,也必须设置该寄存器。设置该寄存器即决定了整个PWM周期的频率,需要注意的是从0计算至T1CC0,因此设置值时需要注意减去1,对于频率敏感的场合尤其需要注意。

而T1CC2/T1CC3/T1CC4则默认设置为0,等待后续PWM配置函数进行计算和配置。

T1CCTL2/T1CCTL3/T1CCTL4则用于配置各个通道的输出模式与极性。在这里设置的值将使各个通道均工作在比较输出模式,并在计数值由0增加至T1CCx期间输出高电平,此后由T1CCx至T1CC0的过程中输出低电平,即输出正占空比,与一般的使用方式相符合。

在PWM_Set函数中,首先结合T1CC0的值,计算了PWM的实际占空比,并由此设置了3个输出通道的比较值。

在代码中,使用了TI公司提供的对数据结构进行转换的宏定义,摘录如下。

#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 0xFF)

#define BUILD_UINT16(loByte, hiByte) \
          ((uint16)(((loByte) & 0x00FF) + (((hiByte) & 0x00FF) << 8)))

希望能够对大家学习CC2530及ZigBee有所启发~

ZigBee——使用CC2530的定时器生成指定的PWM波相关推荐

  1. STM32F407-高级定时器输出指定个数PWM功能

    高级定时器输出指定个数PWM只需要设置好重复计数器寄存器RCR的值并打开更新中断即可. 一般情况下的更新中断是在CNT计数到ARR的时候产生,而在设置了RCR后,更新中断将会延迟,比如设置RCR的值为 ...

  2. STM32单片机一个定时器输出不同频率PWM波

      在使用STM32单片机输出PWM波形的时候,通常可以直接使用定时器提供的PWM模式.可以通过自动重装载寄存器(TIMx_ARR)来设置定时器的输出频率,然后通过捕获/ 比较寄存器 1(TIMx_C ...

  3. STM32F103单片机生成16路PWM波

    单片机输出pwm波在项目中是恨常用的一个功能,今天就总结一下用STM32F103C8T6单片机输出16路 pwm波. 使用keil5软件,用标准库函数来实现. 首先看定时器初始化 void TIM1_ ...

  4. STM8学习笔记---定时器输出7路PWM波

    STM8S003F3P6单片机共有三个定时器定时器1.定时器2.定时器4.其中定时器1为16位高级定时器,定时器2为16位通用定时器,定时器4为8位基本定时器.定时器1和定时器2可以输出PWM波.其中 ...

  5. STM32 - CubeMX 的使用实例详细(04.1)- STM32F103的 - 定时器设定详细解释 - PWM波的产生 - 频率占空比的设定 - 软件代码分析

    前言:本文详细条例STM32 103定时器的设定 1 定时器简介 中等容量的STM32F103xx增强型系列产品包含1个高级控制定时器.3个普通定时器,以及2个看门 狗定时器和1个系统嘀嗒定时器. 下 ...

  6. STM32F7同一定时器多路输出PWM波通道之间相互影响问题

    --------------------------2020/8/12更新-------------------------------- 这次用Cube直接生成PWM控制代码,然后再RT-Threa ...

  7. 【定时器/中断/PWM】利用一个定时器实现一路PWM波的输出---点亮LED

    ------------------------------------------凑热闹的分割线------------------------------------------------ /* ...

  8. STM32单片机:定时器TIM输出PWM波

    学习32单片机过程中使用的工具:MDK Keil5 + 正点原子精英版(STM32F103ZET6)+ STM32CubeMX + HAL开发 一.PWM的产生原理 关于PWM的产生原理网上有很多教程 ...

  9. STM32一个定时器同时捕获4路PWM波

    问题的提出: 最近需要用航模遥控器控制遥控车,32单片机做主控,需要用到4个通道即需要捕获4路PWM波.如果用四个定时器来捕获四路PWM波,就太浪费资源了.由于STM32单片机的定时器资源有限,故设想 ...

最新文章

  1. java handler使用方法_Android中Handler的使用方法及实例(基础回顾)
  2. 动态DNS——本质上是IP变化,将任意变换的IP地址绑定给一个固定的二级域名。不管这个线路的IP地址怎样变化,因特网用户还是可以使用这个固定的域名 这样看的话,p2p可以用哇...
  3. python re模块compile_Python re模块的match方法
  4. 渗透测试web未设置http头 Strict Transport Security
  5. 微软获 OpenAI 独家 GPT-3 模型授权,为何马斯克炮轰?
  6. 计算机大数乘法引发的思考 | CSDN 博文精选
  7. 架构师学习笔记(持续更新)
  8. [Remoting]在.NET環境實作Flex 3 Remoting - (2) Flex Builder 環境設定
  9. C#算法练习,求e,求π
  10. 【jmeter连接数据库报错问题排查,以及建立jmeter与mysql之间的简单连接】
  11. Java中的命名规范总结
  12. 双浮点运算计算机在线,双浮点运算计算器
  13. python colorbar刻度_python-如何添加Matplotlib Colorbar刻度
  14. 小程序***已设置仅在企业微信中运行,请前往企业微信打开该小程序,企业微信设置显示小程序。
  15. Arduino制作跑马灯
  16. 混沌与分形(一):谢尔宾斯基三角形与门格海绵
  17. 推荐系统经典算法之——MF(矩阵分解)
  18. HMI-43-【节能模式】顶部标题栏和底部信息栏及灯光及启动动画
  19. iPhone 越狱版本打包
  20. R语言plot(lm)绘图结果解读

热门文章

  1. android gilde生命周期管理,Glide原理之Activity、Fragment生命周期监听(三)
  2. 大数据平台安装部署(适用虚拟机级真实服务器,亲测)
  3. 【C++】万能头文件 <bits/stdc++.h> 的用法和优缺点
  4. sklearn数据降维之字典学习
  5. firefox安装java插件
  6. mysql 游标当前行,MySQL游标的使用笔记大全
  7. U盘启动常见的几种格式
  8. xp服务器修改登录密码,xp服务器开机密码设置
  9. VideoJS+HLS视频加密播放
  10. 从零玩转Python大数据+人工智能全套视频