51单片机的串行口按工作方式1进行串行数据通信,假定波特率为2400bs编写程序

51单片机的串行口按工作方式1进行串行数据通信,假定波特率为2400bs编写程序,第1张

ORG 0000H

AJMP MAIN上电,转向主程序

ORG 0023H串行口的中断入口地址

AJMP SERVE 转向中断服务程序

ORG 0040H主程序

MAIN: MOV SP,#60H 设置堆栈指针

MOV SCON ,#50H

MOV PCON ,#00H

MOV TMOD,#20H

MOV TH1,#0F3H

MOV TL1,#0F3H

SETB TR1

MOV R0 ,#20H 置发送数据区首地址

MOV R1 ,#40H ;置接收数据区首地址

MOV R7 ,#10H ;置发送字节长度

MOV R6 ,#10H ;置接收字节长度

SETB ES允许串行口中断

SETB EACPU允许中断

MOV A ,@R0 ;取第一个数据发送

MOV SBUF ,A发送第一个数据

SJMP $ ;等待中断

SERVE: JNB RI ,SEND TI=1,为发送中断

CLR RI

MOV A ,SBUF 读出接收缓冲区内容

MOV @R1 ,A读入接收缓冲区

DJNZ R6 ,L1 判断数据块发送完否

SJMP L2数据块接收完,转L2

L1:INC R1修改数据区指针

L2:RETI中断返回

SEND:

CLR TI清除发送中断标志

DJNZ R7 ,L3 判断数据块发送完否

SJMP L4数据块接收完,转L4

L3: MOV A ,@R0取数据发送

MOV SBUF ,A发送数据

INC R0修改数据地址

L4:

RETI中断返回

END

#include <reg52.h>

#include <intrins.h>

#define uchar unsigned char

#define uint unsigned int

sbit LCD_RS = P2^0

sbit LCD_RW = P2^1

sbit LCD_EN = P2^2

#define delayNOP(){_nop_()_nop_()_nop_()_nop_()}

uchar data RXDdata[ ] = {0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20,

0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20 }

uchar temp,buf,m,count

bit playflag=0

uchar code cdis1[ ] = {" SERILA TRANFER "}

uchar code cdis2[ ] = {""}

/**********************************************************

延时子程序

**********************************************************/

char code SST516[3] _at_ 0x003b

void delay1(uint ms)

{

uchar k

while(ms--)

{

for(k = 0k <120k++)

}

}

/******************************************************************/

/**/

/*检查LCD忙状态 */

/*lcd_busy为1时,忙,等待。lcd-busy为0时,闲,可写指令与数据。 */

/**/

/******************************************************************/

bit lcd_busy()

{

bit result

LCD_RS = 0

LCD_RW = 1

LCD_EN = 1

delayNOP()

result = (bit)(P0&0x80)

LCD_EN = 0

return(result)

}

/*******************************************************************/

/* */

/*写指令数据到LCD */

/*RS=L,RW=L,E=高脉冲,D0-D7=指令码。 */

/* */

/*******************************************************************/

void lcd_wcmd(uchar cmd)

{

while(lcd_busy())

LCD_RS = 0

LCD_RW = 0

LCD_EN = 0

_nop_()

_nop_()

P0 = cmd

delayNOP()

LCD_EN = 1

delayNOP()

LCD_EN = 0

}

/*******************************************************************/

/* */

/*写显示数据到LCD */

/*RS=H,RW=L,E=高脉冲,D0-D7=数据。 */

/* */

/*******************************************************************/

void lcd_wdat(uchar dat)

{

while(lcd_busy())

LCD_RS = 1

LCD_RW = 0

LCD_EN = 0

P0 = dat

delayNOP()

LCD_EN = 1

delayNOP()

LCD_EN = 0

}

/*******************************************************************/

/* */

/* LCD初始化设定 */

/* */

/*******************************************************************/

void lcd_init()

{

delay1(15)

lcd_wcmd(0x01) //清除LCD的显示内容

lcd_wcmd(0x38) //16*2显示,5*7点阵,8位数据

delay1(5)

lcd_wcmd(0x38)

delay1(5)

lcd_wcmd(0x38)

delay1(5)

lcd_wcmd(0x0c) //开显示,显示光标,光标闪烁

delay1(5)

lcd_wcmd(0x01) //清除LCD的显示内容

delay1(5)

}

/*******************************************************************/

/* */

/* 设定显示位置 */

/* */

/*******************************************************************/

void lcd_pos(uchar pos)

{

lcd_wcmd(pos | 0x80) //数据指针=80+地址变量

}

/*********************************************************

发送数据函数

*********************************************************/

void senddata(uchar dat)

{

SBUF =dat

while(!TI)

TI = 0

}

/*********************************************************

串行中断服务函数

*********************************************************/

void serial() interrupt 4

{

ES = 0 //关闭串行中断

RI = 0 //清除串行接受标志位

buf = SBUF //从串口缓冲区取得数据

playflag=1

switch(buf)

{

case 0x31: senddata('X')break //接受到1,发送字符'W'给计算机

case 0x32: senddata('L')break //接受到2,发送字符'I'给计算机

case 0x33: senddata('1')break //接受到3,发送字符'L'给计算机

case 0x34: senddata('0')break //接受到4,发送字符'L'给计算机

case 0x35: senddata('0')break //接受到5,发送字符'A'给计算机

case 0x36: senddata('0')break //接受到5,发送字符'R'给计算机

default:senddata(buf)break //接受到其它数据,将其发送给计算机

}

if(buf!=0x0D)

{

if(buf!=0x0A)

{

temp =buf

if(count<16)

{

RXDdata[count]=temp

count++

}

}

}

ES = 1 //允许串口中断

}

/*********************************************************

数据显示函数

*********************************************************/

void play()

{

if(playflag)

{

lcd_pos(0x40) //设置位置为第二行

for(m=0m<16m++)

lcd_wdat(cdis2[m]) //清LCD1602第二行

for(m=0m<16m++)

{

lcd_pos(0x40+m) //设置显示位置为第二行

lcd_wdat(RXDdata[m]) //显示字符

}

playflag=0

count=0x00

for(m=0m<16m++)

RXDdata[m]=0x20//清显存单元

}

}

/*********************************************************

主函数

*********************************************************/

void main(void)

{

P0 = 0xff

P2 = 0xff

SCON=0x50 //设定串口工作方式

PCON=0x00 //波特率不倍增

TMOD=0x20 //定时器1工作于8位自动重载模式, 用于产生波特率

EA=1

ES = 1 //允许串口中断

TL1=0xf3

TH1=0xf3//波特率2400

TR1=1

lcd_init()

lcd_pos(0x00) //设置显示位置为第一行

for(m=0m<16m++)

lcd_wdat(cdis1[m]) //显示字符

lcd_pos(0x40) //设置显示位置为第二行

for(m=0m<16m++)

lcd_wdat(cdis2[m]) //显示字符

while(1)

{

play()

}

}

这个串口通信程序在我的开发版上已经全部验证通过,你可以根据实际,攸 改里面某些参数,满足你自己的需要就行。

比如你你点亮小灯,这部分你只可在相应位置添加代码即可。单片机都是51的。

其中1602的显示程序是用来验证是否通信成功,这部分你可作为参考。这部分你大可用小灯显示程序来替代。


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

原文地址: http://outofmemory.cn/yw/7942505.html

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

发表评论

登录后才能评论

评论列表(0条)

保存