论坛风格切换切换到宽版
  • 5385阅读
  • 11回复

串口测试程序实验 [复制链接]

上一主题 下一主题
离线bg5baw
 
发帖
698
只看楼主 倒序阅读 0楼 发表于: 2006-03-26
今天写了个简单的串口测试代码,想实验一下串口通信,现用测试器能发现串口输出端有数据输出,但不知道数据是否正确;代码写入单片机后想用串口调度软件看一下,是否能看到数据,现串口连机线也没有.又没法实验了,从来没做过串口相关的东西,心里没底,希望有串口通信实验板的朋友把代码写入芯片试试,明天就去买条串口线玩玩.更希望高手出来讨论.指点.把我们的论坛抄得更热.

#include<at89x51.h>

int a=170,n1.shou;
main()
{


tmod=0x12;//t0为8位定时器;t1为16位定时器;
scon=0x40;//串口为8位异步发送;
ea=1;//开总中断;
th0=0xff;//t0的高位;
tl0=0x32;//t0的初值;
et0=1;//开t0中断;
tr0=1;//开始计数;

th1=0xff;//t1的高位;
tl1=0x30;//t1的初值;//波特率为75.倍增后为150;
pcon=0x80;//波特率*2;
tr1=1;//开始终t1计数;
es=1;//开串行口中断;/////////
ren=1;//开串口接收;

while(1)
{
sbuf=a;//循环发送数据
if(ti==1)
{
n1=sbuf;
ti=0;
}
}
}
void t0(void) interrupt 1 using 0//t0中断;

{
p3_6=~p3_6;//位取反;


th0=0xff;//初值重装;

tl0=0x64;
}
void ps(void) interrupt 4 using 1//串行中断;

{//暂空
while(ri==1)
shou=sbuf;//////////////////////////////////////收到pc发送过来的信号数据;
ri=0;
p3_2=~p3_2;////////////////////////////////////取反p3_2
}
离线bg5baw
发帖
698
只看该作者 1楼 发表于: 2006-03-26
下面是hex文件
附件: 串口TEST1.rar (0 K) 下载次数:252
离线BG8WJ
发帖
166
只看该作者 2楼 发表于: 2006-03-26
sorry for using english because my os not chinese ver.
your soure code has some bug.
1st. line 3 int a=170,n1.shou; after n1 it must be "," not" ."
2nd. for loop send data from i/o you can use sprintf() can do well.
离线bg5sbj
发帖
386
只看该作者 3楼 发表于: 2006-03-27
看不懂c语言!
离线bg6abp
发帖
20
只看该作者 4楼 发表于: 2006-03-27
这个程序应该无法进行串口通信。t1应设为自动重载模式,否则t1溢出后你原来的初值就没有了。还有些地方写得不是很好。其实上atmel网站上就有51的包括串口在内的大量示例代码,c的和汇编的都有。51的串口编程很容易实现,在不能做实验的情况下利用keil的软件仿真也基本上可以调出正确的程序。给你一个串口通信的代码,22.1184mhz晶振下速度为115200bps,单片机把从串口收到的数据转发给电脑,用串口调试助手很容易看到成不成功。不知怎么提交的帖子里的代码没有缩进,将就一点看吧

void inituart(void)//串口初始化
{
disable_int;
scon = 0x50;//方式1, 8位数据位,允许接收    
tmod |= 0x20;//设置timer1: timer 1,方式2  
pcon |= 0x80;//smod=1
th1 = 0xff;// th1: reload value for 115200 baud rate @ 22.1184mhz  
tr1 = 1;// timer1开始计数
es = 1;//允许串行口中断
ps = 1;//设置串行口中断为高优先级中断
enable_int;
}

void com_isr() interrupt 4 //串行口中断服务程序
{
unsigned char temp;
bit bti_backup;

disable_int;//屏蔽所有中断
if(ri) //如果是接收到数据引起中断
{
  ri = 0; // ri清零
  bti_backup = ti;//备份当前ti的值
  ti = 0;//ti清零,以发送数据
  temp = sbuf;//读接收到的数据到temp
  sbuf = temp;//把temp的数据发送出去
  while(!ti);//等待至发送成功
  ti = bti_backup;//恢复原来ti的值
}
if(ti)//如果是发送完数据引起的中断,则除了ti清零外什么也不干
{
ti = 0; //ti清零,以发送数据
}
enable_int; //开放中断
}

void main()
{
inituart();      
while(1)
{
;      
}
}
离线bg5baw
发帖
698
只看该作者 5楼 发表于: 2006-03-27
今天工作忙,又没时间去买串口线.计划落空,过几天再实验,感谢bg6abp等朋友回帖.我想请问一下,用单片机接收上位机发的的数据.是否只能在串口中断程序中实现.例如上位机向单片机发aa的数据,是单片机先产生中断r1=1,在中断程序中再把数据赋值给其它变量进行处理.是否这样?是否还有其它的办法,请做过串口的高手作解答.
离线bg6abp
发帖
20
只看该作者 6楼 发表于: 2006-03-28
'
今天工作忙,又没时间去买串口线.计划落空,过几天再实验,感谢bg6abp等朋友回帖.我想请问一下,用单片机接收上位机发的的数据.是否只能在串口中断程序中实现.例如上位机向单片机发aa的数据,是单片机先产生中断r1=1,在中断程序中再把数据赋值给其它变量进行处理.是否这样?是否还有其它的办法,请做过串口的高手作解答.
'

