求单片机串口中断接收程序,怎样一次性接受多个字符

求单片机串口中断接收程序,怎样一次性接受多个字符,第1张

首先把变量a定义成一个数组a[10],数组大小,根据要接收的字符确定再加一个变量J

在开中断ES=1后,加一个延时函数我用过很多这样的了请多给点分,以后我还可以帮你程序如下:

#include<reg52h>

unsigned char flag,i,j;

unsigned int k;

unsigned char a[10];

unsigned char code table[6]="I get ";

void init()

{

TMOD=0x20; //设定定时器工作方式2

TH1=0xfd; //定时器1装入初值

TL1=0xfd; //同上

TR1=1; //启动T1定时器

SM0=0; //设定工作方式1

SM1=1; //同上

REN=1; //允许串口接收

EA=1; //开总中断

ES=1; //开串口中断

}

void main()

{

init();

while(1)

{

if(flag==1)

{

ES=0;

for(i=0;i<6;i++)

{

SBUF=table[i];

while(!TI);

TI=0;

}

ES=1;

for(k=0;k<0xffff;k++);

for(i=0;i<j;i++)

{

SBUF=a[i];

while(!TI);

TI=0;

}

flag=0;

}

}

}

void ser() interrupt 4 //中断程序,接收数据块,标志位置1

{

RI=0;

a[j]=SBUF;

flag=1;

j+=1;

}

我的程序的一部分,供参考

//主流程

void

main(void)

