22101|25

193

帖子

3

TA的资源

一粒金砂(高级)

楼主
 

ZigBeeCC2530无线PWM产生以及定时器应用 [复制链接]

 
本帖最后由 jsxykj1 于 2014-3-10 20:54 编辑

分享下PWM产生呼吸灯经验,顺便和大家一起继续学习无线,由于小弟新手不才,有不对的请多多原谅。首先谢谢合纵物联的产品和技术支持,官方群 305145401。大家有兴趣的都来讨论ZIGBEE,主要是能够享受优质服务和技术支持。
先来跟大家介绍一个我的这个实验所需要达到的要求。
1.Zigbee协调器接收到上位机串口的数据后用协调器通过周期广播将数据发送到末节点。(这个串口我是通过改了的,如果要修改可以参考透传实验)
2.让末节点的接收事件产生后进入到我定义的PWM事件。(这个部分主要可以学习ZIGBEE的事件调用触发,以及定时器的寄存器配置。)
1.ZIGBEE协调器部分编程:
1、 ZigBee 模块接收到从 PC 机发送信息,然后无线发送出去
以前我们做的都是 CC2530 给 PC 机串口发信息,还没接触过 PC 机发送
给 CC2530,现在我们就来完成这个任务。其主要代码在 MT_UART.C 中。我
们之前协议栈串口实验对串口初始化时候已经有所了解了。
我们在这个文件里找到串口初始化函数 void MT_UartInit (),找到下面代码:

#if defined (ZTOOL_P1) || defined (ZTOOL_P2)
uartConfig.callBackFunc = MT_UartProcessZToolData;
#elif defined (ZAPP_P1) || defined (ZAPP_P2)
uartConfig.callBackFunc = MT_UartProcessZAppData;
#else
uartConfig.callBackFunc = NULL;
#endif

