串口处理问题:不用等待接收多个字节
本帖最后由 GZLJZ 于 2012-4-20 00:30 编辑大家好,我之前把波特率设为115200,这样接收发送多个字节都直接在中断里了,
看到大家做485通信都经常波特率设为9600,接收一个字节就要约1MS,做485程序发送接收切换都要加入延时,这样如果发送接收20字节就要20MS多了,
这样单这个串口中断就占80MS,如果主循环里需要80MS以内处理的事情就做不了,
大家是这样处理这个问题的呢?
编辑原因:特率设为9600,接收一个字节好像是约1MS,我写4MS了 看到有人说,串口中断接收一个存进缓存里,等全部数据接收完了,在在主程序循环里处理,
但做485通信都知道,从机需要及时回应主机的,希望大家多耐心解答下困扰我的问题,先谢了 怎么及时也好,你就在主流程那里把一些复杂的函数拆成小部分完成,这样可以及时的 接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
做串口发送接收为了解决死等在那里,使用上面两行方法,我就不知具体主程序里怎么做:
做个缓冲区,用中断方式发送。 lollipop 发表于 2012-4-19 23:12 static/image/common/back.gif
做个缓冲区,用中断方式发送。
这样就是不行呀,假设主机发个地址过来,从机要回应主机呀,
我知道有人就是把地址和数据一起发给从机了,从机全部接收完成后才去处理,是不是需要的数据, GZLJZ 发表于 2012-4-19 23:18 static/image/common/back.gif
这样就是不行呀,假设主机发个地址过来,从机要回应主机呀,
我知道有人就是把地址和数据一起发给从机了 ...
你可以在串口的中断服务程序里判断接收到的信息 发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
下面程序是不是上面两行的意思,我就相这样做,可惜我看不懂C语言,有好心人转成汇编就好了
#include <REG52.H>
sbit LED = P1^0;
unsigned char UART_buff;
bit New_rec = 0, Send_ed = 1, Money = 0;
//----------------------------------------------
void main (void)
{
SCON = 0x50; //串口方式1, 8-n-1, 允许接收.
TMOD = 0x20; //T1方式2
TH1 = 0xFD; //9600bps@11.0592MHz
TL1 = 0xFD;
TR1 = 1;
ES= 1; //开中断.
EA= 1;
while(Money == 0); //等着交费,呵呵,等着接收$.
while(1){
if ((New_rec == 1) && (Send_ed == 1)){//如果收到新数据及发送完毕
SBUF = UART_buff; //那就发送.
New_rec = 0;
Send_ed = 0;
} }
}
//----------------------------------------------
void ser_int (void) interrupt 4
{
if(RI == 1) {//如果收到.
RI = 0; //清除标志.
New_rec = 1;
UART_buff = SBUF;//接收.
if(UART_buff == '1')LED = 1;
if(UART_buff == '0')LED = 0;
if(UART_buff == '$')Money = 1;
}
else{ //如果送毕.
TI = 0; //清除标志.
Send_ed = 1;
}
} 要汇编, 你直接编译一下不就得了.
不管 if ((New_rec == 1) && (Send_ed == 1))中的 && 有没有用错, 这段代码都无法保证接收数据不丢失. gycsy963 发表于 2012-4-19 23:50 static/image/common/back.gif
要汇编, 你直接编译一下不就得了.
不管 if ((New_rec == 1) && (Send_ed == 1))中的 && 有没有用错, 这 ...
对,上面程序好像不是正确的,
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
我就是要板数据处理放在主程序里,中断接收到一个字节就退出,这样就没有在浪费等待时间,
主程序里具体怎么编写呢。
本帖最后由 diannaoza 于 2012-4-20 00:33 编辑
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
下面程序是不是上面两行的意思,我就相这样做,可惜我看不懂C语言,有好心人转成汇编就好了
#include <REG52.H>
sbit LED = P1^0;
unsigned char UART_buff;
uart_buffdata 60h
bit New_rec = 0, Send_ed = 1, Money = 0;
new_rec bit 20h
send_ed bit 21h
money bit22h
//----------------------------------------------
void main (void)
{
clr new_rec
setb send_ed
clr money
SCON = 0x50; //串口方式1, 8-n-1, 允许接收.
mov SCON,#0X50
TMOD = 0x20; //T1方式2
MOV TMOD,#0X20
TH1 = 0xFD; //9600bps@11.0592MHz
MOV TH1,#0FDH
TL1 = 0xFD;
MOV TL1,#0FDH
TR1 = 1;
SETB TR1
ES= 1; //开中断.
SETB ES
EA= 1;
SETB EA
while(Money == 0); //等着交费,呵呵,等着接收$.
jnb money,$
while(1){
while:
if ((New_rec == 1) && (Send_ed == 1)){//如果收到新数据及发送完毕
jnb new_rec while_ex
jnb send_ed while_ex
while_enter:
mov sbuf,uart_buff
SBUF = UART_buff; //那就发送.
New_rec = 0;
clr new_rec
Send_ed = 0;
clr send_ed
while_ex:
ljmp while
} }
}
//----------------------------------------------
void ser_int (void) interrupt 4
{
if(RI == 1) {//如果收到.
jnb ri,ri_ex
RI = 0; //清除标志.
clr ri
New_rec = 1;
setb new_rec
UART_buff = SBUF;//接收.
mov uart_buf,sbuf
if(UART_buff == '1')LED = 1;
cjne uart_buf,#01h,ri_fn1ex
setb p1.0
ljmp ri_et_ex
ri_fn1ex:
if(UART_buff == '0')LED = 0;
cjne uart_buf,#00h,ri_fn2ex
clr p1.0
ljmp ri_et_ex
ri_fn2ex:
if(UART_buff == '$')Money = 1;
cjne uart_buf,#'$',ri_fn3ex
setb money
ljmp ri_et_ex
ri_fn3ex:
ri_et_ex:
ljmp ri_ti_ex
}
ri_ex:
else{ //如果送毕.
TI = 0; //清除标志.
clr ti
Send_ed = 1;
setb send_ed
}
ri_ti_ex:
} 回复11楼,谢谢你花那么多时间修改代码,C语言我是看不懂了,我是想实现下面的意思,数据在主程序里编写的思路,中断接收一个字节立即退出。用个全局变量?表明接收到第几个,再做处理?
发送数据时,也用“中断方式”,清除 TI 后,用另一个变量通知主函数,数据发送完毕。
接收数据时,使用“中断方式”,清除 RI 后,用一个变量通知主函数,收到新数据。
页:
[1]