例一
●题目
●原理图
●Method
●Method 1
这道例题是来自丁向荣老师的《单片微机原理与接口技术》上的演示例题。
同时,也给出了代码,同时在老师的网课中也进行了演示,代码如下:
#include<STC15.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar temp;
uchar temp1;
void Delay100ms() //@11.0592MHz
{
unsigned char i, j, k;
_nop_();
_nop_();
i = 5;
j = 52;
k = 195;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit(void) //[email protected]
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xE0; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
//-----------------------------------IO口初始化函数-----------------------------//
void GPIO(void)
{
P0M1=0;
P0M0=0;
P1M1=0;
P1M0=0;
P2M1=0;
P2M0=0;
P3M1=0;
P3M0=0;
P4M1=0;
P4M0=0;
P5M1=0;
P5M0=0;
}
void main()
{
GPIO(); //调用IO初始化函数
UartInit();//调用串行口1初始化函数
ES=1;
EA=1;
while(1)
{
temp=P3;
temp=temp&0X0C; //读P33,P32引脚的输入状态值
SBUF=temp; //串行发送
while(TI==0); //检测穿行发送是否结束
TI=0;
Delay100ms(); //设置串行发送间隔
}
}
void uart_isr() interrupt 4 //串行接收中断函数
{
if(RI==1)
{
RI=0;
temp1=SBUF;
switch(temp1&0x0c)
{
case 0x00:P4=0XFE;break;
case 0x04:P4=0XFD;break;
case 0x08:P4=0XFB;break;
default:P4=0XF7;break;
}
}
}
但实际的运行结果是:双机串行异步通信只能发送一次数据,即刚上电时刻自锁开关的状态值,之后无论开关状态如何,数据都不能继续发送。(没有尝试过其他的热启动复位)。网上有说是发送中断标志位TI或(和)接收中断标志位RI实际上没有清零的,也没有解决。
●Method 2
参照官方例程和DL的代码,修改出了一个暂且在仿真中能正常使用的的程序(区别以及原因ing):
#include<STC15.H>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar temp; //串行发送临时传递参数
uchar temp1; //串行接收临时传递参数
uchar busy; //正忙标志(数据正在传输)
void Delay100ms(); //@11.0592MHz
void GPIO(void); //IO口初始化函数
void UartInit(void); //[email protected] 串行口1初始化函数
void SendData(void); //发送串口数据 (串行发送采用查询方式)
void main()
{
GPIO();
UartInit();
ES=1; //允许串行口1中断
EA=1; //总中断允许控制位
while(1)
{
SendData(); //发送串口数据
}
}
//-----------------------------------IO口初始化函数-----------------------------//
void GPIO(void)
{
P0M1=0;
P0M0=0;
P1M1=0;
P1M0=0;
P2M1=0;
P2M0=0;
P3M1=0;
P3M0=0;
P4M1=0;
P4M0=0;
P5M1=0;
P5M0=0;
}
//-------------------------------------串行口1初始化函数-----------------------------//
void UartInit(void) //[email protected]
{
SCON = 0x50; //8位数据,可变波特率
AUXR |= 0x40; //定时器1时钟为Fosc,即1T
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
TMOD &= 0x0F; //设定定时器1为16位自动重装方式
TL1 = 0xE0; //设定定时初值
TH1 = 0xFE; //设定定时初值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
}
//------------------------串行接收中断函数 (串行接收采用中断方式)---------------------//
void uart_isr() interrupt 4
{
if(RI)
{
RI=0; //清除RI位
temp1=SBUF;
switch(temp1&0x0c)
{
case 0x00:P4=0XFE;break;
case 0x04:P4=0XFD;break;
case 0x08:P4=0XFB;break;
default:P4=0XF7;break;
}
}
if(TI)
{
TI = 0; //清除TI位
busy = 0; //清零正忙标志
}
}
//-----------------------发送串口数据(串行发送采用查询方式)-------------------------------//
void SendData(void)
{
while(busy); //等待前面的数据发送完成
temp = P3; //
temp=temp&0X0C; //读取P33,P32引脚的输入状态值
busy = 1; //将正忙标志置1,
SBUF = temp; //串行发送
}