STC89C52 串口发送XDATA区域数据很奇怪的问题!~

nhcxc 2010-04-22 03:20:04
我用串口发送一个数组,发送函数如下:
void Uart_Init() //初始化UART
{
SCON =0x58; //选择串口工作方式,打开接收允许
TMOD|=0x20; //定时器1工作在方式2,
TH1 =0xfd; //实现波特率9600(系统时钟11.0592MHZ)
TL1=0xfd;
PCON |= 0x80; //实现波特率倍增
TR1 =1; //启动定时器T1
ES=1; //允许串行口中断
PS=1; //设计串行口中断优先级
EA =1; //单片机中断允许
}
///初始化没有问题。

void UART_SendData(unsigned char *data_buf,unsigned int iCount)//发送程序
{
bit es;
iUartSendLen = iCount-1;
es=ES;
ES=0;//关闭中断
for(iSendCounter=0;iSendCounter<=iUartSendLen;iSendCounter++)
{
TI=0;
SBUF = data_buf[iSendCounter];
while(!TI);
TI=0;
}
ES=es;
}//这个函数测试也没有问题

void SendDataToWifi(unsigned char *cCommandPara,unsigned char iLength)
{
unsigned char xdata cBuf[300]; //需要发送数据的数组 注意问题就在这行
cBuf[0] = 0x01; // 同步字段31 5f 33 5f 32 33 34
cBuf[1] = 0x02; // 控制字段
cBuf[2]=(iLength+1)>>8;
cBuf[3]=(iLength+1)&0x00ff;
cBuf[4]=GetCrc8(&cBuf[1],3);
memcpy(&cBuf[5],cCommandPara,iLength);
UART_SendData(cBuf,iLength+12);
}

当我定义下面的这个结构接收串口数据的时候,串口发送出去的内容全部变成了 OX02
typedef struct Buffer2
{
unsigned char gcATReceData[300];
unsigned int gcATReceCount;
} Buffer2;
struct Buffer2 xdata ATReceBuffer[1];//这里也必须把数组定义到XDATA里面

现在问题是:
当我把
unsigned char xdata cBuf[300];
改成
unsigned char cBuf[50];

发送和接收都正常,
但由于一次发送的内容比较多,必须把变量定义到 XDATA空间里面。。
我该怎么解决这个问题?
...全文
1114 14 打赏 收藏 举报
写回复
14 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
nhcxc 2010-04-24
谢谢楼上的大哥,ES的问题我改过来了。。iUartSendLen 由于在其他的地方需要用到这个全局变量,所以在这里赋值了。。你提出的XDATA的问题,我在其他地方还有XDATA的分配空间。我测试过了。确实并不是我之前考虑到的可能。局部变量和全局变量是没有区别的。。我修改了一下SENDBUF[250]就没有问题了。。然而300的时候KEIL没有报错,居然通过了。。

我现在把发送函数改成下面的,
unsigned char xdata* cpSendBufPtr;

void UART_SendData(unsigned char *data_buf,unsigned int iCount)
{
iUartSendLen = iCount-1;
iSendCounter = 0;
SBUF = data_buf[0];
cpSendBufPtr = &data_buf[1];
}
在中断里面再发送余下的。

测试完全没有问题了。。
  • 打赏
  • 举报
回复
jiqiang01234 2010-04-23
楼主看一下编译后xdata占用了多少字节。你的程序中,使用xdata类型的只用到这么两处吗?一个unsigned char xdata cBuf[300],一个struct Buffer2 xdata ATReceBuffer[1]。如果是的话,那么编译后xdata的使用应该是这两者之和,也就是602字节。
  • 打赏
  • 举报
回复
jiqiang01234 2010-04-23
void UART_SendData(unsigned char *data_buf,unsigned int iCount)//发送程序
{
bit es;
iUartSendLen = iCount-1;
es=ES;
ES=0;//关闭中断
for(iSendCounter=0;iSendCounter<=iUartSendLen;iSendCounter++)
{
TI=0;
SBUF = data_buf[iSendCounter];
while(!TI);
TI=0;
}
ES=es;
}//这个函数测试也没有问题

