串口通信的问题

kusheng176 2010-04-23 10:01:43
我最近碰到2个问题,实在搞不懂,所以请教一下各位大哥。。。
1、我通过我的硬件键盘,按键,然后在串口调试助手上显示相应的键值,但是上面显示的数值前面,总有一些诡异的符号。比如我按6,就会显示66666。
我希望只显示出一个正常的6,应该怎么弄呢?

2、我每次按完一次键以后,程序就终止了,我想要按完6个键,程序才会终止,应该怎么做呢?

主程序如下:
main()
{
a=0;
while(a<6)
{
P1=0x70;
TMOD=0x20; //设置定时器1为工作方式2
TH1=0xf3;
TL1=0xf3;
TR1=1;
REN=1;
SM0=0;
SM1=1;
EA=1; /*CPU开中断*/
IT0=1; /*脉冲触发方式(负跳变有效)*/
EX0=1; /*允许外部中断0中断*/
}
}

中断程序内就是一个键盘扫描程序,这是扫描完以后的一个输出代码,请教。。。
SBUF=num;
printf("%d",num);
while(!TI);
TI=0;
a++;
...全文
114 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
kusheng176 2010-04-26
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 wsoon 的回复:]
/**********************************************************************************
* 获取按键值应用数码管显示并通过RS-232发送到PC上进行显示
*
*
*
*
*
* 文 件: TEST.C
* 作 者: soon
* 部 门: 计算机07级04班
* 编写日期: 200……
[/Quote]

谢谢你。。。问题已解决了
Peasant_Lee 2010-04-23
  • 打赏
  • 举报
回复
中断函数,有点混乱,而且有个致命的问题,虽然可能不是造成现在问题的原因,但是对整个系统稳定很严重的。

中断函数里面尽量简洁,但是你用了若干个delay(10)延时10ms函数来消抖。这样你用了几十毫秒等待,再加上你发送UART 的while(!TI); 假如波特率比较低的话,同样需要一定的时间。这个几十ms ,在中断里面延时,是极其少见,没人这样用。

再次,在一般工业应用上,外部中断,连一般的处理也不会做。你在里面处理了按键扫描。而且也比较臃肿。当然这个问题没上面的延时那么严重。

中断里面处理事情越多,压栈也就越大,占用CPU越长,不利于系统的稳定性,到时什么怪现象都会有的,所以我建议,先将程序结构搞好。将按键处理和串口发送另开辟函数,放在主程序里,然后中断只是立标志供主循环判断用。


这样改了之后,假如再出问题,就比较简单了,程序结构也清晰。


kusheng176 2010-04-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 peasant_lee 的回复:]
安装楼主你的回答,我现在的理解是:mian()函数,就是一些串口和中断初始化。所有的操作都是放在中断函数里面,建议将这个函数贴出来吧,问题很有可能就在那里。
[/Quote]

好的

#include <reg52.h>
#include <stdio.h>
#include <absacc.h>
#define uchar unsigned char
#define uint unsigned int
uchar temp;
uint num,a;
sbit P1_7=P1^7;

void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}


void Int0() interrupt 0
{
EX0=0;
P1=0xfe;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xbe:num=1;
break;
case 0xde:num=2;
break;
case 0xee:num=3;
break;
}
if(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}

P1=0xfd;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xbd:num=4;
break;
case 0xdd:num=5;
break;
case 0xed:num=6;
break;
}
if(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}


P1=0xfb;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xbb:num=7;
break;
case 0xdb:num=8;
break;
case 0xeb:num=9;
break;
}
if(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}


P1=0xf7;
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
delay(10);
temp=P1;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xd7:num=0;
break;
}
if(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
SBUF=num;
printf("%d",num);
while(!TI);
TI=0;
a++;
}

main()
{
a=0;
while(a<6)
{
P1=0x70;
TMOD=0x20; //设置定时器1为工作方式2
TH1=0xf3;
TL1=0xf3;
TR1=1;
REN=1;
SM0=0;
SM1=1;
EA=1; /*CPU开中断*/
IT0=1; /*脉冲触发方式(负跳变有效)*/
EX0=1; /*允许外部中断0中断*/
}
}

麻烦你了
Peasant_Lee 2010-04-23
  • 打赏
  • 举报
回复
安装楼主你的回答,我现在的理解是:mian()函数,就是一些串口和中断初始化。所有的操作都是放在中断函数里面,建议将这个函数贴出来吧,问题很有可能就在那里。
kusheng176 2010-04-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 peasant_lee 的回复:]
凡是按键按下,就启动外部中断是吧?
下面这段代码也是在该中断函数里面?
SBUF=num;
printf("%d",num);
while(!TI);
TI=0;
a++;
[/Quote]

是的 但是我跳出中断以后 程序就不循环了 就直接终止了
Peasant_Lee 2010-04-23
  • 打赏
  • 举报
回复
凡是按键按下,就启动外部中断是吧?
下面这段代码也是在该中断函数里面?
SBUF=num;
printf("%d",num);
while(!TI);
TI=0;
a++;
qinshudong 2010-04-23
  • 打赏
  • 举报
回复
哥啊 按键去抖动你去的啊 常用的延时啊 算算时间
kusheng176 2010-04-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 happypay 的回复:]
怎么是TI啊?
不明白,不是RI么?
[/Quote]

我是把我单片机的按键键值,上传到PC机上去,应该没错吧?
happypay 2010-04-23
  • 打赏
  • 举报
回复
怎么是TI啊?
不明白,不是RI么?
soon 2010-04-23
  • 打赏
  • 举报
