共2条
1/1 1 跳转至页
请教版主!串口问题?附实际运行的源程序
问
我在串口中断里面调用了check函数(将得到不确定的返回值),
而在主程序里调用check会得到正确的返回值,有
没有大侠告诉我怎么回事?究竟怎么解决?头痛!!!
用的是Philips p89c61x2单片机,其中check的返回值是由send
函数向串口调试助手发过去的。
下面是经过实际运行的完整用于测试的源程序。用的软件是串口调试助手,
当发送任一数值时响应中断。
#include"reg51.h"
#define uchar unsigned char
void init_serialcomm()
{
TMOD=0X20; ;设置定时器1工作模式为2
TH1 =0XFD; ;设置波特率为9600b
TL1 =0XFD;
SCON=0X50; ;设置串口位方式1
PCON=0X00;
TR1=1;
ES=1; ;打开串口中断允许
EA=1;
}
//发送函数
void send(uchar k)
{
SBUF=k;
while(TI==0);
TI=0;
}
//异或函数
uchar check(uchar k,uchar *m)
{
uchar i,parity;
parity=0x00;
for(i=0;i<k;i++)
{
parity=parity^(*(m+i));
}
return(parity);
}
//串口中断?
void serial() interrupt 4 using 3
{
uchar m[16],i;
//bit flag;
if(RI) //只用于接收中断
{
RI=0; //清接收中断标志位RI,以能便于下次接收中断
m[0]=0x12;
m[1]=0xA1;
m[2]=0x03;
m[3]=0x00;
m[4]=0x00;
m[5]=check(5,m);
for(i=0;i<6;i++)
send(m[i]);
}
}
//主函数
void main()
{
//uchar m[16]={0x12,0xA1,0X03,0X00,0X00};
uchar m[16],i;
init_serialcomm();
m[0]=0x12;
m[1]=0xA1;
m[2]=0x03;
m[3]=0x00;
m[4]=0x00;
m[5]=check(5,m);
for(i=0;i<6;i++)
send(m[i]);
//init_serialcomm();
while(1);
} 答 1: 没有热心人?没人理我。
可以复制回去看看啊,这是怎么一回事? 答 2: rt是不是因为主函数中
for(i=0;i<6;i++)
send(m[i]);
语句改变了*m地址,所以 答 3: ...........
两个函数里的数组m[]不是一回事 答 4: 有错误主函数,中断函数,都有问题
for(i=0;i<6;i++)
send(m[i]);
这是不对的,主函数只发送第一个字节就可以了,其他的在中断中处理较好,否则就要循环监视TI了,
中断中可以这样写
if (RI)
{
RI = 0;
revBuff[rCount] = SBUF;
rCount++;
}
else
{
TI = 0;
if (sCount........
{
..
..
}
else
{
SBUF = sndBuff[sCount];
sCount++;
}
} 答 5: 两个数组不一样不会影响返回值吧两个数组的定义都是完全一样的,就算不一样也应该和主函数返回值是一样的。 答 6: 这两数组都是局部变量局部变量在函数退出后会被清理,如果你在中断函数内部监视返回值,应当是一样的 答 7: windcity 说的对在发送中断send(m[i]); 中有问题
建议 void send(void)
{
SBUF = 0xXX;
send_length = 0xXX;
}
来触发TI中断
void Uart_int(void) interrupt 4
{
if(TI)
{
TI = 0;
if(Send_length--)
SBUF = m[XX]
}
}
大体的结构应该差不多了吧 答 8: 终于发现问题的所在 void serial() interrupt 4 using 3--------------第1种方式中断
void serial() interrupt 4-----------------------第2种方式中断
非常感谢各位大哥的建议,我今天又重新做了一下,终于发现问题的所在,如果我按照第1种方式做,在串口中断子程序里调用check后的返回函数值就是错的,如果按照第2种方式则是对的。
具体原因不明!!!!!!!! 我搞不清楚到底有什么问题呢?按道理说这两种
应该是一样的效果,只是第2种方式中断用到的是寄存器区3的R0---R7啊!
其实这个程序本身没有什么意义,我只是想测试一下在串口中断子程序里调用check函数,看看其返回值是否正确。
再一次谢谢!!
答 9: 主程序中用TI=1启动发送效果更佳主程序中设置发送字节数后,用TI=1启动发送.
这样做的好处是所有发送处理都在中断中,即首字节与其后字节处理简化.
TI=1是51的特色,其它MCU或ARM都几乎没有设置TI的功能,而只有清除的功能...
答 10: 看看信息窗口,肯定会有个MultiCall的警告! 主函数合中断都调用了check函数,有可能在check中调用check,冲毁了数据区(C51不允许递归) 答 11: 原来是这样的“看看信息窗口,肯定会有个MultiCall的警告”
确实有这个问题。
原来是这样的啊,谢谢提醒!!! 答 12: 函数重入问题!!c51的函数默认是非可重入的,
因此会出现MultiCall的警告!!
答 13: 用TI=1就不会出现函数重入问题
而在主程序里调用check会得到正确的返回值,有
没有大侠告诉我怎么回事?究竟怎么解决?头痛!!!
用的是Philips p89c61x2单片机,其中check的返回值是由send
函数向串口调试助手发过去的。
下面是经过实际运行的完整用于测试的源程序。用的软件是串口调试助手,
当发送任一数值时响应中断。
#include"reg51.h"
#define uchar unsigned char
void init_serialcomm()
{
TMOD=0X20; ;设置定时器1工作模式为2
TH1 =0XFD; ;设置波特率为9600b
TL1 =0XFD;
SCON=0X50; ;设置串口位方式1
PCON=0X00;
TR1=1;
ES=1; ;打开串口中断允许
EA=1;
}
//发送函数
void send(uchar k)
{
SBUF=k;
while(TI==0);
TI=0;
}
//异或函数
uchar check(uchar k,uchar *m)
{
uchar i,parity;
parity=0x00;
for(i=0;i<k;i++)
{
parity=parity^(*(m+i));
}
return(parity);
}
//串口中断?
void serial() interrupt 4 using 3
{
uchar m[16],i;
//bit flag;
if(RI) //只用于接收中断
{
RI=0; //清接收中断标志位RI,以能便于下次接收中断
m[0]=0x12;
m[1]=0xA1;
m[2]=0x03;
m[3]=0x00;
m[4]=0x00;
m[5]=check(5,m);
for(i=0;i<6;i++)
send(m[i]);
}
}
//主函数
void main()
{
//uchar m[16]={0x12,0xA1,0X03,0X00,0X00};
uchar m[16],i;
init_serialcomm();
m[0]=0x12;
m[1]=0xA1;
m[2]=0x03;
m[3]=0x00;
m[4]=0x00;
m[5]=check(5,m);
for(i=0;i<6;i++)
send(m[i]);
//init_serialcomm();
while(1);
} 答 1: 没有热心人?没人理我。
可以复制回去看看啊,这是怎么一回事? 答 2: rt是不是因为主函数中
for(i=0;i<6;i++)
send(m[i]);
语句改变了*m地址,所以 答 3: ...........
两个函数里的数组m[]不是一回事 答 4: 有错误主函数,中断函数,都有问题
for(i=0;i<6;i++)
send(m[i]);
这是不对的,主函数只发送第一个字节就可以了,其他的在中断中处理较好,否则就要循环监视TI了,
中断中可以这样写
if (RI)
{
RI = 0;
revBuff[rCount] = SBUF;
rCount++;
}
else
{
TI = 0;
if (sCount........
{
..
..
}
else
{
SBUF = sndBuff[sCount];
sCount++;
}
} 答 5: 两个数组不一样不会影响返回值吧两个数组的定义都是完全一样的,就算不一样也应该和主函数返回值是一样的。 答 6: 这两数组都是局部变量局部变量在函数退出后会被清理,如果你在中断函数内部监视返回值,应当是一样的 答 7: windcity 说的对在发送中断send(m[i]); 中有问题
建议 void send(void)
{
SBUF = 0xXX;
send_length = 0xXX;
}
来触发TI中断
void Uart_int(void) interrupt 4
{
if(TI)
{
TI = 0;
if(Send_length--)
SBUF = m[XX]
}
}
大体的结构应该差不多了吧 答 8: 终于发现问题的所在 void serial() interrupt 4 using 3--------------第1种方式中断
void serial() interrupt 4-----------------------第2种方式中断
非常感谢各位大哥的建议,我今天又重新做了一下,终于发现问题的所在,如果我按照第1种方式做,在串口中断子程序里调用check后的返回函数值就是错的,如果按照第2种方式则是对的。
具体原因不明!!!!!!!! 我搞不清楚到底有什么问题呢?按道理说这两种
应该是一样的效果,只是第2种方式中断用到的是寄存器区3的R0---R7啊!
其实这个程序本身没有什么意义,我只是想测试一下在串口中断子程序里调用check函数,看看其返回值是否正确。
再一次谢谢!!
答 9: 主程序中用TI=1启动发送效果更佳主程序中设置发送字节数后,用TI=1启动发送.
这样做的好处是所有发送处理都在中断中,即首字节与其后字节处理简化.
TI=1是51的特色,其它MCU或ARM都几乎没有设置TI的功能,而只有清除的功能...
答 10: 看看信息窗口,肯定会有个MultiCall的警告! 主函数合中断都调用了check函数,有可能在check中调用check,冲毁了数据区(C51不允许递归) 答 11: 原来是这样的“看看信息窗口,肯定会有个MultiCall的警告”
确实有这个问题。
原来是这样的啊,谢谢提醒!!! 答 12: 函数重入问题!!c51的函数默认是非可重入的,
因此会出现MultiCall的警告!!
答 13: 用TI=1就不会出现函数重入问题
共2条
1/1 1 跳转至页
回复
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |
打赏帖 | |
---|---|
与电子爱好者谈读图四被打赏50分 | |
与电子爱好者谈读图二被打赏50分 | |
【FRDM-MCXN947评测】Core1适配运行FreeRtos被打赏50分 | |
【FRDM-MCXN947评测】双核调试被打赏50分 | |
【CPKCORRA8D1B评测】---移植CoreMark被打赏50分 | |
【CPKCORRA8D1B评测】---打开硬件定时器被打赏50分 | |
【FRDM-MCXA156评测】4、CAN loopback模式测试被打赏50分 | |
【CPKcorRA8D1评测】--搭建初始环境被打赏50分 | |
【FRDM-MCXA156评测】3、使用FlexIO模拟UART被打赏50分 | |
【FRDM-MCXA156评测】2、rt-thread MCXA156 BSP制作被打赏50分 |