这个函数中,实现上(并非指功能上)还是稍微有些问题。
1、那个es变量其实没什么用,浪费了。接收前ES=0,接收后ES=1就可以了,不需要保存。
2、在c语言的循环中,往往约定循环变量范围是前闭合后开的半开半闭区间,及[a,b),所以for循环中的iSendCounter变量的范围应该是[0,iCount),即for(iSendCounter=0;iSendCounter<iCount;i++)。因此,iUartSendLen 这个变量可以省略。
3、关于“长度”变量的命名。一般来说,字符串的长度用length命名,而一般数据的长度用size命名。假设要使用iUartSendLen 这个变量,最好命名为iUartSendSize或nUartSendSize
  • 打赏
  • 举报
回复
jiqiang01234 2010-04-23
[Quote=引用 8 楼 nhcxc 的回复:]
问题终于解决了。。原来unsigned char xdata cBuf[300];这句话不能在函数里面声明,必须声明为全局变量,我估计可能是在编译的时候,由于有两个XDATA的变量,如果一个是全局变量,一个是局部变量的话,就会导致编译器,自动分配内存的时候出错。。
[/Quote]
我担心这并非是真正的原因。在函数里声明变量,仅仅是局部变量而已,不会导致什么编译时内存分配错误之类的问题(除非分配太大超出限制)。
  • 打赏
  • 举报
回复
Peasant_Lee 2010-04-22
STC可用的xdata空间有多大?你可以再试试定义unsigned char xdata cBuf[50]; 试试效果如何,看发送正常不?

凌晨3点多,呵呵,人人都在睡觉呢,,,,
  • 打赏
  • 举报
回复
durant 2010-04-22
学习了
  • 打赏
  • 举报
回复
Peasant_Lee 2010-04-22
呵呵,恭喜楼主。这个问题很难看出来,呵呵,看来定义局部变量的时候,特别是占用空间大的数据,要考虑剩余的xdata空间啊,不过也奇怪,编译器连个警告都没有么?这个有点像使用堆栈一样了,使用过程中要小心,时刻注意堆栈是否溢出。
  • 打赏
  • 举报
回复
nhcxc 2010-04-22
问题终于解决了。。原来unsigned char xdata cBuf[300];这句话不能在函数里面声明,必须声明为全局变量,我估计可能是在编译的时候,由于有两个XDATA的变量,如果一个是全局变量,一个是局部变量的话,就会导致编译器,自动分配内存的时候出错。。
  • 打赏
  • 举报
回复
Peasant_Lee 2010-04-22
楼主谦虚了,呵呵,我们就是讨论而已。
你现在用的是数组,其实数组也就是一个指针,传输的时候,也就是传输数组头的地址,当然这众所周知是个指针。问题是,你现在用数组,出问题了,暂时不知道问题在哪,换成指针的话,估计一样,不过楼主可以试试。

我曾经使用过一个韩国的增强型的51单片机,他的编译器是自做的,曾经出现很多很怪的问题。放在KEIL上是不会出现的。所以,我也想问问,STC也是用keil做编译环境的么?假如不是,到keil编译下,假如通过,下载看看效果。
  • 打赏
  • 举报
回复
nhcxc 2010-04-22
谢谢,Peasant_Lee大哥。。单字节发送,不是没有想过。。但是做起来的话很麻烦,由于处理的数据是一个自定义的协议,协议已经做好了。。修改起来,几乎等于整个工程重新再做。。我觉得应该可以利用指针来访问,XDATA区域的数据。。但是小弟才疏学浅。。不知道怎么解决这个问题。。两天了。。就是卡着过不了。。
  • 打赏
  • 举报
回复
nhcxc 2010-04-22
分不够,可以再加!~都快天亮了。。就是卡在这里。。
  • 打赏
  • 举报
回复
ydy8762 2010-04-22
飘过,mark
  • 打赏
  • 举报
回复
Peasant_Lee 2010-04-22
假如楼主不嫌麻烦,CPU资源充足的话,可以考虑单字节单字节的发送,然后就不需要XDTAT BUF了,直接从unsigned char *cCommandPara 取数据到ram区。
  • 打赏
  • 举报
回复
nhcxc 2010-04-22
STC有1280个XDATA。。。我查了一下资料,有可能是void UART_SendData(unsigned char *data_buf,unsigned int iCount)。。这里面声明的unsigned char *data_buf,指向的是 DATA 区域的指针,引用他不能获得XDATA里面的值。。但是我写成这样:
void UART_SendData(unsigned char xdata *data_buf,unsigned int iCount),也还是不行。。真的真的搞不懂。。。有没有高手能碰过类似的问题啊?
  • 打赏
  • 举报
回复
发帖
单片机/工控

2.7w+

社区成员

硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
帖子事件
创建了帖子
2010-04-22 03:20
社区公告
暂无公告