“ UART (USART)口的多机通信 ─ 利用 ZigBee 无线模块相互通信“ 发现了4种数据通
整个系统由“1台PC和5组感测模块(M16L + 6轴传感器)“组成,其中:
主机部分:1块ZigBee无线通信模块由RS-232 to USB到1台PC,标志为0号。
从机部分:5块ZigBee无线通信模块各自和5组感测模块的UART接口串接,分别标志为1~5号。
总共有6个节点,而全部的ZigBee无线通信模块皆设置为“广播模式”。
程序流程为:
一、1~5号模块分别上电后,进入INITIAL状态,等待接收Capture命令。
二、由0号(PC)透过自身的ZigBee模块”广播”发送一个Capture命令(0xFF0xEC),让1~5号的ZigBee模块一起接收此命令。
三、1~5号模块判断接收到Capture命令(认定为几乎同时收到!?)以后,禁止接收功能(RXEN = 0)。
四、开始对传感器信号进行ADC,各轴轮流采样转换,各5次并且取平均值后,进入INITIAL状态,始能接收功能(RXEN = 1),等待接收ID命令。
五、其中,当1号模块完成ADC后,会自动进入发送数据状态(无需等待接收ID命令),发送全部的数据后,进入INITIAL状态,始能接收功能(RXEN = 1),
之后又再次地等待0号发送Capture命令。
数据包格式为: “ID地址、数据1、数据2、数据3、数据4、数据5、数据6“,共7个字节。
六、当0号(PC)接收完1号发送的完整数据包后,开始发送2号的ID命令(0xFFID地址),让2号模块传回它自身模块的数据包。
七、2号模块判断接收到ID命令后,进入发送状态,并且禁止接收功能;数据包发送完成后,进入INITIAL状态,始能接收功能,
之后又再次地等待0号发送Capture命令。
八、3、4、5号的状态分别类似于六、和七、。
九、最后,0号接收完5号模块的完整数据包后,判断并处理1~5号的数据,又再次地”广播”发送Capture命令,让1~5号的ZigBee模块一起准备接收此命令,
回到流程二、。
问题描述如下:
发现了4种数据通信的问题情况,导致整体流程通信到一半,就卡住停止了:
1. 0号(PC)开始发送Capture命令,整体流程通信了一段时间,突然1~5号模块没有收到Capture命令?
2. 整体流程通信了一段时间,突然1~5号模块的某一号模块没有收到0号发送的ID命令,以致数据只显示到上一号模块。
3. 同上,但情况变为:0号(PC)没有收到1~5号某一号模块的数据包,以致无法发送下一组的ID命令。
4. 同上,情况为:0号(PC)没有收到5号模块的数据包,以致无法发送Capture命令。
检查过PC收到的每一号模块的数据包内容,皆正确无误。
而这些问题发生的时间都是随机不固定的,有时发生在启动后2秒内,有时发生在启动后10秒内,甚至有时发生在2分钟内,但是有时候通信却很稳定。
已经思考了很久,但仍不知道哪里有问题,在此麻烦请教各位,谢谢。
(下方为2号模块的M16L程序内容) /*****************************************************************************************************************************
CPU : ATmega16L
CLK : 7.3728 MHz
Buad Rate : 57600
*****************************************************************************************************************************/
#define F_CPU 7372800
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "ZIG100.h"
#defineID 0x32 //编号2
#defineSTART 0xEC //模块启动命令
#defineCALLFLAG 0xFF //接收起始旗标
#defineSENSOR 6 //感测轴数
#defineTIMES 5 //采样次数
/* 状态参数 */
#defineINITIAL 0 //初始
#defineACTION 1 //AD转换
#defineTX 2 //传送
#defineWAIT 4 //等待ADC完成
/* 指令接收参数 */
#defineQUANTITY 2 //指令数据2笔
#defineFIRST 0 //索引值 0
#defineSECOND 1 //索引值 1
/* USART参数 */
#defineFOSC 7372800 // Clock频率 //
#defineBUAD 57600 // Buad Rate //
#defineUBRR (FOSC/(16*BUAD))-1
/* ADC参数 */
#defineADC_INITI 0x60 // ADC参考电压:AVcc,数据向左对齐 //
/* 各个输入通道 */
#defineADC1 0x01
#defineADC2 0x02
#defineADC3 0x03
#defineADC4 0x04
#defineADC5 0x05
#defineADC6 0x06
volatile int State = 0;
int RxNum = 0;
int Axis = 0, Count = 0; //惯性轴和采样次数
unsigned int ADC_Data; //组合ADC数据
unsigned int ADC_Average; //ADC平均
unsigned char RX_Command;
//ADC取5次平均//
void AverageFilter(void)
{
int axis, count;
for(axis = 0; axis < SENSOR; axis++)
{
ADC_Average = INITIAL; //清空上一堆数据
for(count = 0; count < TIMES; count++)
{
ADC_Average += ADC_Data; //不断累加
}
ADC_Average /= TIMES; //平均=累加和/5
}
}
//无线传送ADC值//
void ADC_Tx(void)
{
int axis;
ZIG100_Tx(ID); //传送ID
for(axis = 0; axis < SENSOR; axis++)
{
ZIG100_Tx((unsigned char)ADC_Average); //数据1~6
}
}
//USART接收中断程序//
ISR(USART_RXC_vect)
{
RX_Command = UDR; //读取UDR值,更新RXC
switch(RxNum)
{
case FIRST:
if(RX_Command == CALLFLAG)
{
RxNum = SECOND;
}
break;
case SECOND:
switch(RX_Command)
{
case START: //Capture 命令
UCSRB &= ~_BV(RXEN);
State = ACTION;
break;
case ID: //ID 命令
UCSRB &= ~_BV(RXEN);
State = TX;
break;
}
RxNum = FIRST;
break;
}
}
//ADC中断程序//
ISR(ADC_vect)
{
//在取样次数内即可转换,超过即取平均//
if(Count < TIMES)
{
ADC_Data = ADCH;
ADMUX++; //切换channel
Axis++; //切换axis
//重新切换并采样次数+1//
if(Axis == SENSOR)
{
ADMUX = ADC_INITI | ADC1; //再从ADC1开始
Axis = INITIAL;
Count++;
}
State = ACTION;
}
else
{
AverageFilter(); //Count超过后,开始取平均
Count = INITIAL; //重新计数采样次数
State = INITIAL;
}
}
int main(void)
{
DDRA = 0x00; //PA为传感器输入
PORTA = 0x00;
//USART抗干扰//
DDRD = 0x02; //RXD输入,TXD输出
PORTD = 0x03; //RXD上拉电阻有效,TXD输出
ADMUX = ADC_INITI | ADC1; //从 ADC1 开始 //
USART_Initi(UBRR); //设定USART和buad rate
//ADC enable, ADC interrupt enable, ADC_clk=7.3728 M/64=115.2 KHz//
ADCSRA = _BV(ADEN) | _BV(ADIE) | _BV(ADPS2) | _BV(ADPS1);
sei(); //全局中断
while(1)
{
switch(State)
{
case INITIAL:
State = WAIT;
UCSRB |= _BV(RXEN); //启动RX,准备接收讯号进入中断
break;
case ACTION:
ADCSRA |= _BV(ADSC); //ADC start (单次转换, 每次到完成都需要25个ADC_clk周期)
State = WAIT;
break;
case TX:
ADC_Tx();
State = INITIAL;
break;
case WAIT:
// 等待 //
break;
}
}
}
------------------------------------ZIG100.h------------------------------------------------
void USART_Initi(unsigned int ubrr)
{
UBRRH = (unsigned char)(ubrr >> 8);
UBRRL = (unsigned char)ubrr;
UCSRB = (1 << RXCIE) | (1 << RXEN) | (1 << TXEN);
UCSRC = (1 << URSEL) | (3 << UCSZ0);
}
void ZIG100_Tx(unsigned char data)
{
while( !(UCSRA & (1 << UDRE)) );
UDR = data;
} 无线传输的一大特点就是不可靠,容易受干扰
Zigbee不是可靠通讯的协议栈不同于有线网的TCP
而且串口通信业会产生误码,最好加上数据包头和校验数据 是否因为无线网络部稳定?出现数据误传,或者丢失?没有看到楼主的握手协议部分,建议加入0号和1~5号的握手试试。 回复【2楼】superrf
无线传输的一大特点就是不可靠,容易受干扰
zigbee不是可靠通讯的协议栈不同于有线网的tcp
而且串口通信业会产生误码,最好加上数据包头和校验数据
-----------------------------------------------------------------------
后来有尝试将数据包的内容修改,加了数据包头 (0xFF0xAA0x55),并且再增加一个测试节点,接收主/从机的所有数据。
发现:
不论是主或从机部分,所发送出来的数据内容都正确;但是依然会有类似的问题 --- 系统通信了一段时间,主(从)机有广播发送出数据,然而从(主)机似乎没收到命令,所以没传回自身数据。
而系统没在最后加上checksum,是因为希望单单就通信的部分,先能够稳定发送和接收数据不会间断。
烦请指导,谢谢。 回复【3樓】sailen
是否因為無線網絡部穩定?出現數據誤傳,或者丟失?沒有看到樓主的握手協議部分,建議加入0號和1~5號的握手試試。
-----------------------------------------------------------------------
数据部分似乎没有误传,有增加测试节点来做测试。
不论是主/从机,每个节点发送或接收到的数据内容都正确,但就是会有此问题:通信了一段时间,主(从)机有广播发送出数据,然而从(主)机似乎没收到命令,所以没传回自身数据。
烦请指导,谢谢。 其实你的情况很简单的啊,你没有加上超时处理的啊,不可以无限等待某一个一节点给你回复。必须设置超时时间,等待一定时间后没有收到回复,要么重发,要么丢弃发下一个节点。
不知道你ZigBee是哪家的芯片?有没有走协议栈。 回复【6楼】sytu_xww芦苇
-----------------------------------------------------------------------
全部使用的ZigBee模块是ZIG-100,模块上的芯片是CC2420。
PC(0号)端的程序是使用DataReceived触发的,接收到上一个节点的数据,处理后便会发送呼叫下一个节点回传数据。
但是通信一段时间,在某个时间点,PC端却没有进入触发程序 (下一个节点没有回传数据);透过测试端接收测试的话,确实有收到下一个节点发送的回传数据,这是不懂的问题所在。
为了固定并缩短整体的采样周期,请问能否不加上超时处理呢?因为并不知道何时会发生超时,或是发生的次数也不固定。
烦请指导,谢谢。 你是不是遇到同频干扰的问题了? 我也用过cc2420,遇到了通信瘫痪的问题。
这里假定你没有用协议栈,那么你在发送数据之前,要用CCA探测一下,如果信道空闲,再随机退避一个时间,把数据发送出去。
记得2420是具有cca_txon功能的。用这个命令发送,STXONCCA。 回复【9楼】renkaikaiser
-----------------------------------------------------------------------
我使用的是应用层部分,协议栈应该都被产品(ZIG-100)写好了。
在每次通信期间,我都有延迟一小段时间再发送,还是会发生模块或PC机有收不到数据的情况,但是单纯接收的测试端就都有收到? chiaming 发表于 2011-2-28 17:04 static/image/common/back.gif
回复【9楼】renkaikaiser
-----------------------------------------------------------------------
我也遇到同楼主一样的问题,总感觉Zigbee通讯的稳定性太差了,我感觉好像有丢包,只能通过应用层加一些超时,重发来处理了。 周末没事 mark优秀帖
页:
[1]