回复
/**********************************************************************************
* 获取按键值应用数码管显示并通过RS-232发送到PC上进行显示
*
*
*
*
*
* 文 件: TEST.C
* 作 者: soon
* 部 门: 计算机07级04班
* 编写日期: 2009.5.4
* 模块版本:
* 适用芯片: CPU 89C52RC
* 修改记录:
* ================================================================================
* 版 本| 日 期 | 修改人 | 描 述
* ================================================================================
* | | |
* | | |
* | | |
* ================================================================================
*
* 注意事项:在进行发送字符到PC机上时,由于通信波特率为9600,所以在我按键按下的时间
* 内,进行发送的字符较多。所以,必须进行延时处理,使其只通发送一个字符到
* PC机。本程序进行处理的时间只能进行发送与接收是以字符格式进行的,当格式
* 格式不对时,所进行延时的时间需要进行重新设置。
*
*
*
*
**********************************************************************************/

#include <reg52.h>

#define uint unsigned int
#define uchar unsigned char


uchar buff[4]={0XC0,0xCF,0XA4,0XB0}; /*定义要进行数码显示的数字*/
uchar buff2[3]={'1','2','3'}; /*定义要进行在串口调试工具中进行显示的字符*/
uchar buff3[]=" "; /*用于在串口调试工具中输出空格*/

sbit key1=P3^5; /*按键1*/
sbit key2=P3^6; /*按键2*/
sbit key3=P3^7; /*按键3*/

uchar buf; /*用于保存按键的编号*/
uchar chose; /*用于确定是否有按键按下*/
uchar i; /*用于循环控制*/


void sender(uchar buf); /*声明串口发送函数*/
void dispchar(uchar buf); /*声明数码显示函数*/
void key(void ); /*声明获取按键编号函数*/
void delytime(uint time); /*声明延时函数*/


/***********************************主函数*************************************/
void main(void )
{
/*进行设置波特率为9600*/
TMOD=0X20;

TL1=0XFD;
TH1=0XFD;

SCON=0XD8;
PCON=0X00;

EA=1; /*允许中断*/
TR1=1; /*启动T1中断*/
ES=1; /*允许串口中断*/
REN=0; /*禁止接收数据*/


P2=0X7F; /*选中第四个数码显示管*/
P0=0XC0; /*初始化显示*/

while(1)
{
key(); /*获取按键编号*/

dispchar(buf); /*进行显示*/

if(chose==1)
{
delytime(25000); /*进行延时,这样就只进行显示一次字符,否则进行多次显示*/

sender(buff2[buf-1]); /*在串口调试工具中进行显示字符*/

for(i=0;i<4;i++) /*在串口调度工具中输出空格*/
sender(buff3[i]);

}
}

}

/**********************************************************************************
* 发送函数
*描述:该函数用于发送字符到PC机。
*
*参数: 要进行发送的字符
*
*返回值:无
*
* 注意事项:
**********************************************************************************/
void sender(uchar buf)
{
SBUF=buf;

while(TI==0);

TI=0; /*软件清零*/
}

/**********************************************************************************
* 进行数码管显示
*描述:该函数用于在数码管上进行显示字符。
*
*参数:要进行显示的字符
*
*返回值:无
*
* 注意事项:
**********************************************************************************/
void dispchar(uchar buf)
{
P0=buff[buf];
}

/**********************************************************************************
* 获取接键值
*描述:该函数用于获取接键值。
*
*参数: 无
*
*返回值:无
*
*注意事项:由于本人的实验板只有三个按键,所以,对按键的判断没有采用其它的算法。
* 当按键数量有一定的数量时,请采用其它的算法。这样在时间溢率上才能达
* 所需的要求。
**********************************************************************************/
void key(void )
{
if(key1==0)
{
delytime(300); /*进行延时,去抖动*/

if(key1==0) /*再次进行扫描*/
{
buf=1;
chose=1;
}
}

else if(key2==0)
{
delytime(300);

if(key2==0)
{
buf=2;
chose=1;
}
}

else if(key3==0)
{
delytime(300);

if(key3==0)
{
buf=3;
chose=1;
}
}

else /*进行保存最后一次按键的编号,否则就只有暂短的显示,又恢复到0*/
{
buf=buf;
chose=0;
}
}


/**********************************************************************************
* 延时函数
*描述:该函数用于延时。
*
*参数:要进行延时的时间
*
*返回值:无
*
*注意事项:本延时函数不是一个精准的延时函数,若对延时时间要求太严格,请应用汇编
* 语言进行,那样写出的延时才能准确
**********************************************************************************/
void delytime(uint time)
{
while(time)
{
time--;
}
}


/**********************************************************************************
||
||
||
|| END
||
||
||
||
**********************************************************************************/

这是本人在学单片机的时候写的,楼主可以试着改改不需要的函数,在按键实验中请注意去抖动和进行适量的延时,否则会出现多个值,这是因为按下按键的时候与发送值的时间不是一个数量级的。

很久没有用过单片机,也只能给你提供这么点信息,因为本人是把单片机做为入门嵌入式的一个经过,入门嵌入式后就再也没有用过单片机了。
kingkb 2010-04-23
  • 打赏
  • 举报
回复
串口初始化怎么写在while里?
kusheng176 2010-04-23
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 peasant_lee 的回复:]
中断函数,有点混乱,而且有个致命的问题,虽然可能不是造成现在问题的原因,但是对整个系统稳定很严重的。

中断函数里面尽量简洁,但是你用了若干个delay(10)延时10ms函数来消抖。这样你用了几十毫秒等待,再加上你发送UART 的while(!TI); 假如波特率比较低的话,同样需要一定的时间。这个几十ms ,在中断里面延时,是极其少见,没人这样用。

再次,在一般工业应用上,外部中断……
[/Quote]


谢谢你 我等下按照你说的 去改一下程序吧 万分感谢~

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