我们定义了 ZTOOL_P1,故协议栈数据处理的函数 MT_UartProcessZToolData,
进入这个函数定义。下边是对函数关键地方的解释。
/*******************************************************************
* @fn MT_UartProcessZToolData
*
* @brief | SOP | Data Length | CMD | Data | FCS |
* | 1 | 1 | 2 | 0-Len | 1 |
*
* Parses the data and determine either is SPI or just simply serial data
* then send the data to correct place (MT or APP)
*
* @param port - UART port
* event - Event that causes the callback
* @return None
****************************************************************/
/* 这个函数很长,具体说来就是把串口发来的数据包进行打包,校验,生
成一个消息,发给处理数据包的任务。如果你看过 MT 的文档,应该知道如
果用 ZTOOL 通过串口来沟通协议栈,那么发过来的串口数据具有以下格式:
0xFE, DataLength, CM0, CM1, Data payload, FCS

翻译: 0xFE:数据帧头
DataLength:Datapayload 的数据长度,以字节计,低字节在前;
CM0:命令低字节;
CM1:命令高字节;(ZTOOL 软件就是通过发送一系列命令给 MT 实现和
协议栈交互)
Data payload:数据帧具体的数据,这个长度是可变的,但是要和
DataLength 一致;
FCS :校验和,从 DataLength 字节开始到 Data payload 最后一个字节
所有字节的异或按字节操作;

也就是说,如果 PC 机想通过串口发送信息给 CC2530,由于是使用默认的
串口函数,所以您必须按上面的格式发送,否则 CC2530 是收不到任何东西的,
这也是我们大家在调试串口接收时一直打圈的地方。尽管这个机制是非常完善
的,也能校验串口数据,但是很明显,我们需要的是 CC2530 能直接接收到串口
信息,然后一成不变的发成出去,相信你在聊 QQ 的时候也不希望在每句话前面
加 FE .. ..的特定字符吧,而且还要自己计算校验码。
于是我们就来个偷龙转凤,把改函数换成我们自己的串口处理函数,是不
是很酷?当然,不过前提我们先要了解自带的这个函数。
Void MT_UartProcessZToolData ( uint8 port, uint8 event )
{


while (Hal_UART_RxBufLen(port))
/*查询缓冲区读信息,也成了这里信息是否接收完的标志*/
{
HalUARTRead (port, &ch, 1);

148
/*一个一个地读,读完一个缓冲区就清 1 个了,?为什么这样呢,往下看*/

switch (state)
/*用上状态机了*/
{
case SOP_STATE:
if (ch == MT_UART_SOF) /* MT_UART_SOF 的值默认是 0xFE,所以数
据必须 FE 格式开始发送才能进入下
一个状态,不然永远在这里转圈*/
state = LEN_STATE;
break;

case LEN_STATE:
LEN_Token = ch;
tempDataLen = 0;

/* Allocate memory for the data */
pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof
( mtOSALSerialData_t ) +MT_RPC_FRAME_HDR_SZ + LEN_Token );
/* 分配内存空间*/

if (pMsg) /* 如果分配成功*/
{
/* Fill up what we can */
pMsg->hdr.event = CMD_SERIAL_MSG;
/* 注册事件号 CMD_SERIAL_MSG;,很有用*/
pMsg->msg = (uint8*)(pMsg+1);
/*定位数据位置*/



/* Make sure it’s correct */
tmp=MT_UartCalcFCS((uint8*)&pMsg->msg[0], MT_RPC_FRAME_HDR_SZ
+ LEN_Token);
if (tmp == FSC_Token) /*数据校验*/
{
osal_msg_send( App_TaskID, (byte *)pMsg );
/*把数据包发送到 OSAL 层,很很重要*/
}
else
{
/* deallocate the msg */
osal_msg_deallocate ( (uint8 *)pMsg );
/*清申请的内存空间*/

149

}
/* Reset the state, send or discard the buffers at this point */
state = SOP_STATE; /*状态机一周期完成*/




简单看了一下代码,串口从 PC 机接收到信息会做如下处理:
1、 接收串口数据,判断起始码是否为 0xFE
2、 得到数据长度然后给数据包 pMsg 分配内存
3、 给数据包 pMsg 装数据
4、 打包成任务发给上层 OSAL 待处理
5、 释放数据包内存

我们要做的是简化再简化。流程变成:
1、 接收到数据
2、 判断长度然后然后给数据包 pMsg 分配内存
3、 打包发送给上层 OSAL 待处理
4、 释放内存


网蜂独家参考程序如下:
1. void MT_UartProcessZToolData ( uint8 port, uint8 event )
2. {
3. uint8 flag=0,I,j=0; //flag 是判断有没有收到数据,j 记录数据长度
4. uint8 buf[128]; //串口 buffer 最大缓冲默认是 128,我们这里用 128.
5. (void)event; // Intentionally unreferenced parameter

6. while (Hal_UART_RxBufLen(port)) //检测串口数据是否接收完成

7. {
8. HalUARTRead (port,&buf[j], 1); //把数据接收放到 buf 中
9. j++; //记录字符数
10. flag=1; //已经从串口接收到信息
11. }

12. if(flag==1) //已经从串口接收到信息

13. { /* Allocate memory for the data */
14. //分配内存空间,为机构体内容+数据内容+1 个记录长度的数据
15. pMsg = (mtOSALSerialData_t *)osal_msg_allocate( sizeof
16. ( mtOSALSerialData_t )+j+1);
17. //事件号用原来的 CMD_SERIAL_MSG

150
18. pMsg->hdr.event = CMD_SERIAL_MSG;
19. pMsg->msg = (uint8*)(pMsg+1); // 把数据定位到结构体数据部分
20. pMsg->msg [0]= j; //给上层的数据第一个是长度
21. for(i=0;i 22. pMsg->msg [i+1]= buf;
23. osal_msg_send( App_TaskID, (byte *)pMsg ); //登记任务,发往上层
24. /* deallocate the msg */
25. osal_msg_deallocate ( (uint8 *)pMsg ); //释放内存
26. }
27. }


由网蜂提供的代码可以知道,数据包中数据部分的格式是:
datalen + data
到这里,数据接收的处理函数已经完成了,接下来我们要做的就是怎么在任
务中处理这个包内容呢?很简单,因为串口初始化是在 SampleApp 中进行的,
任务号也是 SampleApp 的 ID,所以当然是在 SampleApp.C 里面进行了。在
SampleApp.C 找到任务处理函数:
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events ),加入下
面红色代码:
uint16 SampleApp_ProcessEvent( uint8 task_id, uint16 events )
{
afIncomingMSGPacket_t *MSGpkt;
(void)task_id; // Intentionally unreferenced parameter
if ( events & SYS_EVENT_MSG )
{
MSGpkt(afIncomingMSGPacket_t*)osal_msg_receive( SampleApp_TaskID );
while ( MSGpkt )
{
switch ( MSGpkt->hdr.event )
{
case CMD_SERIAL_MSG: //串口收到数据后由 MT_UART 层传递过来的
数据,用网蜂方法接收,编译时不定义 MT
相关内容,
SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt);
break;

解释:串口收到信息后,事件号 CMD_SERIAL_MSG 就会被登记,便进入
case CMD_SERIAL_MSG:

执行 SampleApp_SerialCMD((mtOSALSerialData_t *)MSGpkt);大家是不
是很奇怪怎么在协议栈里找不到这个函数,当然了,我们那边只把他打包了,然
后登记任务,这个包是我们自己的,想怎么处理当然由自己来搞掂。大家应该想到这个函数应该要把信息无线发送出去吧,想到这个的话你的悟性还挺高的。

下面贴上网蜂的参考代码,用户也可以自己完成。
1. void SampleApp_SerialCMD(mtOSALSerialData_t *cmdMsg)
{
2. uint8 I,len,*str=NULL; //len 有用数据长度
3. str=cmdMsg->msg; //指向数据开头
4. len=*str; //msg 里的第 1 个字节代表后面的数据长度

5. /********打印出串口接收到的数据,用于提示*********/

6. for(i=1;i<=len;i++)
7. HalUARTWrite(0,str+I,1 );
8. HalUARTWrite(0,” ”,1 );//换行

9. /*******发送出去***参考网蜂 1 小时无线数据传输教*********/

10. if ( AF_DataRequest( &SampleApp_Periodic_DstAddr, &SampleApp_epDesc,
11. SAMPLEAPP_COM_CLUSTERID,//自己定义一个
12. len+1, // 数据长度
13. str, //数据内容
14. &SampleApp_TransID,
15. AF_DISCV_ROUTE,
16. AF_DEFAULT_RADIUS ) == afStatus_SUCCESS )
17. {
18. }
19. else
20. {
21. // Error occurred in request to send.
22. }
23. }


这是协调器通过串口事件将实现读取串口的信息周期给出去。修改根据网峰的还是很简单。
下面给大家粘出协调器的代码。这个基本没改过就当他是透传。


我们的协调器大概就是这么简单。
2.现在给大家在末节点先粘出代码。

这是我先给大家配置一个定时器1,由于定时器1是16位的所以我们在处理高八位和第八位需要自己给一个规定来转化,定时器34不需要因为是8位也有8位寄存器。
#define HI_UINT16(a) (((a) >> 8) & 0xFF)
#define LO_UINT16(a) ((a) & 0xFF)   16位高低转换
#define HI_UINT8(a) (((a) >> 4) & 0x0F)
#define LO_UINT8(a) ((a) & 0x0F)  8位高低转换
我在和一个朋友一起配置寄存器的时候会发现我们是否需要关了定时器再进行值得装载,在这里我是觉得是不需要的,不然每回关对电平会产生影响,之后他的效果就会很差。
所以我将前面的T1CTL=0;开始这句话删除了。
再我们来配置引脚,和优先级这里我们需要打开芯片手册,这个很简单在这,我的定时器1有两个备用脚我是用的2,因为我的串口P0.3和通道冲突了,所以在这我希望大家先将自己的引脚看好不然串口没效果了,会很麻烦。所以大家先配置PERCFG寄存器现在自己的外设优先级设置好这样我们就方便后面的应用。
我是选用的向上比较模式。这个通过我的值看看你们的芯片手册肯定就懂了,再就是PWM波也可以用模模式产生,只是我们配置操作不一样。在这里跟大家粘出其他模式代码
这个也是可以的大家可以试试。先说到这里关于接收串口后建立事件,不停的触发事件,下楼继续分享,要做作业了蛋疼。
此帖出自无线连接论坛

最新回复

真心不错的好资料啊,谢谢分享啊,对做项目和开发很有用的。  详情 回复 发表于 2019-1-9 10:59

赞赏

1

查看全部赞赏

点赞 关注(4)
 

回复
举报

193

帖子

3

TA的资源

一粒金砂(高级)

沙发
 
本帖最后由 jsxykj1 于 2014-3-10 21:12 编辑

大家只要裸奔出了PWM我现在就来讲讲创建时间,这样我们才能好好的玩转ZIGBEE的osal哟!先给大家上代码
看看末节点代码:

1.我们可以再这里设置事件。PRO_PWM_EVENT这个我是需要加一个宏定义的意思就是给事件编个号吧(如图)

这样我们事件算是能够被创建,我们再看看读到数据后我们事件怎么执行

这个是事件发生后的执行。Init1();这个函数要被执行现在我们事件基本就能够工作了但是我们的事件到底在干什么呢?估计说到这里大家都会有疑问所以现在跟大家看看{我这个是做的呼吸灯,所以你们懂的}
void InitT1() //系统不配置工作时钟时默认是2分频,即16MHz
{
   unsigned int pwm_value;
   
     //unsigned int   flag;
     
     // T1CTL=0;
  //设置通道相关 I/O 引脚输出
  P1DIR |= 0x02;
  //将 P1.1 定义为外设功能
  P1SEL |= 0x02;
  
  //外设控制 定时器 1 定义在位置 2
  PERCFG |= 0x40;
  //设置比较值
  T1CC1H = 0x00;
  T1CC1L = 0x0f;
  //输出向上,比较模式
  T1CCTL1 = 0x1C;
  T1CTL = 0x05;          //1分频,自动重装 0X0000-0XFFFF
    pwm_value = brightness * (MAX_PWM_VAL / 100);
  // set the new PWM value
  T1CC1H = HI_UINT16(pwm_value);
  T1CC1L = LO_UINT16(pwm_value);
if(flag==0)
    brightness=brightness +1;
   if(brightness>=100)
   flag=1;
   if(flag==1)
    brightness=brightness-1;
   if(brightness<=4)
     flag=0;
}
让装载值每隔20毫秒加1所以我的呼吸灯周期大概在4S我让灯从占空比在0-100-4这样变化的所以大家可以看到这样每次加1的效果比一次执行到100占空比再触发事件有着天然的区别,这也是一个朋友介绍的很感谢,,,呵呵。
我也不知道你们那里还没看懂   如果还有没看懂的直接提出来我来跟大家补充。看楼下要源码  所以我给大家在三楼放出,希望我们大家多来分享资料都学习下。
此帖出自无线连接论坛
 
 
 

回复

193

帖子

3

TA的资源

一粒金砂(高级)

板凳
 
本帖最后由 jsxykj1 于 2014-3-10 21:17 编辑

源码!

Source.zip

12.72 KB, 阅读权限: 5, 下载次数: 196

售价: 1 分芯积分  [记录]

由于整个工程太大也没必要,我直接给CH文件,大家应该都懂了

此帖出自无线连接论坛

点评

真心不错的好资料啊,谢谢分享啊,对做项目和开发很有用的。  详情 回复 发表于 2019-1-9 10:59
 
 
 

回复

2002

帖子

24

TA的资源

五彩晶圆(高级)

4
 
使用了T1的PWM功能实现的是么,高手,这样次啊能真正把频率做高,没中断所以不会影响RF部分是吧,希望LZ能分享整个工程给大家,学习一下
此帖出自无线连接论坛

点评

目前没有看到影响射频部分,不过这个我还会跟楼继续补充给大家的,频率呵呵 你要好高呢?大家一起好好学习呵呵,只是最近上大二课多作业也多麻烦死了  详情 回复 发表于 2014-3-9 17:57
 
 
 

回复

193

帖子

3

TA的资源

一粒金砂(高级)

5
 
shower.xu 发表于 2014-3-9 17:48
使用了T1的PWM功能实现的是么,高手,这样次啊能真正把频率做高,没中断所以不会影响RF部分是吧,希望LZ能 ...

目前没有看到影响射频部分,不过这个我还会跟楼继续补充给大家的,频率呵呵 你要好高呢?大家一起好好学习呵呵,只是最近上大二课多作业也多麻烦死了
此帖出自无线连接论坛
 
 
 

回复

6107

帖子

4

TA的资源

版主

6
 
好,支持。学习了。
此帖出自无线连接论坛
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(初级)

7
 
支持
此帖出自无线连接论坛

点评

上面有呀!  详情 回复 发表于 2014-7-15 11:26
 
 
 

回复

9

帖子

0

TA的资源

一粒金砂(初级)

8
 
楼主能不能分享一下工程啊
此帖出自无线连接论坛
 
 
 

回复

193

帖子

3

TA的资源

一粒金砂(高级)

9
 
 
 
 

回复

20

帖子

0

TA的资源

一粒金砂(中级)

10
 
非常感谢楼主的分享啊。学习了。
此帖出自无线连接论坛
 
 
 

回复

120

帖子

0

TA的资源

一粒金砂(中级)

11
 
LZ    请问PWM可以在CC2530的任意引脚产生吗?还是只有固定的几个引脚,那么具体的是那些呢?
此帖出自无线连接论坛

点评

定时器引脚输出  详情 回复 发表于 2015-3-4 22:44
 
 
 

回复

4996

帖子

19

TA的资源

裸片初长成(初级)

12
 
学习了。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
此帖出自无线连接论坛
个人签名我的博客
 
 
 

回复

193

帖子

3

TA的资源

一粒金砂(高级)

13
 
定时器指定引脚输

此帖出自无线连接论坛
 
 
 

回复

193

帖子

3

TA的资源

一粒金砂(高级)

14
 
flying510 发表于 2015-1-11 13:05
LZ    请问PWM可以在CC2530的任意引脚产生吗?还是只有固定的几个引脚,那么具体的是那些呢?



定时器引脚输出
此帖出自无线连接论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

15
 
楼主,这个可以用按键无线控制呼吸灯吗?研究了这方面好久,不解啊
此帖出自无线连接论坛

点评

你好可以的。我就是这样实现的  详情 回复 发表于 2016-4-18 15:11
 
 
 

回复

193

帖子

3

TA的资源

一粒金砂(高级)

16
 
1330921338 发表于 2016-4-16 14:48
楼主,这个可以用按键无线控制呼吸灯吗?研究了这方面好久,不解啊

你好可以的。我就是这样实现的
此帖出自无线连接论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

17
 
楼主真厉害,给力,实现了
此帖出自无线连接论坛
 
 
 

回复

1

帖子

0

TA的资源

一粒金砂(初级)

18
 
编译不通过呀
此帖出自无线连接论坛
 
 
 

回复

2

帖子

3

TA的资源

一粒金砂(初级)

19
 
此帖出自无线连接论坛
 
 
 

回复

2

帖子

3

TA的资源

一粒金砂(初级)

20
 
不用分享了,
此帖出自无线连接论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/7 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表