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的显示程序是用来验证是否通信成功,这部分你可作为参考。这部分你大可用小灯显示程序来替代。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)