除了在中断中处理,也可以用反复检测ri位的方法。当串口收到数据后,ri位被硬件置1。但这样做比较浪费cpu资源,在其它代码比较多的时候有可能造成读数据不及时,也就是下一字节的数据都来了,上一字节的数据还没读出来

while(1)
{
  if(ri)
  {
    读串口;
    ri = 0;
  }
  ...
  其它代码
  ...    //如果这些代码比较多可能造成读数据不及时
}
离线BG6AGB
发帖
915
只看该作者 7楼 发表于: 2006-03-28
'
今天工作忙,又没时间去买串口线.计划落空,过几天再实验,感谢bg6abp等朋友回帖.我想请问一下,用单片机接收上位机发的的数据.是否只能在串口中断程序中实现.例如上位机向单片机发aa的数据,是单片机先产生中断r1=1,在中断程序中再把数据赋值给其它变量进行处理.是否这样?是否还有其它的办法,请做过串口的高手作解答.
'

建议在ram中建立一个循环队列,在中断触发后将sbuf的数据送入循环队列中,这样避免了数据丢失,又避免了中断处理函数执行时间过长,而对于数据内容的处理,可以在主程序中做。
如果主程序比较费时间的话,这个循环队列就要建的稍微大一些。

具体可以看看任意一本数据结构的书关于队列的部分。
离线bg5baw
发帖
698
只看该作者 8楼 发表于: 2006-03-29
第一楼的代码:今天已经实验.能收到数据,但不知何原因数据不正确.收到的是00.真怪!~
离线bg5baw
发帖
698
只看该作者 9楼 发表于: 2006-03-30
'
建议在ram中建立一个循环队列,在中断触发后将sbuf的数据送入循环队列中,这样避免了数据丢失,又避免了中断处理函数执行时间过长,而对于数据内容的处理,可以在主程序中做。
如果主程序比较费时间的话,这个循环队列就要建的稍微大一些。
具体可以看看任意一本数据结构的书关于队列的部分。
'

谢谢你建议!
离线yido
发帖
52
只看该作者 10楼 发表于: 2006-03-30
串口通信我做过一些哈。有一点点体会。欢迎拍砖哈,互相学习。

一、在串口中断中代码量只要不是特别的多没有太大关系。
串口速率9600bps,单片机的晶振11.0592/12。也接近1m,所以串口中断函数中有简要的数据处理一般不会有太大的影响,我以前是根据程控指令的最大长度建立一个16字节或者32字节的环形缓冲区。串口收到的数据全部往里面放,在主程序中进行数据处理。后来觉得特费资源,虽然ram资源很够用,但是片上系统这个冬冬我一般比较节省,未雨绸缪,将来改进,升级难度要小一点。写计算机程序时候不一样哈,数据我从不吝啬。

后来,我将串口程控指令的解释干脆放在串口中断中进行,使用数个if判断,我自己设计的程控指令。比如<17 frq=123456789>,在串口中断中解码,判断数据合法性。最多要执行5-6个if判断后进入处理,总共进入中断处理程序后要进行15条左右指令的执行。运行还没有出过问题。


二,一般串口中断程序只是用来处理收数据。
即 if(ri)。发数据一般用查询指令查询处理
void send232dta(unsigned char argdta)
{
    sbuf = argdta;
    while(ti==0);
    ti=0;
}

三、注意共地和晶振
不光串行通信的共地,还有收发电路和数据电路的共地。晶振的频率最好能稳定一点,否则也容易导致数据混乱。
离线bg5baw
发帖
698
只看该作者 11楼 发表于: 2006-04-06
'
串口通信我做过一些哈。有一点点体会。欢迎拍砖哈,互相学习。
一、在串口中断中代码量只要不是特别的多没有太大关系。
串口速率9600bps,单片机的晶振11.0592/12。也接近1m,所以串口中断函数中有简要的数据处理一般不会有太大的影响,我以前是根据程控指令的最大长度建立一个16字节或者32字节的环形缓冲区。串口收到的数据全部往里面放,在主程序中进行数据处理。后来觉得特费资源,虽然ram资源很够用,但是片上系统这个冬冬我一般比较节省,未雨绸缪,将来改进,升级难度要小一点。写计算机程序时候不一样哈,数据我从不吝啬。
后来,我将串口程控指令的解释干脆放在串口中断中进行,使用数个if判断,我自己设计的程控指令。比如<17 frq=123456789>,在串口中断中解码,判断数据合法性。最多要执行5-6个if判断后进入处理,总共进入中断处理程序后要进行15条左右指令的执行。运行还没有出过问题。
二,一般串口中断程序只是用来处理收数据。
即 if(ri)。发数据一般用查询指令查询处理
void send232dta(unsigned char argdta)
{
    sbuf = argdta;
    while(ti==0);
    ti=0;
}
三、注意共地和晶振
不光串行通信的共地,还有收发电路和数据电路的共地。晶振的频率最好能稳定一点,否则也容易导致数据混乱。
'


谢谢你提供宝贵的经验!按你的思路我已经实验,通信数据很准确!