51单片机如何进行多字节串口接收!!!

51单片机如何进行多字节串口接收!!!,第1张

串口的收发可以用查询和中断两个办法来实现。

1、查询方法更适合于半双工机制,编写的思路简单,程序结构简单,在全双工通信中易出问题。

2、中断方法则更高效。你的程序把两种方法混搭使用,容易出错。

以你的程序为例,一旦收到首个23H字符,就停止在中断服务中for循环里面等待5个剩余字符。假设传感器只发了3个字符,你的程序就停止在for循环里面。

以你的程序为例改进,在中断服务接收中,每次接收中断只收1个字符,完成后退出。

void uart_interrupt(void) interrupt 4 using 0

{

static unsigned char i=0;

unsigned char buf;

if(RI==1)

{

buf=SBUF;

switch(i)

{

case 0:

if(buf==0x23)i=1;

break;

case 1:

case 2:

case 3:

case 4:

case 5:

buffer[i-1]=buf;

i++;

if(buf==0x23)

i=1;

if(i==5)

{

do_something_here(buffer);

i=0;

}

break;

default: i=0;break;

}

RI = 0; //RI清零

}

if(TI==1) TI=0; //TI清零

}

这样改符合你的思维习惯吗?实际串口协议解析与协议密切相关,用状态机做比较好。程序中i把它变成状态机的状态,思考一下,改改程序更佳。

ORG 0000H

SJMP 0050H

ORG 0023H

LJMP S_INT

TAB:DB 20H,49H,20H,47H,45H,54H,20H,'NULL'

ORG 0050H

MOV TMOD,#20H

MOV TH1,#0FDH

MOV TL1,#0FDH

SETB TR1

SETB SM1

CLR SM0

SETB EA

SETB ES

MOV R0,#30H

MOV A,#1H

MAIN:SETB REN

ACALL DELAY

JNZ MAIN

MOV R2,#0

MOV DPTR,#TAB

MOV R7,#7

SEND:MOV A,R2

MOVC A,@A+DPTR

CLR ES

MOV SBUF,A

JNB TI,$

CLR TI

INC R2

DJNZ R7,SEND

MOV R0,#30H

SHOW:MOV A,@R0

MOV SBUF,A

JNB TI,$

CLR TI

INC R0

CJNE A,#40H,SHOW

SETB ES

MOV A,#1

MOV R0,#30H

SJMP MAIN

S_INT:CLR RI

MOV A,SBUF

MOV @R0,A

CJNE A,#40H,NEXT

MOV A,#0

NEXT:INC R0

RETI

DELAY:MOV 7DH,#200

LOOP1:MOV 7EH,#40

DJNZ 7EH,$

DJNZ 7DH,LOOP1

RET

END

这个是方式一的

串行发送程序 Txasm :

PCON, #00H ;; 波特率不倍增

SETB TR1 ;; 启动定时器T1

MOV IE, #0 ;; 禁止任何中断

CALL DLY125 ;; 延时125ms

;;--------------------------------------------

T_X: ;; 透传发送字串

ACALL DSPLED ;; P20控制LED闪亮

MOV R3, #4 ;; 待发送字符个数

MOV DPTR, #TAB_TX ;; 数据表首址

TX_LP1: CLR A

MOVC A, @A+DPTR ;; A←数据表的1个字符

CLR TI ;; TI清零,允许发送

MOV SBUF,A ;; 发送1个字符

JNB TI, $ ;; 等待1个字符帧发送结束

DJNZ R3, TX_next

CALL DLY500 ;; 延时500ms

SJMP T_X ;; 重复发送

TX_next: ;; 发送另一字符

INC DPTR ;; 数据表指针移动

SJMP TX_LP1

;;--------------------------------------------

DSPLED: ;;开机或复位,P20控制LED闪亮6遍

MOV R2, #6 ;; 循环次数

LEDLP1: CLR P20 ;; LED亮

CALL DLY125 ;; 延时125ms

SETB P20 ;; LED灭

CALL DLY125

DJNZ R2,LEDLP1 ;; 循环

RET

;;----------------------------------------------

DLY125: ;; 延时125ms

DLY125A: MOV R5,#250

DLY125B: MOV R6,#250

DJNZ R6,$

DJNZ R5,DLY125B

RET

;; 2502502μs=125 000μs =125ms

;;----------------------------------------------

DLY500: ;; 延时500ms

MOV R7,#4

DLY500A: MOV R6,#250