{

//系统初始化

SCON

=

0x50;

//串口方式为1,SM2=

0,TB8=

1

PCON

=

0x80;

//

SMOD=1

TMOD

=

0x22;

//设定定时器0/1的工作模式为方式2

//设置T0中断的定时时间为1/7200毫秒

TH0

=

0x00;

TL0

=

0x00;

//设置异步串口的波特率

//TH1

=

0x0f4;

//OSC

=

110592MHz

bps

=

4800

SMOD=1

//TL1

=

0x0f4;

TH1

=

0x0fd;

//OSC

=

110592MHz

bps

=

19200

SMOD=1

TL1

=

0x0fd;

//设置中断优先级,T0中断为高优先级中断,其他为低优先级中断

IP

=

0x02;

//

设置中断优先级--T0为高优先级,其他低

ET0

=

1;

//定时器0中断

ES

=

1;

//串行接口中断

EA

=

1;

//系统中断允许

TR0

=

1;

//启动定时器0

TR1

=

1;

//串口接收中断处理程序

//发送采用查询处理

void

SerialComm(void)

interrupt

4

{

_pReceive[_cReceive]

=

SBUF;

_cReceive

++;

if(_cReceive

>=

RecBuffSize)

_cReceive

=

0;

RI

=

0;

}

//串口发送一个字节

//senddata:需要发送的数据

void

SendOneByte(unsigned

char

senddata)

{

ES

=

0;

TI

=

0;

SBUF

=

senddata;

while(TI

==

0);

TI

=

0;

ES

=

1;

}

你这串口接收子程序,只要接收到第一个字节的数据就一直在中断子程序中,然后等待接收其它数据了,

while(!RI); 这就是在等待接收其它数据了,接收完了以后又在中断子程序连续发送了。这么写程序是有很大弊病的,一旦进入中断程序,到最后发送结束,都一直在中断子程序中,那这个期间单片机是不能再做其它工作的,也就是不能再执行主程序了。

while(!RI);这就是查询方式等待接收数据,那又何必写成中断程序呢,不如直接写成查询程序了,同样下面的, while(!TI);这也明明是在查询方式发送,就不必要写在中断程序中了。

既然采用中断的方式,就是当接收到一个数据后才响应一次中断,保存这个数据,然后就立即从中断返回,这样,继续执行主程序,这样,接收数据和发送数据才不影响主程序。

同理,在中断程序发送一个字节的数据就立即从中断返回执行主程序,也不影响主程序的执行。

另外,更重要的一点就是while(!RI);,等待接收数据,如果不能收到数据就永远等待下去,假如通信线有故障,或者发送方有问题,不能发送数据了,那么将永远等待下去,这就相当于死机了,多可怕,写程序就怕这个事情发生的。

#include<reg52h>

unsigned char code table[] ={" "};

unsigned char code table1[]={" : "};

sbit rs=P1^2;

sbit lcden=P1^0;

unsigned char flag,m;

void delay(int xms)

{

int i,j;

for(i=xms;i>0;i--) //i=xms即延时约xms毫秒

for(j=110;j>0;j--);

}

void write_com(unsigned char com)

{//写液晶命令函数

rs=0;

lcden=0;

P2=com;

delay(3);

lcden=1;

delay(3);

lcden=0;

}

void write_date(unsigned char date)

{//写液晶数据函数

rs=1;

lcden=0;

P2=date;

delay(3);

lcden=1;

delay(3);

lcden=0;

}

void init()

{//初始化函数

unsigned char num;

lcden=0;

rs=0;

write_com(0x38);//1602液晶初始化

write_com(0x0c);

write_com(0x06);

write_com(0x01);

write_com(0x80);

for(num=0;num<15;num++)//写入液晶固定部分显示

{

write_date(table[num]);

delay(3);

}

write_com(0x80+0x40);

for(num=0;num<5;num++)

{

write_date(table1[num]);

delay(3);

}

}

void write_dianya(unsigned char add,unsigned char date)

{//1602液晶刷新时分秒函数4为时,7为分,10为秒

unsigned char bai,shi,ge;

bai=date/100;

shi=date%100/10;

ge=date%10;

write_com(0x80+0x40+add);

write_date(0x30+bai);

write_date(0x30+shi);

write_date(0x30+ge);

}

void main ()

{

init();

TMOD=0x20; //设置定时器1工作方式2

TH1=0xfd;

TL1=0xfd;

TR1=1;

REN=1; //设置串行口工作方式

SM0=0;

SM1=1;

EA=1; //中断设置

ES=1;

while(1)

{

if(flag==1)

{

ES=0;

SBUF=m;

while(!TI);

TI=0;

ES=1;

}

}

}

void ser() interrupt 4

{

RI=0;

m=SBUF;

write_dianya(5,m);

flag=1;

}

可靠的接受程序!!从LZ 的display(a1a10)看出来这程序就不咋样,如果显示函数 还是 用 延时做的,可靠的接受程序给LZ 也是 白瞎……

以下是 UART 驱动程序

/10位异步收发串口通讯驱动——火柴天堂作品-20130119/

/源程序硬件环境:52单片机,110592MHz晶振,定时器1作为波特率发生器,通讯波特率9600 bit/s/

//

#define UART_H

#include"REG52h" //包含52头文件

#include"UARTh" //包含串口头文件

#define th1 0xfa //651us at 110592MHz Fosc for 8bit auto reload mode

static uchar UART_DataR; //串口接收数据寄存器

static uchar bdata Flag=0; //标志位 寄存器

sbit UART_ReFlag=Flag^0; //串口接收标志位 0:无数据 1:新数据

sbit UART_SendFlag=Flag^1; //串口发送标志位 0:空闲中 1:发送中

void UART()interrupt 4 //串口中断函数

{

if(RI) //若串口接收完成

{

RI=0; //清 串口接收溢出位

UART_DataR=SBUF; //将串口收到的数据存进 UART_DataR

UART_ReFlag=TRUE; //串口接收标志位 置位(有新数据)

}

if(TI) //若串口发送完成

{

TI=0; //清 串口发送溢出位

UART_SendFlag=FALSE; //清串口发送标志位(空闲中)

}

}

void UART_Init() //串口初始化函数

{

SCON=0x50; //选择通讯方式:10位异步收发,串口中断使能

PCON=0x80; //波特率倍频

TMOD&=0x0f; //定时器1控制位清0

TMOD|=0x20; //定时器1工作模式2(8位自重装,做波特率发生器)

TH1=th1; //定时器初值

TL1=th1; //定时器初值

TR1=1; //开始计时

ES=1; //允许串口中断

EA=1; //允许系统中断

}

bit UART_SendByte(uchar send_data) //串口发送字节函数,发送内容send_data,返回值:0 *** 作失败,1 *** 作成功

{

if(!UART_SendFlag) //若串口空闲中,则

{

SBUF=send_data; //将发送内容 送到 串口寄存器

UART_SendFlag=TRUE; //置位串口发送标志位(进入忙态)

return TRUE; //返回1, *** 作成功

}

return FALSE; //否则,返回0, *** 作失败

}

uchar ASCII_ToHex(uchar ascii_data) //ASCII 转 Hex 函数

{

uchar hex_data=0; //定义 Hex变量存储转换结果

if(ascii_data>='0' && ascii_data<='9') hex_data=ascii_data-'0'; //若 转换内容为 字符'0-9',则转成对应数字0-9

else if(ascii_data>='a' && ascii_data<='f') hex_data=ascii_data-'a'+10; //若 转换内容为 字符'a-f',则转成数字10-15

else if(ascii_data>='A' && ascii_data<='F') hex_data=ascii_data-'A'+10; //若 转换内容为 字符'A-F',则转成数字10-15

return hex_data; //返回转换结果,非以上字符,不在Hex(0-F)范围内,默认0

}

bit UART_ReadByte(uchar p_data,bit data_mode) //串口读字节函数,返回值0 无数据,1 有数据,将data_mode模式(ASCII_Mode或HEX_Mode)转成Hex结果存到p_data指向地址

{

if(!UART_ReFlag) return FALSE; //若无新数据,则返回 0(无数据)

UART_ReFlag=FALSE; //否则,清 串口接收标志位

if(data_mode==HEX_Mode) p_data=UART_DataR; //Hex模式,将串口接收结果存到p_data指向地址

if(data_mode==ASCII_Mode) p_data=ASCII_ToHex(UART_DataR); //ASCII模式,将串口接收结果转成Hex后,存到p_data指向地址

return TRUE; //返回 1(有数据)

}

串口接收比较好的处理方式如下。

1设定好通讯协议,如包头+长度+数据+校验+包尾,那么中断中每收到一个字节就判断,直到收到包尾为止。这是51时代用得比较多的状态机接收流程。

但如果由于接收中断被嵌套,或干扰等原因导致一帧数据的后部分丢失,就是说接收不到包尾,那么这个状态机如何能自动复位以便接收下一帧?

2串口空闲中断也是用得比较多的一种方法,但是波特率较高的时候,空闲中断的触发时间相应变短,使得接收中断不被打断的要求变高,如果接收中断被耽误了,从而触发空闲中断,也是收不到完整数据。

3定时器中断代替串口空闲中断,这个可以避免串口空闲中断时间不够的问题,因为这个定时器中断可以自己设置。但是一个串口需要搭配一个定时器使用,不爽。

4串口接收只把数据放到缓存,此外不做任何事情。然后在另一个线程不断parse这个缓存,从头开始找其中有没有符合一帧的数据,如果有就是解析,同时将这一帧从缓存中删掉,如果没有就什么也不做。这样的程序就不用管一帧是否结束,可以较好的适应各种收不全、丢数据的问题。

以上就是关于求单片机串口中断接收程序,怎样一次性接受多个字符全部的内容,包括:求单片机串口中断接收程序,怎样一次性接受多个字符、C51单片机如何从PC机串口接收字符串、我需要一个程序,51单片机串口接受到一帧数据并把这一帧数据赋值到一个数组中。等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/10161377.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-05
下一篇 2023-05-05

发表评论

登录后才能评论

评论列表(0条)

保存