DLY500B: MOV R5,#250

DJNZ R5,$

DJNZ R6,DLY500B

DJNZ R7,DLY500A

RET

;; 42502502μs=500 000μs =500ms

;;-------------------------------------------------

TAB_TX: DB 38H,30H,35H,31H,

;; 8 0 5 1

;;----------------------------------------------

END

#include <REG52H>

#define uchar unsigned char

#define uint unsigned int

sbit ring=P3^7;

sbit CASE1=P2^0;

sbit CASE2=P2^1;

sbit CASE3=P2^2;

sbit CASE4=P2^3;

uchar se=0,re=0;

uchar temp=0;

void wait(uint cnt)

{

while(--cnt);

}

//串口发送程序

void send(uchar se)

{

SBUF=se; //发送数据

while(TI == 0);

TI = 0;

}

//串口接收程序

uchar receive(void)

{

re=SBUF; //接收数据

while(RI==0);

RI=0;

return re;

}

//串口初始化

void sinti(void)

{

SCON = 0x50;

TMOD |= 0x20;

TH1 = 0xFD;

TR1 = 1;

EA = 1;

ES = 1;

}

void delay(int cnt)

{

while(--cnt);

}

//主程序

int main (void)

{

int i;

sinti(); //串口初始化程序

ring=1;

while(1)

{

while (1)

{

if(CASE1==0)

{

send('a');

ring=0;

break;

}

if(CASE2==0)

{

send('b');

ring=0;

break;

}

if(CASE3==0)

{

send('c');

ring=0;

break;

}

if(CASE4==0)

{

send('d');

ring=0;

break;

}

}

if(ring==0)

{

wait(60000);

ring=1;

}

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

}

}

//串口中断程序

void UART_SER (void) interrupt 4 //串行中断服务程序

{

if(RI) //判断是接收中断产生

{

RI=0; //标志位清零

temp=SBUF;

}

if(TI) //如果是发送标志位,清零

TI=0;

}

while(RI); //接收数据,若字符未接受完,一直等待

{

RI=0;

temp[num]=SBUF;

num++;

endmark=1;

/

假如你波特率为9600,那么接收一个位时间大概为100us,假如你的单片机执行一条语句1us,

那么你用查询的方式有可能会是你只接收到第一个字节后,就会推出这个while循环

/

}

建议你用串口中断的方式来接收多个字节的数据,下面是我之前写过的程序

/

串口中断函数

ReData[]: 里是一个字节类型的数组,这里一次只接收4个字节数据

/

void Usart_isr() interrupt 4 using 2

{

if(RI)

{

ReData[ReceiveCount++] = SBUF;

if(ReceiveCount > 3)

{

ReceiveCount = 0;

}

RI = 0;

}

}

#include <AT89X51H>//单片机51头文件,存放着单片机的寄存器

unsigned char dat; //用于存储单片机接收发送缓冲寄存器SBUF里面的内容

sbit gewei=P2^2; //个位选通定义

sbit shiwei=P2^3; //十位选通定义

unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,0x77,0x7c,0x39,0x5e,0x79,0x71};

//{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x67,};// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9

void Delay(unsigned int tc) //延时程序

{

while( tc != 0 )

{unsigned int i;

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

tc--;}

}

void LED() //LED显示接收到的数据

{

shiwei=0;

P0=~table[dat/16];

Delay(8);

shiwei=1;

gewei=0;

P0=~table[dat%16];

Delay(5);

gewei=1;

}

void Init_Com(void)//功能:串口初始化,波特率9600,方式1

{

TMOD = 0x20;

PCON = 0x00;

SCON = 0x50;

TH1 = 0xFd;

TL1 = 0xFd;

TR1 = 1;

}

void main()//主程序功能:实现接收数据并把接收到的数据原样发送回去///////

{

Init_Com();//串口初始化

// P1=0xf0;

while(1)

{

if ( RI ) //扫描判断是否接收到数据,

{

dat = SBUF; //接收数据SBUF赋与dat

RI=0; //RI清零。

SBUF = dat; //在原样把数据发送回去

}

LED(); //显示接收到的数据

}

}

以上就是关于51单片机如何进行多字节串口接收!!!全部的内容,包括:51单片机如何进行多字节串口接收!!!、51单片机汇编语言写串口程序、两个51单片机串口通信程序等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

原文地址: https://outofmemory.cn/zz/9862150.html

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

发表评论

登录后才能评论

评论列表(0条)

保存